Skip to content

Metrics

Every metric the Smart Router exposes over Prometheus, with its type, labels, and meaning. All metrics are defined under protocol/metrics/.

The classified-error counter smartrouter_errors_total is broken down by error name and category; see Error codes for the full taxonomy of names it can carry.

Already running the dashboard overlay? It ships pre-built panels over these series — this page is the underlying reference and the recipes for rolling your own.

What to watch

If you only graph a handful of things, graph these:

Question Metric(s)
Is the router up and serving? smartrouter_overall_health, smartrouter_total_relays_serviced
Are requests failing? smartrouter_total_errored, smartrouter_errors_total (by error_category / retryable)
How fast is it? smartrouter_end_to_end_latency_milliseconds (histogram → p50/p95/p99)
Is a node degrading? rpc_endpoint_overall_health, rpc_endpoint_end_to_end_latency_milliseconds, rpc_endpoint_latest_block
Is failover working hard? smartrouter_retries_total, smartrouter_hedge_total
Is the cache earning its keep? smartrouter_cache_success_total / smartrouter_cache_requests_total

Querying — PromQL recipes

Copy-paste starting points (adjust labels / windows to taste).

# Request error ratio (last 5m)
sum(rate(smartrouter_total_errored[5m]))
  / sum(rate(smartrouter_total_relays_serviced[5m]))

# p99 end-to-end latency, per chain (ms)
histogram_quantile(0.99,
  sum by (spec, le) (rate(smartrouter_end_to_end_latency_milliseconds_bucket[5m])))

# Cache hit ratio
sum(rate(smartrouter_cache_success_total[5m]))
  / sum(rate(smartrouter_cache_requests_total[5m]))

# Retry rate per relay (how often the first attempt isn't enough)
sum(rate(smartrouter_retries_total[5m]))
  / sum(rate(smartrouter_total_relays_serviced[5m]))

# Non-retryable (terminal) errors only — usually client/chain problems, not infra
sum by (error_name) (rate(smartrouter_errors_total{retryable="false"}[5m]))

# Nodes currently unhealthy
rpc_endpoint_overall_health == 0

# Per-node request share (is selection lopsided?)
sum by (provider_address) (rate(smartrouter_requests_total[5m]))

Suggested alerts

Starting points — tune thresholds to your traffic.

Alert Expression sketch Why
Router unhealthy smartrouter_overall_health == 0 for 1m No endpoint is serving.
High error ratio error-ratio recipe > 0.05 for 5m Something broke upstream or in config.
Latency regression p99 recipe > 2000 for 10m Tail latency degraded.
Node down rpc_endpoint_overall_health == 0 for 5m A configured upstream is out.
Cache cold hit-ratio recipe < 0.2 for 30m Cache misconfigured or bypassed — cost/latency risk.
Post-finality divergence increase(smartrouter_cross_validation_mismatch_total{finality="finalized"}[15m]) > 0 A node disagreed on finalized data — high-signal correctness alert.

Exposition

Metrics are served in Prometheus text format from an HTTP server started by the metrics manager.

Path Format Description
/metrics Prometheus All registered metrics (promhttp.Handler())
/metrics/overall-health text 200 Health status OK if ≥1 endpoint is healthy, else 503 Unhealthy
/metrics/health-overall text Alias of the above (backward-compat path)

Configuration

Flag / env Default Effect
--metrics-listen-address disabled Address to expose Prometheus metrics on, e.g. :7779 or localhost:7779. The literal disabled turns the metrics server off entirely.
--optimizer-qos-sampling-interval 1s How often the optimizer-QoS sampler refreshes the rpc_optimizer_selection_score gauge and — when --usage-otel-enabled is set — emits optimizer_qos events to the OTel usage pipeline.
# enable, then scrape
smartrouter ... --metrics-listen-address ":7779"
curl http://localhost:7779/metrics

The flag name and the disabled sentinel live in flags.go.

Optimizer scores are always on

The optimizer-QoS client is created unconditionally, so rpc_optimizer_selection_score is populated on /metrics regardless of telemetry config. Remote shipping of these reports flows through the OTel usage pipeline (--usage-otel-enabled), not a dedicated push address.

Conventions

  • Latency histograms all share the same buckets, in milliseconds (buckets.go): 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000.
  • Attempt histograms (retry_attempts, hedge_attempts) use integer buckets 1…10.
  • Common labels:
    • spec — chain spec id (e.g. ETH1, LAV1).
    • apiInterfacejsonrpc, tendermintrpc, rest, grpc.
    • endpoint_id — the configured upstream RPC endpoint.
    • provider_address — node the relay was routed to.
    • method — RPC method name.
    • function — the RPC method / REST path the relay invoked, as carried by the latency histograms and relay counters (same values as method; sum by (...) over it gives the aggregate). Requests to methods outside the spec appear as Default-<method>.
  • Boolean gauges encode 1 = true / healthy / present, 0 = false / unhealthy / absent.
  • Protocol version gauges encode major*1e6 + minor*1e3 + patch.
  • Metrics are registered with registerOrReuse, which returns the already-registered collector instead of panicking on a duplicate — so re-registration (e.g. across test runs sharing the default registry) is safe.

