Skip to content

feat(telemetry): enable session tracking and flush envelopes on exit#71

Merged
lukeocodes merged 1 commit intomainfrom
feat/telemetry-session-flush
May 8, 2026
Merged

feat(telemetry): enable session tracking and flush envelopes on exit#71
lukeocodes merged 1 commit intomainfrom
feat/telemetry-session-flush

Conversation

@lukeocodes
Copy link
Copy Markdown
Member

Why

Today the `dx-cli` Sentry project has zero events. That's expected for an errors-only telemetry contract on a CLI that's been live <24h — most users haven't hit an unhandled exception. But it also means there's no signal at all: we can't tell "is anyone running v0.2.22?" from the dashboard.

Sessions fix that without violating the errors-only design.

What changed

Two lines in `packages/deepctl-telemetry/src/deepctl_telemetry/client.py`:

```python
sentry_sdk.init(
...
auto_session_tracking=True, # NEW (already the SDK default; explicit now)
traces_sample_rate=0.0, # unchanged
profiles_sample_rate=0.0, # unchanged
...
)

atexit.register(_flush_on_exit) # NEW
```

Plus a tiny module-level helper:

```python
def _flush_on_exit() -> None:
try:
import sentry_sdk
sentry_sdk.flush(timeout=2.0)
except Exception:
pass
```

What it gives us

After the next release lands on PyPI and a few users invoke `dg`:

  • Releases dashboard populates with per-version session counts.
  • Crash-free session % per release, the canonical CLI health metric.
  • Stable signal that "the new version actually launched on someone's machine" without per-command instrumentation.

What it doesn't change

  • `traces_sample_rate=0` and `profiles_sample_rate=0` are unchanged — no transactions, no profiles.
  • No new PII paths. `before_send` scrubbing applies to error envelopes; session envelopes carry only release tag, environment, and start/end timestamps.
  • Opt-out paths (`dg config set telemetry.enabled false`, `DEEPCTL_TELEMETRY_DISABLED=1`, `--non-interactive` once fix(non-interactive): promote CI=1 to hard signal, add --non-interactive flag #67 lands) all skip session tracking too — `init_telemetry` returns early before `atexit.register` is reached, verified by `test_disabled_does_not_register_atexit`.

Why `atexit` and not `Sentry.flush()` inline somewhere

CLI commands have multiple exit paths — `return BaseResult(...)`, raised exceptions, `ctx.exit()` from Click, sys.exit on signal, etc. `atexit` is the only hook that fires on all of them. The 2-second budget caps user-visible exit delay even if Sentry is unreachable. The bare-`except` ensures a Sentry hang can never block process termination.

Test plan

5 new cases in `TestSessionFlush`:

  • `test_init_enables_auto_session_tracking` — kwargs dict on `sentry_sdk.init` includes `auto_session_tracking=True` and confirms `traces_sample_rate==0`, `profiles_sample_rate==0` are still in place.
  • `test_init_registers_atexit_flush` — `atexit.register` called once with the `_flush_on_exit` function reference.
  • `test_disabled_does_not_register_atexit` — when `is_enabled` returns False, neither `sentry_sdk.init` nor `atexit.register` fires.
  • `test_flush_on_exit_calls_sentry_flush_with_2s_budget` — `sentry_sdk.flush(timeout=2.0)` is the call shape.
  • `test_flush_on_exit_swallows_exceptions` — Sentry raising during flush does not propagate.

Full suite: `uv run pytest packages/deepctl-telemetry/tests/` → 10 passed in 0.06s.

Two small additions to deepctl-telemetry so the dx-cli Sentry project
gets release-health signal alongside errors:

1. `auto_session_tracking=True` in sentry_sdk.init. Already the SDK
   default, but spelling it out makes the contract explicit and
   defends against a future SDK release flipping the default off.

2. New `_flush_on_exit` registered via `atexit.register` after a
   successful init. Calls `sentry_sdk.flush(timeout=2.0)` so the
   session envelope (and any error envelope captured at the very tail
   of execution) actually leaves the process before Python tears down.
   Without this, short-lived `dg` invocations can lose their session
   record entirely.

   Wrapped in a bare except so a Sentry hang or network glitch can
   never block CLI exit. 2s is the maximum the user waits.

After this lands, the Releases view in Sentry
(https://deepgram.sentry.io/releases/?project=4510993603362816) starts
showing per-version session counts and crash-free percentages — the
'is anyone actually using v0.2.X' dashboard. Errors-only contract is
preserved: traces_sample_rate stays 0, profiles_sample_rate stays 0,
no per-command instrumentation.

Tests: 5 new cases in TestSessionFlush covering auto_session_tracking
being set to True in init kwargs, atexit registration of
_flush_on_exit, no atexit registration when telemetry is disabled,
2.0s flush timeout, and exception suppression in the flush path.
@lukeocodes lukeocodes merged commit 1c86e70 into main May 8, 2026
38 checks passed
@lukeocodes lukeocodes deleted the feat/telemetry-session-flush branch May 8, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant