Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
# define sleep_s(SECONDS) Sleep((SECONDS) * 1000)
#else

# include <pthread.h>
# include <signal.h>
# include <unistd.h>

Expand Down Expand Up @@ -272,6 +273,32 @@ create_debug_crumb(const char *message)
return debug_crumb;
}

#ifdef SENTRY_PLATFORM_WINDOWS
DWORD WINAPI
log_thread_func(LPVOID lpParam)
{
(void)lpParam;
int LOG_COUNT = 100;
for (int i = 0; i < LOG_COUNT; i++) {
sentry_log_debug(
"thread log %d on thread %lu", i, get_current_thread_id());
}
return 0;
}
#else
void *
log_thread_func(void *arg)
{
(void)arg;
int LOG_COUNT = 100;
for (int i = 0; i < LOG_COUNT; i++) {
sentry_log_debug(
"thread log %d on thread %llu", i, get_current_thread_id());
}
return NULL;
}
#endif

int
main(int argc, char **argv)
{
Expand Down Expand Up @@ -381,6 +408,10 @@ main(int argc, char **argv)
sentry_options_add_view_hierarchy(options, "./view-hierarchy.json");
}

if (has_arg(argc, argv, "enable-logs")) {
sentry_options_set_enable_logs(options, true);
}

sentry_init(options);

if (has_arg(argc, argv, "attachment")) {
Expand All @@ -389,6 +420,43 @@ main(int argc, char **argv)
sentry_attachment_set_content_type(bytes, "application/octet-stream");
}

// TODO incorporate into test
if (sentry_options_get_enable_logs(options)) {
if (has_arg(argc, argv, "logs-timer")) {
for (int i = 0; i < 10; i++) {
sentry_log_info("Informational log nr.%d", i);
}
// sleep >5s to trigger logs timer
sleep_s(6);
// we should see two envelopes make its way to Sentry
sentry_log_debug("post-sleep log");
}
if (has_arg(argc, argv, "logs-threads")) {
// Spawn multiple threads to test concurrent logging
const int NUM_THREADS = 50;
#ifdef SENTRY_PLATFORM_WINDOWS
HANDLE threads[NUM_THREADS];
for (int t = 0; t < NUM_THREADS; t++) {
threads[t]
= CreateThread(NULL, 0, log_thread_func, NULL, 0, NULL);
}
sleep_s(3000);
for (int t = 0; t < NUM_THREADS; t++) {
CloseHandle(threads[t]);
}
#else
pthread_t threads[NUM_THREADS];
for (int t = 0; t < NUM_THREADS; t++) {
pthread_create(&threads[t], NULL, log_thread_func, NULL);
}
sleep_s(3);
for (int t = 0; t < NUM_THREADS; t++) {
pthread_join(threads[t], NULL);
}
#endif
}
}

if (!has_arg(argc, argv, "no-setup")) {
sentry_set_transaction("test-transaction");
sentry_set_level(SENTRY_LEVEL_WARNING);
Expand Down Expand Up @@ -630,6 +698,9 @@ main(int argc, char **argv)
SENTRY_LEVEL_INFO, "my-logger", "Hello World!");
sentry_capture_event(event);
}
if (sentry_options_get_enable_logs(options)) {
sentry_log_debug("logging after scoped transaction event");
}

