Metrics¶
All metrics are served at /metrics on the HTTP listener (see
Operations → Observability).
Metric names follow the prefix ipmapper_, with subsystem groupings by
function.
Naming conventions and cardinality¶
Warning
ipmapper_session_updates_per_remote_addr carries an unbounded addr
label. In deployments with many distinct source IPs (e.g. multiple
RADIUS Listener instances or Admin Portal nodes) this counter set grows
without bound. Monitor its cardinality and consider whether you need it
before scraping at high resolution.
Most labels are bounded: command is one of a small fixed set of RESP or
NATS command names, pattern is one of the fixed HTTP API routes, and
action is one of start, update, or stop.
Is the service ready?¶
After a restart the IP Mapper loads its state from Redis before accepting connections. Use these metrics to confirm the load is complete and the service is healthy:
| Metric | Type | Meaning |
|---|---|---|
ipmapper_ready_status |
gauge | 0 while loading from Redis, 1 when ready to serve. |
ipmapper_redis_load_duration_seconds |
histogram | Time taken to load sessions from Redis on startup. |
ipmapper_version |
gauge | Always 1, with the running version in the version label. |
If ipmapper_ready_status stays at 0 longer than expected, check Redis
connectivity and the journal for load errors.
How many sessions are held?¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_state_active_sessions_total |
gauge | Number of sessions currently in the active session table. |
ipmapper_state_stolen_allocations_total |
counter | Number of IP allocations claimed by a new session from an existing one. A non-zero value is normal during IP handover; a steadily rising value may indicate duplicate session IDs. |
ipmapper_state_sid_not_found_total |
counter | Number of times a session ID referenced internally was not found. Should be 0 in normal operation. |
Is the NATS interface healthy?¶
Traffic volume¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_nats_calls_total{command} |
counter | Total NATS calls per command. |
ipmapper_nats_calls_error_total{command} |
counter | NATS calls that returned an error. |
ipmapper_nats_request_size_bytes{command} |
histogram | Request payload size in bytes per command. |
ipmapper_nats_response_size_bytes{command} |
histogram | Response payload size in bytes per command. |
Latency¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_nats_duration_seconds{command} |
histogram | NATS request handling time per command. |
ipmapper_session_batch_duration_seconds{command="set-session-batch"} |
histogram | Processing time for a full batch. |
ipmapper_nats_sessions_per_batch |
histogram | Number of sessions in each set-session-batch call. |
A rising error rate alongside rising latency typically points to lock contention on the session state (see Is the session pipeline keeping up? below).
Is the RESP interface healthy?¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_resp_calls_total{command} |
counter | Total calls per RESP command. |
ipmapper_resp_duration_seconds{command} |
histogram | RESP command handling time. |
ipmapper_session_updates_per_remote_addr{addr} |
counter | Session updates broken down by source. RESP records the calling IP address; NATS and the HTTP API record the fixed labels nats and http. Useful for tracing which upstream is generating load. |
Is the HTTP API healthy?¶
These metrics are only populated when the HTTP session API
is enabled. The pattern label is the matched route — one of /api/v1/sessions,
/api/v1/sessions/batch, /api/v1/sessions/query, or /api/v1/sessions/clean.
Traffic volume¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_http_calls_total{pattern} |
counter | Successful HTTP API calls per endpoint. |
ipmapper_http_calls_error_total{pattern} |
counter | HTTP API calls that returned an error (4xx). |
ipmapper_http_calls_unauthorized_total{pattern} |
counter | Requests rejected for a missing or invalid X-API-Key. A rising value points at a misconfigured client token or unauthorized access attempts. |
ipmapper_http_request_size_bytes{pattern} |
histogram | Request payload size per endpoint. |
ipmapper_http_response_size_bytes{pattern} |
histogram | Response payload size per endpoint. |
Latency¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_http_duration_seconds{pattern} |
histogram | HTTP API request handling time per endpoint. |
ipmapper_http_sessions_per_batch |
histogram | Number of sessions in each POST /api/v1/sessions/batch call. |
ipmapper_session_batch_duration_seconds{command="set-session-batch"} |
histogram | Processing time for a full batch (shared with the NATS batch path). |
Is the session pipeline keeping up?¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_session_updates_total{action} |
counter | Session events by action (start, update, stop). |
ipmapper_session_allocations_per_session |
histogram | Number of IP allocations per session. Sessions with many allocations are more expensive to index. |
ipmapper_session_batch_duration_seconds{command} |
histogram | Processing time for batch and cleanup operations. |
ipmapper_session_cleanup_duration_seconds{command} |
histogram | Time spent in muted-session and expired-session cleanup sweeps. |
High ipmapper_session_cleanup_duration_seconds with a large session count
may indicate that options.expired_sessions_cleanup_interval is too short
for the session volume. Raising it reduces cleanup CPU at the cost of
sessions staying in memory slightly longer after expiry.
Is this instance the active HA replica?¶
These metrics are only meaningful when the Redis HA lock
is enabled. With the lock disabled, ipmapper_has_lock stays at 0 on every
instance.
| Metric | Type | Meaning |
|---|---|---|
ipmapper_has_lock |
gauge | 1 if this instance currently holds the Redis HA lock and is the active replica, 0 otherwise. Exactly one instance per Redis backend should report 1. |
ipmapper_lock_extension_failures |
gauge | Number of consecutive lock-extension failures by the active instance. Resets to 0 on every successful extension. A non-zero value indicates intermittent Redis trouble; the process exits when the elapsed failure time exceeds 70% of the configured lock expiry. |
ipmapper_lock_exit_total{reason} |
counter | Incremented when the active instance exits because of a lock-related error. reason="taken" means another instance grabbed the lock; reason="extend_failed" means lock extension kept failing past the threshold. Useful for diagnosing why a failover happened. |
Each instance scrapes its own copy of ipmapper_has_lock, so to reason
about the HA group as a whole you need to aggregate across the replicas
that share the same Redis backend.
Recommended alerts (assuming a single HA group; add a by (...) clause
if you run multiple groups against separate Redis backends):
sum(ipmapper_has_lock) == 0for more thanexpiry— no instance is currently active (full outage; failover did not complete).sum(ipmapper_has_lock) > 1— more than one instance reports itself as active. This is split brain, should never happen unless the IP Mapper instances are pointing at different Redis backends.max(ipmapper_lock_extension_failures) > 0sustained — the active instance is losing Redis connectivity and is at risk of being forced into a failover. This is not an issue if it happens occasionally but ifipmapper_lock_extension_failuresis frequently > 0 and then recovers, it might indicate stability issues with the connection to Redis.
Is the Redis connection healthy?¶
| Metric | Type | Meaning |
|---|---|---|
ipmapper_redis_ext_requests_total |
counter | Requests sent to Redis for static mapping queries. |
ipmapper_redis_ext_errors_total{error} |
counter | Redis errors for static mapping queries, by error type. |
These metrics cover only the query_static_mappings read path
(see Configuration → options), not the main
session sync pipeline. For the sync pipeline, check the journal stats line
(sent, received, connects) and Redis server metrics.