Skip to content

Metric Dictionary

Canonical reference for every metric, dimension, and aggregated statistic that dcc-mcp-core observability surfaces produce. Use this dictionary to understand units, sampling windows, null/missing-value semantics, and which storage layer holds each metric.


1. Gateway Admin SQLite — Persistent Metrics

The gateway writes structured rows to the shared gateway_admin.sqlite database. This is the authoritative per-machine store for tool-call traces, session lifecycle, and aggregated statistics.

1.1 tool_calls table

ColumnTypeUnitSamplingMissing semantics
request_idTEXTEvery tool callNOT NULL, PK
session_idTEXTEvery tool callNOT NULL — empty string when no session
parent_request_idTEXTWhen attributedNULL = orphan (no parent chain)
batch_idTEXTWhen inside a batchNULL = standalone call
tool_nameTEXTEvery tool callNOT NULL
skill_nameTEXTWhen knownNULL = direct tool (no skill wrapper)
dcc_typeTEXTWhen knownNULL = gateway-level call
instance_idTEXTWhen knownNULL = no target instance resolved
agent_idTEXTWhen caller providesNULL = anonymous
transportTEXTEvery call"mcp", "rest", or NULL on legacy paths
via_gatewayINTEGERbooleanEvery call0 = direct DCC, 1 = via gateway, NULL = unknown
started_at_msINTEGERms since epochEvery callNOT NULL
duration_msINTEGERmsEvery callNOT NULL — wall-clock, may be 0 for sub-ms calls
successINTEGERbooleanEvery call0 = failure, 1 = success
error_messageTEXTOn failureNULL on success
error_kindTEXTOn classified failureNULL = unclassified
mcp_methodTEXTEvery callAlways "tools/call" in practice
trace_idTEXTWhen traceparent attachedNULL = no distributed trace
span_idTEXTWhen span attachedNULL = no span

Row retention: bounded by the gateway ring buffer (default 5000 rows in JSONL; SQLite mirror retains all rows). The SQLite lane is append-only with no automatic purge — operators may delete old partitions.

1.2 sessions table

ColumnTypeUnitSamplingMissing semantics
session_idTEXTEvery session startNOT NULL, PK
parent_session_idTEXTWhen spawnedNULL = root session
dcc_typeTEXTEvery sessionNOT NULL
instance_idTEXTWhen knownNULL = unknown instance
statusTEXTEvery sessionOne of: active, ended, crashed, disconnected, gpu_crashed, timed_out, cancelled, thread_affinity_failure
started_at_msINTEGERms since epochEvery sessionNOT NULL
last_activity_at_msINTEGERms since epochEvery sessionUpdated on each tool call
ended_at_msINTEGERms since epochOn endNULL while session is active
end_reason_jsonTEXTOn non-normal endNULL for normal end
tool_call_countINTEGERcountEvery sessionDefaults to 0
error_countINTEGERcountEvery sessionDefaults to 0
core_versionTEXTEvery sessionNOT NULL — semver of dcc-mcp-core
adapter_versionTEXTWhen DCC adapter providesNULL = unknown
build_shaTEXTWhen build metadata availableNULL = dev build

Session status semantics:

StatusMeaning
activeSession is live and accepting tool calls
endedClean shutdown via on_session_end
crashedDCC host process terminated unexpectedly
gpu_crashedGPU device lost / TDR event
disconnectedGateway lost contact with the DCC backend
timed_outSession exceeded the configured idle timeout
cancelledClient explicitly cancelled the session
thread_affinity_failureDCC thread-affinity constraint could not be satisfied

1.3 session_events table

ColumnTypeUnitSamplingMissing semantics
idINTEGEREvery eventPK, auto-increment
session_idTEXTEvery eventNOT NULL
event_typeTEXTEvery eventSee table below
event_jsonTEXTEvery eventNOT NULL — JSON payload
created_at_msINTEGERms since epochEvery eventNOT NULL

Event types:

EventPayloadWhen emitted
session_start{ session_id, dcc_type, instance_id, core_version }On first initialize
session_end{ session_id, reason }On clean close
session_crash{ session_id, signal?, exit_code? }On process termination
session_timeout{ session_id, idle_seconds }On idle timeout expiry
tool_call_start{ request_id, tool_name, session_id }Before dispatch
tool_call_end{ request_id, success, duration_ms }After completion

2. Prometheus Exporter — Runtime Metrics

Available when compiled with the prometheus Cargo feature. Mounted at GET /metrics on the same Axum router as the MCP server.

2.1 Per-DCC Server Metrics

MetricTypeUnitLabelsMissing/zero semantics
dcc_mcp_tool_calls_totalcounterinvocationstool, statusAbsent until first call. status="success" or status="error".
dcc_mcp_tool_duration_secondshistogramsecondstoolNo observations = zero histogram. Buckets: log-ish 1 ms → 30 s.
dcc_mcp_jobs_in_flightgaugecounttool0 when no jobs are running.
dcc_mcp_job_created_totalcounterjobstool, resultresult{accepted, queue_full}.
dcc_mcp_job_wait_secondshistogramsecondstoolZero for instantly-scheduled jobs.
dcc_mcp_notifications_sent_totalcounternotificationschannelchannel{sse, ws}.
dcc_mcp_active_sessionsgaugecount0 when no sessions. Refreshed every 5 s.
dcc_mcp_registered_toolsgaugecount0 when registry empty. Refreshed every 5 s.
dcc_mcp_build_infogaugeversion, crateAlways 1. Published once at startup.

