Skip to content

Stats

The stats block is the empty object — its sole purpose is to enable the stats subsystem by being present. There are no configurable fields.

Usage

json
{
  "stats": {}
}

Once stats is present, the stats engine starts collecting per-user and per-outbound byte counters. Those counters are then exposed two different ways:

  • gRPC — turn on StatsService under api and call StatsService/GetStats from an external client.
  • HTTP / Prometheus — turn on metrics instead.

Which counters are populated is controlled by policy:

  • policy.levels[N].statsUserUplink / statsUserDownlink / statsUserOnline enable per-user counters for users at that level.
  • policy.system.statsInboundUplink / statsInboundDownlink / statsOutboundUplink / statsOutboundDownlink enable system-wide counters by inbound and outbound tag.

Notes

  • StatsConfig.Build (infra/conf/xray.go:342-344) returns a zero-value stats.Config{} regardless of input. The block is a marker.
  • Without a corresponding policy flag, the counters exist but stay at zero — common gotcha when stats appear "broken".

Source: infra/conf/xray.go:339-344 · v26.6.1 (94ffd50)

Core Tutorial by Argsment