Prometheus exporter

The vastnfs-exporter is an optional HTTP server that exposes VastNFS RPC transport statistics for Prometheus. It runs on NFS client hosts (the host that mounts VastNFS exports) and reads kernel debugfs/sysfs — the NFS server is out of scope.

The exporter mirrors the discovery logic of vastnfs-ctl: it walks VastNFS mount RPC transports and publishes per-operation counters (same source as rpc-transports-stats), live per-transport queue depths (same sysfs fields as rpc-transports), transport state flags, and per-mount config (vastnfs_mount_info).

Default listen address: 0.0.0.0:9001. Endpoints:

PathDescription
/metricsPrometheus text exposition
/Minimal health/index body

Build (optional)

Default package builds omit the exporter. Include it when building packages:

./build.sh bin --with-exporter

With --with-exporter, packages add python3 and python3-prometheus-client (>= 0.16) as runtime dependencies and install the exporter files listed below. See Building packages for other build.sh bin flags.

The exporter source must be committed before ./build.sh src — the packaging scripts use git archive HEAD, which ships only committed files.

Install paths

After installing a package built with --with-exporter:

FileRPM pathDEB path
Python modules (exporter.py, metrics.py, discovery.py, version)/usr/share/vastnfs-exporter//usr/share/vastnfs-exporter/
Wrapper script/usr/bin/vastnfs-exporter/usr/bin/vastnfs-exporter
systemd unit/usr/lib/systemd/system/vastnfs-exporter.service/lib/systemd/system/vastnfs-exporter.service

The wrapper executes python3 /usr/share/vastnfs-exporter/exporter.py "$@".

The service unit is installed but not auto-enabled. After package install:

sudo systemctl enable --now vastnfs-exporter

Verify:

curl -s localhost:9001/metrics | head

Prerequisites

The exporter reads kernel debugfs and sysfs, not /proc mountstats. debugfs must be mounted at /sys/kernel/debug. Most distributions mount it at boot; verify with:

mount | grep debugfs
ls /sys/kernel/debug/vastnfs

If debugfs is not mounted, RPC metrics stay empty and vastnfs_exporter_vastnfs_present is 0. Mount manually if needed:

sudo mount -t debugfs none /sys/kernel/debug

Paths the exporter uses:

PathFilesystemRole
/sys/kernel/debug/vastnfs/nfs_sb/*debugfsIdentify VastNFS mounts (not present in upstream Linux NFS)
/sys/kernel/debug/vastnfs/nfs_clnt/*debugfsMap NFS clients to rpc_clnt IDs
/sys/kernel/debug/sunrpc/rpc_xprt/*/extradebugfsPer-operation RPC counters (per-op stats)
/sys/kernel/debug/sunrpc/rpc_xprt/*/infodebugfsTransport id, netid, addr, port labels
/sys/kernel/sunrpc/rpc-clients/, xprt-switches/sysfsTraverse RPC client → xprt-switch → transport IDs
/sys/kernel/sunrpc/xprt-switches/*/xprt*/xprt_statesysfsTransport state flags (CONNECTED, BOUND, etc.)
/sys/kernel/sunrpc/xprt-switches/*/xprt*/xprt_infosysfsLive queue depths (binding_q_len, sending_q_len, etc.)

Discovery walks VastNFS NFS clients, resolves each to an RPC client and its transports via sysfs, then reads per-op counters from debugfs and queue depths and state flags from sysfs for those transports only.

Debugfs files are root-owned and often mode 0400; /sys/kernel/debug itself is often mode 700. The packaged service runs as unprivileged vastnfs-exporter with the capabilities needed to traverse and read these paths (same requirement as sudo vastnfs-ctl).

systemd

The vastnfs-exporter service runs as a dedicated unprivileged user (vastnfs-exporter) with systemd hardening enabled. The unit declares RequiresMountsFor=/sys/kernel/debug so the service does not start until debugfs is mounted.

Manual run

Packaged binary

sudo systemctl stop vastnfs-exporter   # if running as a service
sudo vastnfs-exporter                  # listens on 0.0.0.0:9001
curl -s localhost:9001/metrics

Flags

FlagDefaultDescription
--host0.0.0.0Listen address
--port9001Listen port
--shutdown-timeout5Grace period after SIGTERM/SIGINT before exit (seconds)

Manual runs need root (or CAP_SYS_ADMIN + CAP_DAC_READ_SEARCH) to read debugfs, same as vastnfs-ctl.

Metrics

The exporter uses a private Prometheus registry (no default python_* or process_* series).

Labels

Per-transport labels used across RPC metrics:

LabelDescriptionExample
xprt_idKernel RPC transport ID2
netidRPC network IDtcp, rdma
addrRemote endpoint192.168.23.11:2049

