From e9d2bc3f05cfcd3da9e1fa7b0a878c6b374c58c7 Mon Sep 17 00:00:00 2001 From: JoshuaMoelans <60878493+JoshuaMoelans@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:28:42 +0100 Subject: [PATCH 1/5] add event_id to logs envelope - this avoids collisions with the nil-event_id-envelope for sessions on Crashpad --- src/sentry_envelope.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sentry_envelope.c b/src/sentry_envelope.c index 72e6de221..77da3371b 100644 --- a/src/sentry_envelope.c +++ b/src/sentry_envelope.c @@ -459,6 +459,10 @@ sentry__envelope_add_logs(sentry_envelope_t *envelope, sentry_value_t logs) return NULL; } + sentry_uuid_t event_id; + sentry__ensure_event_id(logs, &event_id); + sentry__envelope_set_event_id(envelope, &event_id); + sentry__envelope_item_set_header( item, "type", sentry_value_new_string("log")); sentry__envelope_item_set_header(item, "item_count", From 77d701e04717d7fdb6de8acc571185c90f349e1b Mon Sep 17 00:00:00 2001 From: JoshuaMoelans <60878493+JoshuaMoelans@users.noreply.github.com> Date: Thu, 18 Dec 2025 12:15:21 +0100 Subject: [PATCH 2/5] add test for logs+session on Crashpad --- tests/test_integration_crashpad.py | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/test_integration_crashpad.py b/tests/test_integration_crashpad.py index 6bec1c279..15f72bc58 100644 --- a/tests/test_integration_crashpad.py +++ b/tests/test_integration_crashpad.py @@ -614,6 +614,38 @@ def test_crashpad_logs_on_crash(cmake, httpserver): assert_logs(logs_envelope, 1) +@pytest.mark.skipif(not flushes_state, reason="test needs state flushing") +def test_crashpad_logs_and_session_on_crash(cmake, httpserver): + tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "crashpad"}) + + env = dict(os.environ, SENTRY_DSN=make_dsn(httpserver)) + httpserver.expect_oneshot_request("/api/123456/minidump/").respond_with_data("OK") + httpserver.expect_request("/api/123456/envelope/").respond_with_data("OK") + + with httpserver.wait(timeout=10) as waiting: + run( + tmp_path, + "sentry_example", + ["log", "enable-logs", "capture-log", "crash", "start-session"], + expect_failure=True, + env=env, + ) + + assert waiting.result + + run(tmp_path, "sentry_example", ["log", "no-setup"], env=env) + + # we expect 1 envelope with the log, 1 for the crash, and 1 for the session + assert len(httpserver.log) == 3 + logs_request, multipart = split_log_request_cond(httpserver.log, is_logs_envelope) + logs = logs_request.get_data() + + logs_envelope = Envelope.deserialize(logs) + + assert logs_envelope is not None + assert_logs(logs_envelope, 1) + + def test_disable_backend(cmake, httpserver): tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "crashpad"}) From 9524e02f1b19ce228a5abe7cb2fc332176bc9a04 Mon Sep 17 00:00:00 2001 From: JoshuaMoelans <60878493+JoshuaMoelans@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:28:56 +0100 Subject: [PATCH 3/5] extract session/logs from request --- tests/__init__.py | 15 +++++++++++++++ tests/test_integration_crashpad.py | 11 ++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index 36fb648e2..710405bf0 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -70,6 +70,21 @@ def split_log_request_cond(httpserver_log, cond): ) +def extract_request(httpserver_log, cond): + """ + Extract a request matching the condition from the httpserver log. + Returns (matching_request, remaining_log_entries) + + The remaining_log_entries preserves the original format so it can be + chained with subsequent extract_request calls. + """ + for i, entry in enumerate(httpserver_log): + if cond(entry[0].get_data()): + others = [httpserver_log[j] for j in range(len(httpserver_log)) if j != i] + return (entry[0], others) + return (None, httpserver_log) + + def run(cwd, exe, args, expect_failure=False, env=None, **kwargs): if env is None: env = dict(os.environ) diff --git a/tests/test_integration_crashpad.py b/tests/test_integration_crashpad.py index 15f72bc58..0a501dd7d 100644 --- a/tests/test_integration_crashpad.py +++ b/tests/test_integration_crashpad.py @@ -11,6 +11,7 @@ run, Envelope, split_log_request_cond, + extract_request, is_session_envelope, is_logs_envelope, is_feedback_envelope, @@ -637,14 +638,18 @@ def test_crashpad_logs_and_session_on_crash(cmake, httpserver): # we expect 1 envelope with the log, 1 for the crash, and 1 for the session assert len(httpserver.log) == 3 - logs_request, multipart = split_log_request_cond(httpserver.log, is_logs_envelope) - logs = logs_request.get_data() - logs_envelope = Envelope.deserialize(logs) + logs_request, remaining = extract_request(httpserver.log, is_logs_envelope) + session_request, remaining = extract_request(remaining, is_session_envelope) + multipart = remaining[0][0] # The crash/minidump + logs_envelope = Envelope.deserialize(logs_request.get_data()) assert logs_envelope is not None assert_logs(logs_envelope, 1) + session_envelope = Envelope.deserialize(session_request.get_data()) + assert session_envelope is not None + def test_disable_backend(cmake, httpserver): tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "crashpad"}) From e8d57fea2e2eb17ff59483d7f722d744799e717b Mon Sep 17 00:00:00 2001 From: JoshuaMoelans <60878493+JoshuaMoelans@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:00:32 +0100 Subject: [PATCH 4/5] remove event_id from logs --- src/sentry_envelope.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sentry_envelope.c b/src/sentry_envelope.c index 77da3371b..72e6de221 100644 --- a/src/sentry_envelope.c +++ b/src/sentry_envelope.c @@ -459,10 +459,6 @@ sentry__envelope_add_logs(sentry_envelope_t *envelope, sentry_value_t logs) return NULL; } - sentry_uuid_t event_id; - sentry__ensure_event_id(logs, &event_id); - sentry__envelope_set_event_id(envelope, &event_id); - sentry__envelope_item_set_header( item, "type", sentry_value_new_string("log")); sentry__envelope_item_set_header(item, "item_count", From 43ebf2015748e00da0d13a38bf6a061a4bd9964c Mon Sep 17 00:00:00 2001 From: JoshuaMoelans <60878493+JoshuaMoelans@users.noreply.github.com> Date: Mon, 29 Dec 2025 11:53:30 +0100 Subject: [PATCH 5/5] generate random UUID for envelopes without event_id --- src/sentry_database.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sentry_database.c b/src/sentry_database.c index 81646410f..32cf8ba57 100644 --- a/src/sentry_database.c +++ b/src/sentry_database.c @@ -103,6 +103,13 @@ static bool write_envelope(const sentry_path_t *path, const sentry_envelope_t *envelope) { sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope); + + // Generate a random UUID for the filename if the envelope has no event_id + // this avoids collisions on NIL-UUIDs + if (sentry_uuid_is_nil(&event_id)) { + event_id = sentry_uuid_new_v4(); + } + char *envelope_filename = sentry__uuid_as_filename(&event_id, ".envelope"); if (!envelope_filename) { return false;