Skip to content

Metrics

The proxy exposes Prometheus metrics on /metrics when the status server is enabled. Every metric name starts with proxy_tcp_.

This page is organized around the questions an operator asks, not by metric name.

Naming and label cardinality

All labels are bounded, so the metric surface stays small:

  • listener — the configured listener name. Bounded by how many listeners you define.
  • protocolhttp, https, or socks5.
  • directionin (upstream to client, download) or out (client to upstream, upload).
  • resultallow, block, fail_open, or error.
  • stage — one of the lifecycle stages: inspect, decision, dns, dial, proxy, closing.

Target hosts and client IP addresses are deliberately not used as labels; they would be unbounded. Those values appear only on the status page connection table, never in metrics.

Is the proxy receiving and serving traffic?

Metric Type Meaning
proxy_tcp_connections_accepted_total counter Downstream connections accepted, counted at accept time before inspection. Labels: listener, protocol.
proxy_tcp_connections_closed_total counter Connections closed and removed from the active set. Labels: listener, protocol.
proxy_tcp_bytes_total counter Bytes proxied. Label direction (in/out).
proxy_tcp_active_connections gauge Connections currently tracked, at any stage.

Accept rate per listener:

sum by (listener) (rate(proxy_tcp_connections_accepted_total[5m]))

Throughput in bits per second, both directions:

sum by (direction) (rate(proxy_tcp_bytes_total[5m])) * 8

Where are connections in their lifecycle?

These gauges are computed by walking the active registry at scrape time, so they always reflect the current moment.

Metric Type Meaning
proxy_tcp_active_pre_proxy_connections gauge Active connections not yet tunneling — still in inspect, decision, dns, or dial.
proxy_tcp_active_proxying_connections gauge Active connections currently tunneling bytes both ways.
proxy_tcp_active_connections_by_stage gauge Active connection count broken down by stage.
proxy_tcp_active_connection_age_seconds histogram Age distribution of the connections active at scrape time.

A large, sustained proxy_tcp_active_pre_proxy_connections without a matching rise in proxying connections points to clients that connect and never send the first bytes, slow inspection, or a slow decision backend. The per-stage gauge tells you which stage they are piling up in:

proxy_tcp_active_connections_by_stage

Are policy decisions working?

Metric Type Meaning
proxy_tcp_decisions_total counter Remote policy decisions by result.

The result label values:

  • allow — the backend allowed the connection.
  • block — the backend blocked it.
  • fail_open — the backend failed, but the listener's fail_open setting let the connection through.
  • error — the backend failed and the connection was closed.

A non-zero fail_open or error rate means the decision backend is failing. Which one you see depends on each listener's fail_open setting.

sum(rate(proxy_tcp_decisions_total{result=~"fail_open|error"}[5m]))

Block ratio:

sum(rate(proxy_tcp_decisions_total{result="block"}[5m]))
  / sum(rate(proxy_tcp_decisions_total[5m]))

What is failing, and where?

Metric Type Meaning
proxy_tcp_connection_failures_total counter Connections that ended with an error, by the stage that produced the failure.

The stage label points straight at the subsystem: dns failures mean resolution problems, dial failures mean the upstream host was unreachable, decision failures mean the backend errored.

sum by (stage) (rate(proxy_tcp_connection_failures_total[5m]))

How fast are decisions and DNS?

Metric Type Meaning
proxy_tcp_decision_duration_seconds histogram Remote policy decision request duration.
proxy_tcp_dns_duration_seconds histogram Upstream DNS lookup duration.

Each histogram exposes _bucket, _sum, and _count series. The 99th percentile decision latency:

histogram_quantile(0.99, sum by (le) (rate(proxy_tcp_decision_duration_seconds_bucket[5m])))

If decision latency approaches decision.timeout, connections start failing the decision stage.

How big and long-lived are connections?

Metric Type Meaning
proxy_tcp_connection_age_seconds histogram Total lifetime of ended connections, by protocol.
proxy_tcp_connection_bytes histogram Bytes transferred per ended connection, by direction.

These record one observation per closed connection, so they describe completed sessions rather than live ones (use proxy_tcp_active_connection_age_seconds for the connections open right now). The buckets reach multi-day ages and up to a terabyte per connection, so long-lived tunnels and bulk transfers stay on-scale.