feat(telemetry): implement session tracking and telemetry server - #2098
Conversation
There was a problem hiding this comment.
Pull request overview
Implements per-session telemetry attribution by emitting a single session_started event per session (with raw Wire client info as properties), removing client name/version from the shared telemetry context, and adding local debugging + targeted tests.
Changes:
- Add
track_session_started_once(...)and process-level tracking to ensuresession_startedis emitted once per session. - Wire/app integration: emit
session_startedfrom Wire initialization (and a fallback on first prompt), and from non-wire app startup. - Add telemetry debug server script and update/extend tests to reflect new attribution model (client info on event properties, not context).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/kimi_cli/telemetry/__init__.py |
Adds session-started tracking API/state and opportunistic flush scheduling. |
src/kimi_cli/telemetry/sink.py |
Removes client name/version enrichment from global context. |
src/kimi_cli/wire/server.py |
Tracks session start from wire initialize + prompt fallback. |
src/kimi_cli/app.py |
Tracks session start on app init for non-wire UI modes. |
src/kimi_cli/soul/agent.py |
Adds ui_mode / resumed fields onto Runtime for attribution. |
tests/telemetry/test_instrumentation.py |
Updates tests to assert client info is not in context; adds session_started-focused tests. |
tests/telemetry/test_telemetry.py |
Resets new session_started tracking state in test fixture. |
tests/telemetry/test_crash.py |
Resets new session_started tracking state in test fixture. |
tests/core/test_wire_server_steer.py |
Adds focused test ensuring wire client info emits session_started. |
scripts/telemetry_debug_server.py |
Adds a small local HTTP receiver for inspecting outbound telemetry payloads. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| session_id = _session_id | ||
| if not session_id or session_id in _session_started_sessions: | ||
| return |
| if _sink is not None: | ||
| with suppress(Exception): | ||
| asyncio.get_running_loop().create_task(_sink.flush()) |
There was a problem hiding this comment.
🟡 copy_for_subagent does not propagate new ui_mode and resumed fields to subagent runtimes
The copy_for_subagent method at src/kimi_cli/soul/agent.py:339-361 constructs a new Runtime but does not pass ui_mode=self.ui_mode or resumed=self.resumed. This means every subagent runtime silently gets the defaults ui_mode="shell" and resumed=False, even when the parent is running in "wire" mode or was resumed. While no code currently reads these fields from subagent runtimes, the wire server accesses self._soul.runtime.resumed (src/kimi_cli/wire/server.py:639), and if a similar pattern is ever used in a subagent context, the values would be wrong.
(Refers to lines 339-361)
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
session_startedtelemetry event once per session with raw Wire client info as event propertiesTest Plan
uv run pytest tests/telemetry tests/core/test_wire_server_steer.py::test_wire_client_info_emits_session_starteduv run ruff check src/kimi_cli/telemetry/__init__.py src/kimi_cli/telemetry/sink.py src/kimi_cli/app.py src/kimi_cli/wire/server.py src/kimi_cli/soul/agent.py tests/telemetry/test_instrumentation.py tests/telemetry/test_telemetry.py tests/telemetry/test_crash.py tests/core/test_wire_server_steer.pyuv run ruff format --check src/kimi_cli/telemetry/__init__.py src/kimi_cli/telemetry/sink.py src/kimi_cli/app.py src/kimi_cli/wire/server.py src/kimi_cli/soul/agent.py tests/telemetry/test_instrumentation.py tests/telemetry/test_telemetry.py tests/telemetry/test_crash.py tests/core/test_wire_server_steer.pyuv run pyright src/kimi_cli/telemetry src/kimi_cli/wire/server.py src/kimi_cli/app.py src/kimi_cli/soul/agent.py