Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
fbed0e2
initial queue attempt
JoshuaMoelans Aug 8, 2025
234bbb6
add timer
JoshuaMoelans Aug 8, 2025
5815c1e
prototype double buffer approach
JoshuaMoelans Aug 8, 2025
914514d
update logs unit tests for batching
JoshuaMoelans Aug 8, 2025
d1988a8
replace timer with bgworker
JoshuaMoelans Aug 11, 2025
d07ef33
add first integration tests
JoshuaMoelans Aug 11, 2025
b3d624c
Merge branch 'joshua/feat/logs' into joshua/feat/logs_batching
JoshuaMoelans Aug 11, 2025
b2dbe18
update example.c with correct log thread amounts
JoshuaMoelans Aug 11, 2025
ccd88d2
cleanup
JoshuaMoelans Aug 12, 2025
845f5bc
add wait for 'adding' logs in flush logic
JoshuaMoelans Aug 12, 2025
ad88a88
go back to single queue for performance testing
JoshuaMoelans Aug 12, 2025
28d4a50
add time checks
JoshuaMoelans Aug 12, 2025
3d360cb
add ToDos + cleanup sentry_value_t cloning
JoshuaMoelans Aug 13, 2025
f067959
initial attempt
JoshuaMoelans Aug 13, 2025
91b2f7f
cond_wait for timer + 'adding' spinlock
JoshuaMoelans Aug 13, 2025
c0395ae
add sleep for tests
JoshuaMoelans Aug 13, 2025
ea3fffb
add sleep for tests
JoshuaMoelans Aug 13, 2025
98d6c21
force flush before attempting timer_worker shutdown
JoshuaMoelans Aug 13, 2025
e1e2a1b
add proper cond_wait for 'adding' counter
JoshuaMoelans Aug 14, 2025
cb834f7
revert to manual flush on shutdown instead of timer thread flush
JoshuaMoelans Aug 14, 2025
d320067
add separate timer_stop atomic
JoshuaMoelans Aug 14, 2025
c85f685
cleanup + replace 'adding' cond_wait by pure spinlock
JoshuaMoelans Aug 14, 2025
3c28646
change bgworker for simpler thread implementation
JoshuaMoelans Aug 14, 2025
651ca04
cleanup
JoshuaMoelans Aug 26, 2025
02cea90
fix memleak
JoshuaMoelans Aug 26, 2025
3907d90
fixes
JoshuaMoelans Aug 27, 2025
d8bbb23
cleanup
JoshuaMoelans Aug 27, 2025
b8c110e
cleanup
JoshuaMoelans Aug 27, 2025
6f2be36
windows fixes
JoshuaMoelans Aug 27, 2025
394c492
update shutdown order
JoshuaMoelans Aug 27, 2025
8da409e
fixes
JoshuaMoelans Aug 27, 2025
ed9176b
explicit check to stop timer task
JoshuaMoelans Aug 27, 2025
208952b
windows cleanup
JoshuaMoelans Aug 28, 2025
b34b5c8
loosen threaded test assertion for CI
JoshuaMoelans Aug 29, 2025
b63d7e4
add continue for unexpected logs flush trigger instead of attempting …
JoshuaMoelans Aug 29, 2025
6d30ff1
Windows re-add condition variable trigger case
JoshuaMoelans Sep 1, 2025
978abfb
feat(logs): add `before_send_log` (#1355)
JoshuaMoelans Sep 8, 2025
165c8f2
fix ownership issues in single buffer batching (#1362)
supervacuus Sep 8, 2025
210f959
batching double buffered (#1365)
supervacuus Sep 11, 2025
f022d1e
add flush retry for missed flush requests
JoshuaMoelans Sep 11, 2025
cdad215
move flush retry into flush function
JoshuaMoelans Sep 12, 2025
c405106
add docs
JoshuaMoelans Sep 12, 2025
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
82 changes: 60 additions & 22 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 @@ -395,28 +422,39 @@ main(int argc, char **argv)

// TODO incorporate into test
if (sentry_options_get_enable_logs(options)) {
sentry_log_warn(
"This is a big number %" PRIu64, 18446744073709551615ULL);
sentry_log_warn("This is a medium number as unsigned %" PRIu64,
9007199254740991ULL);
sentry_log_warn(
"This is a medium number as signed %" PRId64, 9007199254740991LL);
sentry_log_trace("We log it up %i%%, %s style", 100, "trace");
sentry_log_debug("We log it up %i%%, %s style", 100, "debug");
sentry_log_info("We log it up %i%%, %s style", 100, "info");
sentry_log_warn("We log it up %i%%, %s style", 100, "warn");
sentry_log_error("We log it up %i%%, %s style", 100, "error");
sentry_log_fatal("We log it up %i%%, %s style", 100, "fatal");

// Test the logger with various parameter types
sentry_log_info(
"API call to %s completed in %d ms with %f success rate",
"/api/products", 2500, 0.95);

sentry_log_warn("Processing %d items, found %u errors, pointer: %p",
100, 5u, (void *)0x12345678);

sentry_log_error("Character '%c' is invalid", 'X');
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")) {
Expand Down
4 changes: 4 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 @@ -324,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
5 changes: 4 additions & 1 deletion src/sentry_envelope.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,9 +420,12 @@ sentry__envelope_add_logs(sentry_envelope_t *envelope, sentry_value_t logs)
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(logs)));
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;
}
Expand Down
Loading
Loading