Counting semantics — relays vs client requests

Verified against a live router with a controlled load; these distinctions matter for any dashboard or alert built on the request counters:

  • smartrouter_requests_total counts relays, not client requests. A cross-validated request increments it once per participant, cache-served requests appear under provider_address="Cached", and the router's own chain-tracker / verification traffic lands in it even with zero client load. Use it for per-provider and relay-level views.
  • smartrouter_end_to_end_latency_milliseconds_count increments exactly once per client request (cache hits included, internal probes excluded) — it is the honest source for "requests served" and RPS, and its function label doubles as the per-method breakdown.
  • requests_success_total is transport-level success. An upstream that answers with a JSON-RPC error object (invalid params, method not found, execution reverted) still counts as a successful relay — the error is recorded separately in node_errors_total and the classified smartrouter_errors_total. total − success therefore measures transport/routing failures, not "callers who got an error".
  • Consistency counters: consistency_total = reads that enforced a minimum seen block, consistency_success_total = checks that passed, and consistency_failed_total = stale responses actually caught. Lazily-registered families (retries, hedge, cache, cross-validation, ws, classified errors) are absent from /metrics until the feature first fires — an absent family means zero events, not missing instrumentation.

Smart Router metrics

These are the metrics specific to running as a Smart Router, defined in smartrouter_metrics_manager.go. They split into endpoint-scoped (rpc_endpoint_*) and router-scoped (smartrouter_*) families.

Endpoint-scoped — rpc_endpoint_*

Metric Type Labels Description
rpc_endpoint_total_relays_serviced Counter spec, apiInterface, endpoint_id, function Relays successfully served by this endpoint.
rpc_endpoint_total_errored Counter spec, apiInterface, endpoint_id, function Errored relays for this endpoint.
rpc_endpoint_requests_in_flight Gauge spec, apiInterface, endpoint_id, function Relays currently in flight to this endpoint.
rpc_endpoint_end_to_end_latency_milliseconds Histogram spec, apiInterface, endpoint_id, function End-to-end latency per function for this endpoint.
rpc_endpoint_overall_health Gauge spec, apiInterface, endpoint_id Endpoint health (1 healthy / 0 unhealthy).
rpc_endpoint_overall_health_breakdown Gauge spec, apiInterface Aggregate health per chain/interface.
rpc_endpoint_selection_score Gauge spec, apiInterface, endpoint_id, score_type Selection scores by score_type (availability / latency / sync / stake / composite).
rpc_endpoint_latest_block Gauge spec, apiInterface, endpoint_id Latest block reported by the endpoint.
rpc_endpoint_fetch_latest_fails Counter spec, apiInterface, endpoint_id Failed latest-block fetches.
rpc_endpoint_fetch_block_fails Counter spec, apiInterface, endpoint_id Failed specific-block fetches.
rpc_endpoint_fetch_latest_success Counter spec, apiInterface, endpoint_id Successful latest-block fetches.
rpc_endpoint_fetch_block_success Counter spec, apiInterface, endpoint_id Successful specific-block fetches.

Optimizer

Metric Type Labels Description
rpc_optimizer_selection_score Gauge spec, endpoint_id, score_type Periodic optimizer selection score per node, by score_type.

Router-scoped — smartrouter_*

Core relay & health

Metric Type Labels Description
smartrouter_total_relays_serviced Counter spec, apiInterface, function Relays served by the router.
smartrouter_total_errored Counter spec, apiInterface, function Errored relays.
smartrouter_end_to_end_latency_milliseconds Histogram spec, apiInterface, function Router-level end-to-end latency.
smartrouter_overall_health Gauge Overall router health (1 / 0).
smartrouter_overall_health_breakdown Gauge spec, apiInterface Per-chain/interface health.
smartrouter_latest_block Gauge spec, apiInterface Latest block known to the router.
smartrouter_protocol_version Gauge version Encoded protocol version.

WebSocket

Metric Type Labels Description
smartrouter_ws_connections_active Gauge spec, apiInterface Active WebSocket connections.
smartrouter_ws_subscriptions_total Counter spec, apiInterface Total WebSocket subscription requests.
smartrouter_ws_subscription_errors_total Counter spec, apiInterface Failed WebSocket subscription requests.

Request breakdown

requests_total = success + failed. read/write partition by statefulness; debug_trace and archive are orthogonal addon flags; batch is mutually exclusive with read/write.