RPC counter metrics add op (RPC operation name, e.g. READ, WRITE, GETATTR). Queue length gauges and vastnfs_rpc_xprt_state use only xprt_id, netid, and addr (state gauges also add state; see below). Exporter-level state and self-observability metrics have no transport labels.

RPC counters (per transport, per operation)

Each counter is a cumulative total with labels xprt_id, netid, addr, and op. All-zero per-op rows are omitted (same filter as vastnfs-ctl rpc-transports-stats).

MetricDescription
vastnfs_rpc_xprt_ops_totalTotal RPC operations
vastnfs_rpc_xprt_trans_totalTotal RPC transmissions
vastnfs_rpc_xprt_timeouts_totalTotal RPC timeouts
vastnfs_rpc_xprt_bytes_sent_totalTotal bytes sent
vastnfs_rpc_xprt_bytes_received_totalTotal bytes received
vastnfs_rpc_xprt_queue_milliseconds_totalCumulative queue wait time (ms); per-op q_ms column in rpc-transports-stats — not an instantaneous queue depth
vastnfs_rpc_xprt_rtt_milliseconds_totalTotal round-trip time (ms)
vastnfs_rpc_xprt_execute_milliseconds_totalTotal execute time (ms)
vastnfs_rpc_xprt_errors_totalTotal RPC errors

Queue length gauges (per transport)

Instantaneous queue depths for each VastNFS mount transport. These are Prometheus gauges (current depth), not cumulative counters. Source: sysfs xprt_info (key=value lines), matching the binding_q_len, sending_q_len, and related fields printed by vastnfs-ctl rpc-transports.

Do not confuse these with vastnfs_rpc_xprt_queue_milliseconds_total above — that counter is cumulative wait time from debugfs per-op stats (q_ms).

MetricSysfs fieldDescription
vastnfs_rpc_xprt_binding_queue_lengthbinding_q_lenTasks waiting for bind/rpcbind
vastnfs_rpc_xprt_sending_queue_lengthsending_q_lenTasks waiting to send
vastnfs_rpc_xprt_pending_queue_lengthpending_q_lenTasks in flight (awaiting reply)
vastnfs_rpc_xprt_backlog_queue_lengthbacklog_q_lenTasks waiting for a free request slot
vastnfs_rpc_xprt_tasks_queue_lengthtasks_queuelenTotal tasks associated with this transport

Labels: xprt_id, netid, addr.

One series set per mount transport each scrape. Queue gauges are omitted when xprt_info is unreadable or the kernel reports <closed> (disconnected transports). Switch-level queue_len from rpc-switches is not exported.

During reconnection a transport may show state flags (e.g. CONNECTING) in vastnfs_rpc_xprt_state while queue gauges are absent — the kernel does not expose xprt_info queue fields until the transport is connected.

Transport state

vastnfs_rpc_xprt_state is a gauge set to 1 for each active state flag on a transport. A transport in CONNECTED BOUND emits two series (one per flag). Common state values: CONNECTED, BOUND, CONNECTING, CLOSE, DISCONN.

Labels: xprt_id, netid, addr, state.

Mount configuration

vastnfs_mount_info — gauge 1 per mount. Labels: nfs_id, mountpoint, proto (effective transport), options (NFS mount options from /proc/self/mountinfo, joined to nfs_sb via sb_id). Independent of xprt metrics.

State gauges (always emitted)

MetricValuesDescription
vastnfs_exporter_vastnfs_present0 or 11 when /sys/kernel/debug/vastnfs exists
vastnfs_exporter_mount_countnon-negative integerNumber of VastNFS mounts exported this scrape
vastnfs_exporter_xprt_countnon-negative integerNumber of VastNFS mount transports exported this scrape

These gauges are emitted on every scrape, including when RPC collection fails (xprt_count0; mount_count follows mount discovery).

Self-observability

MetricTypeDescription
vastnfs_exporter_build_infoinfoBuild version (version label)
vastnfs_exporter_scrape_duration_secondsgaugeWall-clock time of the last collection
vastnfs_exporter_collection_errors_totalcounterFailed collection attempts

Behavior when VastNFS or debugfs is absent

The exporter process stays up. /metrics always returns HTTP 200 — never 5xx for collection failures.

When VastNFS is not loaded, debugfs is not mounted, or VastNFS is loaded but there are no mounts yet, the scrape contains no vastnfs_rpc_xprt_* series. State gauges are still emitted so operators can tell why the scrape is empty:

Conditionvastnfs_exporter_vastnfs_presentvastnfs_exporter_xprt_countRPC metrics
debugfs not mounted / vastnfs not loaded00absent
vastnfs loaded, no mounts10absent
vastnfs loaded, mounts active1> 0present

See also


Document generated on 2026.09.14 19:54 for v4.5.9, branch 4.5