From 9834c609f42d67be5afad189cd321eec4cc24547 Mon Sep 17 00:00:00 2001 From: Andrey Avtomonov Date: Fri, 22 May 2026 16:19:27 +0200 Subject: [PATCH] docs: document full telemetry event catalog --- .../content/docs/community/telemetry.mdx | 10 ++++- .../tests/test_telemetry_schema_sync.py | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 python/ktx-daemon/tests/test_telemetry_schema_sync.py diff --git a/docs-site/content/docs/community/telemetry.mdx b/docs-site/content/docs/community/telemetry.mdx index 0f465105..51d6810f 100644 --- a/docs-site/content/docs/community/telemetry.mdx +++ b/docs-site/content/docs/community/telemetry.mdx @@ -39,7 +39,7 @@ sent. ## Events -Node telemetry emits these events: +**ktx** emits these events: | Event | When it fires | Fields | |-------|---------------|--------| @@ -56,10 +56,18 @@ Node telemetry emits these events: | `sql_completed` | `ktx sql` | `driver`, `isDemoConnection`, `queryVerb`, `referencedTableCount`, `durationMs`, `outcome`, `errorClass` | | `wiki_query_completed` | `ktx wiki ` | `queryLength`, `resultCount`, `durationMs`, `outcome` | | `mcp_request_completed` | Sampled MCP tool invocations | `toolName`, `outcome`, `durationMs`, `errorClass`, `sampleRate` | +| `daemon_started` | The long-lived `ktx-daemon serve-http` server starts | `daemonVersion`, `pythonVersion`, `runtimeVersion`, `startupDurationMs` | +| `daemon_stopped` | The long-lived `ktx-daemon serve-http` server shuts down | `reason`, `uptimeMs` | +| `sl_plan_completed` | A daemon semantic-layer planning pass completes | `outcome`, `stage`, `errorClass`, `durationMs`, `sourceCount`, `joinCount` | +| `sql_gen_completed` | A daemon SQL generation pass completes | `outcome`, `dialect`, `errorClass`, `durationMs` | Common envelope fields are `cliVersion`, `nodeVersion`, `osPlatform`, `osRelease`, `arch`, `runtime`, and `isCi`. +Daemon events use `runtime: "daemon-py"`. The Python daemon reads the same +install ID file as the Node CLI and receives only the already-hashed project ID +for semantic-layer query events. + `mcp_request_completed` is sampled at 10% with a sticky per-process sampling decision. If a process is sampled in, every MCP tool invocation in that process emits the event; if it is sampled out, none do. diff --git a/python/ktx-daemon/tests/test_telemetry_schema_sync.py b/python/ktx-daemon/tests/test_telemetry_schema_sync.py new file mode 100644 index 00000000..6f2ba634 --- /dev/null +++ b/python/ktx-daemon/tests/test_telemetry_schema_sync.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +import json +from pathlib import Path + + +def test_python_schema_copy_matches_node_schema() -> None: + repo_root = Path(__file__).resolve().parents[3] + node_schema = json.loads( + (repo_root / "packages/cli/src/telemetry/events.schema.json").read_text( + encoding="utf-8" + ) + ) + python_schema = json.loads( + ( + repo_root / "python/ktx-daemon/src/ktx_daemon/telemetry/events.schema.json" + ).read_text(encoding="utf-8") + ) + + assert python_schema == node_schema + assert [event["name"] for event in python_schema["x-ktx-catalog"]] == [ + "install_first_run", + "command", + "setup_step", + "connection_added", + "connection_test", + "project_stack_snapshot", + "ingest_completed", + "scan_completed", + "sl_validate_completed", + "sl_query_completed", + "sql_completed", + "wiki_query_completed", + "mcp_request_completed", + "daemon_started", + "daemon_stopped", + "sl_plan_completed", + "sql_gen_completed", + ]