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.protocol—http,https, orsocks5.direction—in(upstream to client, download) orout(client to upstream, upload).result—allow,block,fail_open, orerror.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:
Throughput in bits per second, both directions:
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:
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'sfail_opensetting 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.
Block ratio:
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.
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:
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.