From 8dd2843c18014c8e9712768ee04e51318440da98 Mon Sep 17 00:00:00 2001 From: lukeocodes Date: Sat, 9 May 2026 08:13:13 +0100 Subject: [PATCH] fix(telemetry): explicitly start session after init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #71 enabled auto_session_tracking=True expecting sentry-sdk to start sessions automatically. It doesn't — in sentry-sdk 2.x, that flag only tells *integrations* (Flask/Django/ASGI request handlers) to wrap each request in a session. For CLIs there is no integration that knows when an 'application session' begins, so no session is ever created and the atexit flush has nothing to send. Confirmed by SENTRY_DEBUG=1: the worker flushed but no 'Sending envelope' line ever appeared, and Sentry's Releases dashboard showed zero deepctl@* releases despite #71 having shipped. The fix is one line: call sentry_sdk.start_session() right after init. Default session_mode is already 'application' (per scope.py L1558). The atexit handler from #71 then catches the session in its flush. Verified locally with SENTRY_DEBUG=1, post-fix output now includes: [sentry] DEBUG: Sending envelope [envelope with 1 items (session)] project:4510993603362816 host:o206115.ingest.us.sentry.io Tests: extends TestSessionFlush with test_init_starts_session asserting sentry_sdk.start_session() is called, plus a guard in test_init_enables_auto_session_tracking that 'session_mode' is NOT in init kwargs (caught a regression: 'session_mode' is rejected by sentry-sdk 2.59.0 as TypeError: Unknown option, which the try/except in main.py was silently swallowing). --- .../src/deepctl_telemetry/client.py | 1 + .../tests/unit/test_telemetry.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/deepctl-telemetry/src/deepctl_telemetry/client.py b/packages/deepctl-telemetry/src/deepctl_telemetry/client.py index 516c173..ecfb8d5 100644 --- a/packages/deepctl-telemetry/src/deepctl_telemetry/client.py +++ b/packages/deepctl-telemetry/src/deepctl_telemetry/client.py @@ -78,6 +78,7 @@ def init_telemetry(config: Config) -> bool: ) sentry_sdk.set_tag("cli.version", cli_version) + sentry_sdk.start_session() atexit.register(_flush_on_exit) _initialized = True diff --git a/packages/deepctl-telemetry/tests/unit/test_telemetry.py b/packages/deepctl-telemetry/tests/unit/test_telemetry.py index 0f50e26..01c2915 100644 --- a/packages/deepctl-telemetry/tests/unit/test_telemetry.py +++ b/packages/deepctl-telemetry/tests/unit/test_telemetry.py @@ -53,7 +53,9 @@ def reset_initialized(self) -> None: def test_init_enables_auto_session_tracking(self) -> None: with patch("deepctl_telemetry.client.atexit.register"), patch( "sentry_sdk.init" - ) as mock_init, patch("sentry_sdk.set_tag"): + ) as mock_init, patch("sentry_sdk.set_tag"), patch( + "sentry_sdk.start_session" + ): init_telemetry(_config(True)) assert mock_init.called @@ -61,17 +63,28 @@ def test_init_enables_auto_session_tracking(self) -> None: assert kwargs["auto_session_tracking"] is True assert kwargs["traces_sample_rate"] == 0.0 assert kwargs["profiles_sample_rate"] == 0.0 + assert "session_mode" not in kwargs def test_init_registers_atexit_flush(self) -> None: from deepctl_telemetry.client import _flush_on_exit with patch( "deepctl_telemetry.client.atexit.register" - ) as mock_register, patch("sentry_sdk.init"), patch("sentry_sdk.set_tag"): + ) as mock_register, patch("sentry_sdk.init"), patch( + "sentry_sdk.set_tag" + ), patch("sentry_sdk.start_session"): init_telemetry(_config(True)) mock_register.assert_called_once_with(_flush_on_exit) + def test_init_starts_session(self) -> None: + with patch("sentry_sdk.init"), patch("sentry_sdk.set_tag"), patch( + "deepctl_telemetry.client.atexit.register" + ), patch("sentry_sdk.start_session") as mock_start: + init_telemetry(_config(True)) + + mock_start.assert_called_once_with() + def test_disabled_does_not_register_atexit(self) -> None: with patch( "deepctl_telemetry.client.atexit.register"