diff --git a/CHANGELOG.md b/CHANGELOG.md index c22c7f232..806f32fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +**Features**: + +- Add logs flush on `sentry_flush()`. ([#1434](https://github.com/getsentry/sentry-native/pull/1434)) + ## 0.12.0 **Breaking changes**: diff --git a/src/sentry_core.c b/src/sentry_core.c index 85b6185ed..d07655169 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -314,6 +314,9 @@ sentry_flush(uint64_t timeout) { int rv = 0; SENTRY_WITH_OPTIONS (options) { + if (options->enable_logs) { + sentry__logs_force_flush(); + } rv = sentry__transport_flush(options->transport, timeout); } return rv; diff --git a/src/sentry_logs.c b/src/sentry_logs.c index add1d295a..8a38a2de4 100644 --- a/src/sentry_logs.c +++ b/src/sentry_logs.c @@ -904,6 +904,15 @@ sentry__logs_flush_crash_safe(void) SENTRY_DEBUG("crash-safe logs flush complete"); } +void +sentry__logs_force_flush(void) +{ + while (sentry__atomic_fetch(&g_logs_state.flushing)) { + sentry__cpu_relax(); + } + flush_logs_queue(false); +} + #ifdef SENTRY_UNITTEST /** * Wait for the logs batching thread to be ready. diff --git a/src/sentry_logs.h b/src/sentry_logs.h index b25b4fcfe..866dd526c 100644 --- a/src/sentry_logs.h +++ b/src/sentry_logs.h @@ -23,6 +23,8 @@ void sentry__logs_shutdown(uint64_t timeout); */ void sentry__logs_flush_crash_safe(void); +void sentry__logs_force_flush(void); + #ifdef SENTRY_UNITTEST int populate_message_parameters( sentry_value_t attributes, const char *message, va_list args); diff --git a/tests/unit/test_logs.c b/tests/unit/test_logs.c index d28ed72e4..0a3f5ef6a 100644 --- a/tests/unit/test_logs.c +++ b/tests/unit/test_logs.c @@ -287,3 +287,39 @@ SENTRY_TEST(logs_param_types) uint64_t g = 0xDEADBEEFDEADBEEF; test_param_conversion_types("%u %d %f %c %s %p %x", a, b, c, d, e, f, g); } + +SENTRY_TEST(logs_force_flush) +{ + transport_validation_data_t validation_data = { 0, false }; + + SENTRY_TEST_OPTIONS_NEW(options); + sentry_options_set_dsn(options, "https://foo@sentry.invalid/42"); + sentry_options_set_enable_logs(options, true); + + sentry_transport_t *transport + = sentry_transport_new(validate_logs_envelope); + sentry_transport_set_state(transport, &validation_data); + sentry_options_set_transport(options, transport); + + sentry_init(options); + sentry__logs_wait_for_thread_startup(); + + // These should not crash and should respect the enable_logs option + TEST_CHECK_INT_EQUAL(sentry_log_trace("Trace message"), 0); + sentry_flush(5000); + TEST_CHECK_INT_EQUAL(sentry_log_debug("Debug message"), 0); + sentry_flush(5000); + TEST_CHECK_INT_EQUAL(sentry_log_info("Info message"), 0); + sentry_flush(5000); + TEST_CHECK_INT_EQUAL(sentry_log_warn("Warning message"), 0); + sentry_flush(5000); + TEST_CHECK_INT_EQUAL(sentry_log_error("Error message"), 0); + sentry_flush(5000); + TEST_CHECK_INT_EQUAL(sentry_log_fatal("Fatal message"), 0); + sentry_flush(5000); + sentry_close(); + + // Validate results on main thread (no race condition) + TEST_CHECK(!validation_data.has_validation_error); + TEST_CHECK_INT_EQUAL(validation_data.called_count, 6); +} diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index cdce6a715..ac60b374d 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -88,6 +88,7 @@ XX(lazy_attachments) XX(logger_enable_disable_functionality) XX(logger_level) XX(logs_disabled_by_default) +XX(logs_force_flush) XX(logs_param_conversion) XX(logs_param_types) XX(message_with_null_text_is_valid)