Skip to main content

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

CommandOne-liner
summaryPer-flag eval counts and variant distribution.
srmSample-ratio mismatch check on a rolled-out flag.
rulesRule-fire frequency for one flag.
userAll evaluations for a single unit_id_hash.
coverageFlags evaluated zero times in the window.
dead-flagsFlags whose every evaluation returned the catch-all.
version-skewEval counts grouped by manifest version.
contextsContext-attribute presence + value distribution.
tailLive tail of a streaming source.
simulateRe-evaluate historical context against a candidate manifest.
runRun a built-in query by name (the generic alternative to the aliases above).
capabilitiesSelf-describe: every command, parameter, and diagnostic.
exportArbitrary 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.

FlagTypeDescription
--source <uri>string, repeatableInput source. Local path, glob, or s3:// / gs:// / az:// URI. Multiple --source values are merged.
--since <duration>durationWindow relative to now (e.g. 1h, 7d, 30d). Mutually exclusive with --from / --to.
--from <ts>RFC 3339Inclusive lower bound.
--to <ts>RFC 3339Exclusive upper bound. Defaults to "now" when omitted.
--namespace <slug>slugRestrict to one namespace.
--flag <key>key, repeatableRestrict to one or more flags.
--environment <key>keyRestrict to one environment.
--format human|jsonenumOutput format. Default human.
--thresholds <path>pathOverride the threshold-config file (e.g. SRM significance level, min sample size). Falls through to built-in defaults when omitted.
--engine <name>stringForce a specific query engine: inmemory, duckdb (default for Rungs 1–3), snowflake, bigquery, databricks, redshift.
--explainboolPrint the planned engine query and estimated scan size; do not execute.
--limit <n>integerCap the result set size. Default and maximum vary by query.
--fail-on-errorboolExit 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.

CodeSeverityConditionEmitted by
T001warningObserved variant distribution deviates from the expected split below srm.significance_level.srm, summary (when --expected is set)
T002infoPer-group sample below srm.min_sample_size.srm
T003infoEvery evaluation in the window resolved to the catch-all.dead-flags
T004warningA wide spread of manifest_version values is producing eval traffic.version-skew
T005infoA declared rule had zero matches in the window.rules
T006warningA context attribute referenced by the flag's predicates was never observed in the window.contexts
T007warningThe per-window evaluation rate deviates from the baseline by more than rate.anomaly_z.summary
T008infoA declared flag had zero evaluations in the window.summary, coverage
T009infoA declared variant was never returned in the window.summary
T010warningTwo evaluations with the same unit_id_hash and manifest_version returned different variants.summary
T011errorA record carried a context attribute listed in private_attributes.every command
T012infoA 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

CodeMeaning
0Success. Diagnostics may have fired but did not gate execution.
1An error-severity diagnostic fired AND --fail-on-error was set.
2Invocation error: missing required flag, malformed parameter, unparseable window, unreadable source, unknown engine, query name not found.
3Engine 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