diff --git a/CHANGELOG.md b/CHANGELOG.md index cb4d2f51c..7eaa1b765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,12 @@ **Features**: -- Add runtime API to query user consent requirement ([#1443](https://github.com/getsentry/sentry-native/pull/1443)) +- Add custom attributes API for logs. When `logs_with_attributes` is set to `true`, treats the first `varg` passed into `sentry_logs_X(message,...)` as a `sentry_value_t` object of attributes. ([#1435](https://github.com/getsentry/sentry-native/pull/1435)) +- Add runtime API to query user consent requirement. ([#1443](https://github.com/getsentry/sentry-native/pull/1443)) +- Add logs flush on `sentry_flush()`. ([#1434](https://github.com/getsentry/sentry-native/pull/1434)) ## 0.12.1 -**Features**: - -- Add custom attributes API for logs. When `logs_with_attributes` is set to `true`, treats the first `varg` passed into `sentry_logs_X(message,...)` as a `sentry_value_t` object of attributes. ([#1435](https://github.com/getsentry/sentry-native/pull/1435)) - **Fixes**: - PS5/Switch compilation regression (`sentry__process_spawn` signature change) ([#1436](https://github.com/getsentry/sentry-native/pull/1436)) diff --git a/examples/example.c b/examples/example.c index d6902fb41..32fbc5587 100644 --- a/examples/example.c +++ b/examples/example.c @@ -508,8 +508,6 @@ main(int argc, char **argv) return EXIT_FAILURE; } - sentry_get_crashed_last_run(); - if (has_arg(argc, argv, "log-attributes")) { sentry_value_t attributes = sentry_value_new_object(); sentry_value_t attr = sentry_value_new_attribute( diff --git a/src/sentry_core.c b/src/sentry_core.c index a5f8c6004..16b3146f0 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 88377ca10..c8cbfff75 100644 --- a/src/sentry_logs.c +++ b/src/sentry_logs.c @@ -932,6 +932,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 3dc546d40..f90f59f27 100644 --- a/tests/unit/test_logs.c +++ b/tests/unit/test_logs.c @@ -288,6 +288,42 @@ SENTRY_TEST(logs_param_types) 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); +} + SENTRY_TEST(logs_custom_attributes_with_format_strings) { transport_validation_data_t validation_data = { 0, false }; diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index 84f74f6c6..f8fa3c920 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -90,6 +90,7 @@ XX(logger_enable_disable_functionality) XX(logger_level) XX(logs_custom_attributes_with_format_strings) XX(logs_disabled_by_default) +XX(logs_force_flush) XX(logs_param_conversion) XX(logs_param_types) XX(message_with_null_text_is_valid)