Nomos emits two complementary observability surfaces:
- audit events for durable security evidence
- OpenTelemetry-compatible telemetry records for execution tracing and counters
Telemetry is optional and disabled by default.
When enabled, Nomos emits a fail-safe structured telemetry stream to:
stdoutstderrotlp:<base_url>over OTLP/HTTP JSON (/v1/traces,/v1/logs,/v1/metrics)
Telemetry export failures are ignored and MUST NOT change authorization or execution decisions.
Telemetry records use stable field names:
signal_typeevent_nametrace_idcorrelation_idtraceparent(when accepted from HTTP ingress)tracestate(when accepted from HTTP ingress)statusattributes
Metrics use:
signal_typenamekindvaluetrace_idattributes
Metric kinds currently exported by Nomos:
countergaugehistogram
The current implementation emits:
- request lifecycle events
- policy evaluation events
- executor run events
- counters for decisions, rate limits, approvals, retries, and failures
- upstream MCP request counters and latency histograms
- upstream MCP breaker transition events and breaker-state gauges
- upstream MCP session lifecycle events
nomos.rate_limits counters include stable result, rule_id, scope, action_type, and principal attributes. result=allowed means a matching bucket was consumed; result=exceeded means the action was denied with RATE_LIMIT_EXCEEDED.
mcp.upstream_breaker.transition events include stable upstream_server, from_state, to_state, and failure_kind attributes. These events are emitted only on state transitions and do not change policy or execution decisions.
Nomos emits per-upstream telemetry for configured MCP upstream servers.
Stable metric names:
nomos.mcp.upstream.requestsnomos.mcp.upstream.latency_msnomos.mcp.upstream.breaker_state
nomos.mcp.upstream.requests is a counter emitted once per upstream RPC attempt, including fast-fail outcomes.
Stable labels:
upstream_servertransportmethodaction_typeoutcomeerror_class
nomos.mcp.upstream.latency_ms is a histogram sample emitted with the same labels. It measures elapsed upstream RPC time in milliseconds. When a connection must be established first, Nomos also emits an initialize latency sample for the connection/handshake stage.
nomos.mcp.upstream.breaker_state is a gauge. Values are:
0disabled1closed2half-open3open
Stable labels:
upstream_serverstateenabled
Per-upstream events:
mcp.upstream.requestmcp.upstream.session.lifecyclemcp.upstream_breaker.transition
Structured MCP runtime logs use the same stable field names as the events where applicable:
eventupstream_serverupstream_session_idtransportstagemethodaction_typeoutcomeerror_classlatency_ms
These logs never include raw tool arguments, upstream responses, request bodies, headers, or credential values.
Per-upstream labels are intentionally bounded:
methodis normalized to a fixed set such astools.call,resources.read,prompts.get, orother.action_typeis normalized to canonical Nomos action classes such asmcp.call,mcp.resource_read, ormcp.upstream_rpc.outcomeis limited tosuccess,error, orblocked.error_classis limited to stable classes such asnone,transport,protocol,timeout,credential,canceled, orbreaker_open.- free-form values such as
upstream_serverare sanitized and length-capped before export.
Do not encode tenant ids, user ids, request ids, tool arguments, or resource URIs into upstream server names. Use audit records for high-cardinality forensic detail.
For HTTP ingress, Nomos accepts:
traceparenttracestate
If traceparent is valid, Nomos propagates the accepted trace context back on the HTTP response headers.
Telemetry trace records use Nomos trace_id as the deterministic correlation key so telemetry and audit can be joined reliably.
- telemetry is redacted before export
- secret material must not appear in emitted telemetry
- upstream telemetry must not include raw MCP payloads, arguments, headers, responses, or credentials
- telemetry is additive and does not replace audit evidence
Example:
{
"telemetry": {
"enabled": true,
"sink": "otlp:http://otel-collector:4318"
}
}Supported sinks:
stdoutstderrotlp:<base_url>