exd telemetry
The exd telemetry subtree analyzes evaluation records emitted by the SDKs. It is the read-side of the observability story — sinks write records during evaluation, exd telemetry reads them back.
Surface
| Command | One-liner |
|---|---|
summary | Per-flag eval counts and variant distribution. |
srm | Sample-ratio mismatch check on a rolled-out flag. |
rules | Rule-fire frequency for one flag. |
user | All evaluations for a single unit_id_hash. |
coverage | Flags evaluated zero times in the window. |
dead-flags | Flags whose every evaluation returned the catch-all. |
version-skew | Eval counts grouped by manifest version. |
contexts | Context-attribute presence + value distribution. |
tail | Live tail of a streaming source. |
simulate | Re-evaluate historical context against a candidate manifest. |
run | Run a built-in query by name (the generic alternative to the aliases above). |
capabilities | Self-describe: every command, parameter, and diagnostic. |
export | Arbitrary SQL against object-store data (Rung 3 escape hatch). |
The canned summary / srm / rules / … commands are convenience aliases over telemetry.<name> queries in the built-in catalog. Agents that prefer explicit invocation should use run and discover the parameter set via capabilities.
Common flags
Every command in this tree accepts the following. Subcommand-specific flags are documented on each command page.
| Flag | Type | Description |
|---|---|---|
--source <uri> | string, repeatable | Input source. Local path, glob, or s3:// / gs:// / az:// URI. Multiple --source values are merged. |
--since <duration> | duration | Window relative to now (e.g. 1h, 7d, 30d). Mutually exclusive with --from / --to. |
--from <ts> | RFC 3339 | Inclusive lower bound. |
--to <ts> | RFC 3339 | Exclusive upper bound. Defaults to "now" when omitted. |
--namespace <slug> | slug | Restrict to one namespace. |
--flag <key> | key, repeatable | Restrict to one or more flags. |
--environment <key> | key | Restrict to one environment. |
--format human|json | enum | Output format. Default human. |
--thresholds <path> | path | Override the threshold-config file (e.g. SRM significance level, min sample size). Falls through to built-in defaults when omitted. |
--engine <name> | string | Force a specific query engine: inmemory, duckdb (default for Rungs 1–3), snowflake, bigquery, databricks, redshift. |
--explain | bool | Print the planned engine query and estimated scan size; do not execute. |
--limit <n> | integer | Cap the result set size. Default and maximum vary by query. |
--fail-on-error | bool | Exit with code 1 if any error-severity diagnostic fires. Default off — diagnostics are reported but do not gate execution. |
Commands that require a window (most of them) MUST receive either --since OR both --from and --to. Missing window flags exit with code 2.
Duration syntax
--since accepts the standard Go-style duration form: 30s, 15m, 4h, 7d, 30d. Combinations like 1h30m are accepted.
Window precedence
If you pass both --since and --from, the command exits 2 with error: --since and --from are mutually exclusive. Pick one form.
Discovery (agents)
For programmatic discovery — what queries exist, what parameters each takes, what diagnostics can fire — use:
exd telemetry capabilities --format json
This emits the full catalog described in the capabilities spec. Use it as the source of truth in agent prompts and code generators; the catalog is versioned with the binary, so it is always in sync with what the CLI actually supports.
Output
Human format
Tabular output with a leading code column when any diagnostic fires. Severity is rendered via ANSI color when stdout is a TTY. Numeric counts are right-aligned; rates appear as percentages.
JSON format
Every --format json output is a single object using the shared provenance envelope:
{
"query": "telemetry.srm",
"query_version": 1,
"schema_version": 1,
"inputs": { /* parsed flags */ },
"result": { /* command-specific; see each page */ },
"diagnostics": [
{ "code": "T001", "severity": "warning", "data": { ... }, "message": "..." }
],
"provenance": { /* source URIs, engine, record_count, time_range */ }
}
provenance.engine carries the engine name actually used ("inmemory", "duckdb", etc., not the requested one if a fallback occurred). provenance.record_count is the number of records scanned.
Diagnostics
Every diagnostic carries a stable T-code. Once allocated, a code's semantics, severity, and detection criterion are immutable. The full vocabulary lives in the diagnostics spec; the table here is for navigation.
| Code | Severity | Condition | Emitted by |
|---|---|---|---|
T001 | warning | Observed variant distribution deviates from the expected split below srm.significance_level. | srm, summary (when --expected is set) |
T002 | info | Per-group sample below srm.min_sample_size. | srm |
T003 | info | Every evaluation in the window resolved to the catch-all. | dead-flags |
T004 | warning | A wide spread of manifest_version values is producing eval traffic. | version-skew |
T005 | info | A declared rule had zero matches in the window. | rules |
T006 | warning | A context attribute referenced by the flag's predicates was never observed in the window. | contexts |
T007 | warning | The per-window evaluation rate deviates from the baseline by more than rate.anomaly_z. | summary |
T008 | info | A declared flag had zero evaluations in the window. | summary, coverage |
T009 | info | A declared variant was never returned in the window. | summary |
T010 | warning | Two evaluations with the same unit_id_hash and manifest_version returned different variants. | summary |
T011 | error | A record carried a context attribute listed in private_attributes. | every command |
T012 | info | A record carried an evaluation_reason not in the known set. | every command |
T011 is the only diagnostic that defaults to error severity. Combined with --fail-on-error, it lets a CI job gate "did any SDK leak a PII attribute?"
Reserved range: T013+.
Exit codes
| Code | Meaning |
|---|---|
0 | Success. Diagnostics may have fired but did not gate execution. |
1 | An error-severity diagnostic fired AND --fail-on-error was set. |
2 | Invocation error: missing required flag, malformed parameter, unparseable window, unreadable source, unknown engine, query name not found. |
3 | Engine error: the underlying engine (DuckDB, warehouse) returned an error. The error message is included in the JSON envelope under a top-level error key. |
Stability
The set of subcommand names, the common-flag set, the JSON envelope shape, and the T-code set are stable per spec version. New subcommands MAY be added at minor revisions. New common flags MAY be added if they do not change the meaning of existing flags. Renames or removals require a major spec version.
The --explain plan output, the export SQL surface, and the human-format rendering details are NOT stable across versions.
See also
- Telemetry record schema — what's in a record before any query.
- Sink reference — how records get written.
- Query catalog — full
telemetry.*query reference. - Diagnostics — full
T-codevocabulary. - Capabilities manifest — the JSON catalog
capabilitiesemits.