Metric Type Labels Description
smartrouter_requests_total Counter spec, apiInterface, provider_address, method All requests.
smartrouter_requests_success_total Counter spec, apiInterface, provider_address, method Successful requests.
smartrouter_requests_failed_total Counter spec, apiInterface, provider_address, method Failed requests.
smartrouter_requests_read_total Counter spec, apiInterface, provider_address, method Read (stateless) requests.
smartrouter_requests_write_total Counter spec, apiInterface, provider_address, method Write (stateful) requests.
smartrouter_requests_debug_trace_total Counter spec, apiInterface, provider_address, method Debug/trace addon requests.
smartrouter_requests_archive_total Counter spec, apiInterface, provider_address, method Archive requests.
smartrouter_requests_batch_total Counter spec, apiInterface, provider_address, method Batch requests.

Errors

Metric Type Labels Description
smartrouter_node_errors_total Counter spec, apiInterface, provider_address, method Node errors returned by endpoints.
smartrouter_protocol_errors_total Counter spec, apiInterface, provider_address, method Protocol/transport errors (connection/session failures).

Retries

Metric Type Labels Description
smartrouter_retries_total Counter spec, apiInterface, method Retry attempts triggered (beyond the first try).
smartrouter_retries_success_total Counter spec, apiInterface, method Retried requests that succeeded.
smartrouter_retries_failed_total Counter spec, apiInterface, method Retried requests that failed.
smartrouter_retry_attempts Histogram spec, apiInterface, method Attempts per retried request (buckets 1…10).

Consistency

Metric Type Labels Description
smartrouter_consistency_total Counter spec, apiInterface, method Requests enforcing consistency (seenBlock).
smartrouter_consistency_success_total Counter spec, apiInterface, method Consistency-enforced requests that succeeded.
smartrouter_consistency_failed_total Counter spec, apiInterface, method Consistency-enforced requests that failed.

Hedging

Metric Type Labels Description
smartrouter_hedge_total Counter spec, apiInterface, method Hedge (batch-ticker) relays sent.
smartrouter_hedge_success_total Counter spec, apiInterface, method Hedged requests that succeeded.
smartrouter_hedge_failed_total Counter spec, apiInterface, method Hedged requests that failed.
smartrouter_hedge_attempts Histogram spec, apiInterface, method Hedge relays per request (buckets 1…10).

Cross-validation

Metric Type Labels Description
smartrouter_cross_validation_requests_total Counter spec, apiInterface, method Cross-validated requests.
smartrouter_cross_validation_success_total Counter spec, apiInterface, method Requests that reached consensus.
smartrouter_cross_validation_failed_total Counter spec, apiInterface, method Requests that failed to reach consensus.
smartrouter_cross_validation_provider_agreements_total Counter spec, apiInterface, method, provider_address Times a node agreed with consensus.
smartrouter_cross_validation_provider_disagreements_total Counter spec, apiInterface, method, provider_address Times a node disagreed with consensus.
smartrouter_cross_validation_mismatch_total Counter spec, apiInterface, method, group, finality Content outliers by group: one increment per distinct outlier group per successful deterministic cross-validation request (a response whose SHA256(reply.data) diverged from the reached consensus). Only emitted when a quorum was reached. finality is finalized / not_finalized / unknown; post-finality divergence is the high-signal alert. Bounded cardinality (keyed by operator-defined group, not node address).
smartrouter_cross_validation_failures_total Counter spec, apiInterface, method, reason Failures by reason — the by-reason breakdown of cross_validation_failed_total (which stays unlabeled, so existing dashboards are unaffected). reason is a closed enum: quorum-time no-agreement / insufficient-responses / diversity-unmet / group-quorum-unmet, or request-time structural insufficient-capacity / insufficient-groups. Separates a structural failure (client should fall back) from a quorum disagreement (a retry may help).

Cache

Metric Type Labels Description
smartrouter_cache_requests_total Counter spec, apiInterface, method Cache lookup attempts.
smartrouter_cache_success_total Counter spec, apiInterface, method Cache hits.
smartrouter_cache_failed_total Counter spec, apiInterface, method Cache misses.
smartrouter_cache_latency_milliseconds Histogram spec, apiInterface, method Cache lookup latency.

CSM state-store sizes (diagnostics)

Expose otherwise black-box Consumer-Session-Manager state so integration tests can assert /debug/reset-all emptied each store. All drop to 0 after a reset.

Metric Type Labels Description
smartrouter_csm_blocked_providers Gauge spec, apiInterface Size of the previous-epoch blocked-providers store.
smartrouter_csm_blocked_backup_providers Gauge spec, apiInterface Size of the blocked-backup-providers store.
smartrouter_csm_sticky_sessions Gauge spec, apiInterface Live sticky-session affinities.
smartrouter_csm_reported_providers Gauge spec, apiInterface Size of the reported-providers register.

Shared metrics

Classified errors — smartrouter_errors_*

Defined in error_metrics.go. The error_name and error_category labels come from the classifier registry — see Error codes for the full set of names and their retryability.

Metric Type Labels Description
smartrouter_errors_total Counter error_name, error_category, retryable, chain_id Errors classified by name, category, retryability, and chain.