sentry_transaction_finish(tx);
}
Expand Down
17 changes: 17 additions & 0 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ SENTRY_API char *sentry_value_to_json(sentry_value_t value);
* Sentry levels for events and breadcrumbs.
*/
typedef enum sentry_level_e {
SENTRY_LEVEL_TRACE = -2,
SENTRY_LEVEL_DEBUG = -1,
SENTRY_LEVEL_INFO = 0,
SENTRY_LEVEL_WARNING = 1,
Expand Down Expand Up @@ -1866,6 +1867,22 @@ typedef double (*sentry_traces_sampler_function)(
SENTRY_EXPERIMENTAL_API void sentry_options_set_traces_sampler(
sentry_options_t *opts, sentry_traces_sampler_function callback);

/**
* Enables or disables the structured logging feature.
* When disabled, all calls to sentry_logger_X() are no-ops.
*/
SENTRY_EXPERIMENTAL_API void sentry_options_set_enable_logs(
sentry_options_t *opts, int enable_logs);
SENTRY_EXPERIMENTAL_API int sentry_options_get_enable_logs(
const sentry_options_t *opts);

SENTRY_EXPERIMENTAL_API void sentry_log_trace(const char *message, ...);
SENTRY_EXPERIMENTAL_API void sentry_log_debug(const char *message, ...);
SENTRY_EXPERIMENTAL_API void sentry_log_info(const char *message, ...);
SENTRY_EXPERIMENTAL_API void sentry_log_warn(const char *message, ...);
SENTRY_EXPERIMENTAL_API void sentry_log_error(const char *message, ...);
SENTRY_EXPERIMENTAL_API void sentry_log_fatal(const char *message, ...);

#ifdef SENTRY_PLATFORM_LINUX

/**
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ sentry_target_sources_cwd(sentry
sentry_json.h
sentry_logger.c
sentry_logger.h
sentry_logs.c
sentry_logs.h
sentry_options.c
sentry_options.h
sentry_os.c
Expand Down
5 changes: 5 additions & 0 deletions src/sentry_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "sentry_core.h"
#include "sentry_database.h"
#include "sentry_envelope.h"
#include "sentry_logs.h"
#include "sentry_options.h"
#include "sentry_os.h"
#include "sentry_path.h"
Expand Down Expand Up @@ -161,6 +162,7 @@ sentry_init(sentry_options_t *options)
sentry_close();

sentry_logger_t logger = { NULL, NULL, SENTRY_LEVEL_DEBUG };

if (options->debug) {
logger = options->logger;
}
Expand Down Expand Up @@ -323,6 +325,9 @@ sentry_close(void)
options->backend->shutdown_func(options->backend);
}

// Shutdown logs system before transport to ensure logs are flushed
sentry__logs_shutdown(options->shutdown_timeout);

if (options->transport) {
if (sentry__transport_shutdown(
options->transport, options->shutdown_timeout)
Expand Down
29 changes: 29 additions & 0 deletions src/sentry_envelope.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,35 @@ sentry__envelope_add_transaction(
return item;
}

sentry_envelope_item_t *
sentry__envelope_add_logs(sentry_envelope_t *envelope, sentry_value_t logs)
{
sentry_envelope_item_t *item = envelope_add_item(envelope);
if (!item) {
return NULL;
}

sentry_jsonwriter_t *jw = sentry__jsonwriter_new_sb(NULL);
if (!jw) {
return NULL;
}

sentry__jsonwriter_write_value(jw, logs);
item->payload = sentry__jsonwriter_into_string(jw, &item->payload_len);

sentry__envelope_item_set_header(
item, "type", sentry_value_new_string("log"));
sentry__envelope_item_set_header(item, "item_count",
sentry_value_new_int32((int32_t)sentry_value_get_length(
sentry_value_get_by_key(logs, "items"))));
sentry__envelope_item_set_header(item, "content_type",
sentry_value_new_string("application/vnd.sentry.items.log+json"));
sentry_value_t length = sentry_value_new_int32((int32_t)item->payload_len);
sentry__envelope_item_set_header(item, "length", length);

return item;
}

sentry_envelope_item_t *
sentry__envelope_add_user_report(
sentry_envelope_t *envelope, sentry_value_t user_report)
Expand Down
6 changes: 6 additions & 0 deletions src/sentry_envelope.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ sentry_envelope_item_t *sentry__envelope_add_transaction(
sentry_envelope_item_t *sentry__envelope_add_user_report(
sentry_envelope_t *envelope, sentry_value_t user_report);

/**
* Add a list of logs to this envelope.
*/
sentry_envelope_item_t *sentry__envelope_add_logs(
sentry_envelope_t *envelope, sentry_value_t logs);

/**
* Add a user feedback to this envelope.
*/
Expand Down
5 changes: 3 additions & 2 deletions src/sentry_logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ const char *
sentry__logger_describe(sentry_level_t level)
{
switch (level) {
case SENTRY_LEVEL_TRACE:
return "TRACE ";
case SENTRY_LEVEL_DEBUG:
return "DEBUG ";
case SENTRY_LEVEL_INFO:
Expand All @@ -89,8 +91,7 @@ sentry__logger_describe(sentry_level_t level)
void
sentry__logger_log(sentry_level_t level, const char *message, ...)
{
if (g_logger.logger_level != SENTRY_LEVEL_DEBUG
&& level < g_logger.logger_level) {
if (level < g_logger.logger_level) {
return;
}
sentry_logger_t logger = g_logger;
Expand Down
5 changes: 5 additions & 0 deletions src/sentry_logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const char *sentry__logger_describe(sentry_level_t level);

void sentry__logger_log(sentry_level_t level, const char *message, ...);

#define SENTRY_TRACEF(message, ...) \
sentry__logger_log(SENTRY_LEVEL_TRACE, message, __VA_ARGS__)

#define SENTRY_TRACE(message) sentry__logger_log(SENTRY_LEVEL_TRACE, message)

#define SENTRY_DEBUGF(message, ...) \
sentry__logger_log(SENTRY_LEVEL_DEBUG, message, __VA_ARGS__)

Expand Down
Loading
Loading