Sampling window: gauge metrics refresh on a 5-second background tick. Counters and histograms advance inline on the tools/call hot path.

2.2 Gateway-Only Metrics

MetricTypeUnitLabelsMissing/zero semantics
dcc_mcp_gateway_elections_totalcounterelectionsoutcomeoutcome{won, yielded, lost}
dcc_mcp_gateway_evictions_totalcounterevictionsreasonreason{stale, ghost, probe_fail}
dcc_mcp_gateway_probes_totalcounterprobesoutcomeoutcome{ready, booting, unreachable}
dcc_mcp_gateway_governance_events_totalcountereventscategory, outcomecategory{policy, rate-limit}; outcome{allowed, denied, throttled}

3. Observability Query API — Aggregated Metrics

The Python ObservabilityQuery class provides method-level aggregates computed from the gateway admin SQLite database (Section 1).

3.1 Session Stats

Field returned by get_session_stats():

FieldTypeUnitSampling windowMissing/zero
total_sessionsintegercountFilter time range0 when no sessions match
active_sessionsintegercountFilter time range0 when no active sessions
ended_normallyintegercountFilter time range0
ended_abnormallyintegercountFilter time range0
avg_duration_msfloatmsFilter time range0.0 when no ended sessions
total_tool_callsintegercountFilter time range0
total_errorsintegercountFilter time range0

3.2 Tool Call Stats

Field returned by get_tool_call_stats():

FieldTypeUnitSampling windowMissing/zero
total_callsintegercountFilter time range + limit0
success_countintegercountFilter time range + limit0
failure_countintegercountFilter time range + limit0
success_ratefloatratio [0–1]Filter time range + limit0.0 when zero total
avg_duration_msfloatmsFilter time range + limit0.0

Each row in the events sub-list repeats the column semantics from the tool_calls table (Section 1.1).

3.3 Coverage Stats

Field returned by get_coverage_stats():

FieldTypeUnitSampling windowMissing/zero
observed_requestsintegercountFilter time range0
unobserved_requestsintegercountFilter time range0
coverage_ratiofloatratio [0–1]Filter time range0.0 when zero total

3.4 Crash Stats

Field returned by get_crash_stats():

FieldTypeUnitSampling windowMissing/zero
total_crashesintegercountFilter time range0
host_crashesintegercountFilter time range0
gpu_crashesintegercountFilter time range0

3.5 Funnel Stats

Field returned by get_funnel_stats():

FieldTypeUnitSampling windowMissing/zero
searches_totalintegercountFilter time range0 until search instrumentation is wired
searches_zero_resultsintegercountFilter time range0
skills_loadedintegercountFilter time range0
skills_calledintegercountFilter time rangeUpper bound from tool_calls count
skills_succeededintegercountFilter time range0
script_fallbacksintegercountFilter time range0
ui_control_fallbacksintegercountFilter time range0

4. In-Process Python Telemetry

The ToolRecorder class provides in-memory percentiles without a database.

ToolMetrics fields

FieldTypeUnitSamplingMissing/zero
invocation_countintegercountEvery start()/finish()0 = never recorded
success_countintegercountSame0
failure_countintegercountSame0
avg_duration_msfloatmsSame0.0
p95_duration_msfloatmsSame0.0 when < 20 samples
p99_duration_msfloatmsSame0.0 when < 100 samples
success_rate()floatratio [0–1]Same0.0

Percentile accuracy: p95 stabilises after ~20 samples; p99 after ~100. Below those thresholds, percentiles may match the maximum observed value.


5. Admin API Statistics

The GET /admin/api/stats endpoint computes on-demand from the trace ring buffer (default 200 traces, configurable up to 5000).

GroupFieldUnitMissing/zero
Overalltotal_callscount0
success_rateratio [0–1]0.0
avg_duration_msms0.0
Latencyp50_duration_msms0.0
p95_duration_msms0.0
p99_duration_msms0.0
Top toolstool, call_countcountEmpty list
Top instancesinstance_id, call_countcountEmpty list
Hourlyhour (UTC 0–23), call_countcountZero-filled 24-bucket array

Range filter: ?range=1h|24h|7d|all. Default all = entire ring buffer. StatsFilter supports optional dcc_type, skill, tool, status, instance_id, and session_id dimensions.


6. OTLP Distributed Tracing

OpenTelemetry-compatible spans with these key attributes:

AttributeTypeUnitPresentMissing
dcc.typestringEvery DCC spanNULL on gateway-only spans
dcc.instance_idstringWhen resolvedNULL
mcp.tool_slugstringtools/call spansNULL
mcp.session_idstringSession contextNULL
dcc_mcp.successboolEvery spanfalse on error

See the full attribute table in observability.md.


Index

SurfaceStorageQuery interfaceRetention
SQLite tool_callsgateway_admin.sqliteObservabilityQuery, Admin APIAppend-only
SQLite sessionsgateway_admin.sqliteObservabilityQuery, Admin APIAppend-only
SQLite session_eventsgateway_admin.sqliteAdmin APIAppend-only
PrometheusIn-process registryGET /metricsResets on process restart
OTLP tracesExternal collectorJaeger/Tempo/PhoenixCollector-managed
ToolRecorderIn-process memoryPython metrics()Resets on reset() or process restart
Admin audit ringIn-memory + optional JSONLGET /admin/api/callsDefault 5000 rows
Admin trace ringIn-memory + optional JSONLGET /admin/api/tracesDefault 200 traces
Admin statsOn-demand from trace ringGET /admin/api/statsSame as trace ring

Released under the MIT License.