count
Increment a counter for metrics and monitoring
count
Increments a named counter by 1. Counters are created dynamically on first use without pre-declaration and are accessible via the Management API for monitoring and metrics collection.
Syntax
count "counter_name";
Namespace Behavior
Counters are organized hierarchically using namespaces. The namespace is determined by the presence of :: in the counter name:
Without :: - Current Context Namespace
Counter inherits the full server execution context:
servers {
radius "AUTH_SERVER" {
port 1812;
address 0.0.0.0;
}
}
aaa {
policy "DEFAULT" {
handler "PAP_HANDLER" {
conditions all {
radius.request.code == radius.ACCESS_REQUEST;
}
@final-execute {
count "auth_attempts";
# Creates: server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER::auth_attempts
}
}
}
}
With :: - Custom Namespace
The :: separator creates an explicit namespace hierarchy independent of server context:
handler "MY_HANDLER" {
conditions all {
radius.request.code == radius.ACCESS_REQUEST;
}
@final-execute {
count "custom::metrics::login_count";
# Creates: custom::metrics::login_count
count "myapp::requests";
# Creates: myapp::requests
}
}
See namespace documentation for detailed explanation of hierarchy structure and pattern matching.
Examples
Basic Request Counting
handler "AUTH_HANDLER" {
conditions all {
radius.request.code == radius.ACCESS_REQUEST;
}
@final-execute {
# Count all authentication attempts in current handler namespace
count "total_auth";
match "%{aaa.result}" {
"accept" => {
count "successful";
}
"reject" => {
count "failed";
}
}
}
}
Custom Application Metrics
handler "AUTH_HANDLER" {
conditions all {
radius.request.code == radius.ACCESS_REQUEST;
}
@final-execute {
# Application-specific counters in custom namespace
count "custom::app::requests";
if all {
vars.premium_user == true;
} then {
count "custom::app::premium_users";
}
}
}
Backend Error Tracking
@execute {
try {
backend {
name "SQL";
query "CHECK_USER";
}
} catch {
# Track database errors in custom namespace
count "custom::backend_errors::sql";
reject "Database error: %{aaa.caught_error}";
}
}
Accessing Counter Values
Counters are read-only via the Management API:
# Get counter value (total count)
GET /api/v1/statistics/counter/{namespace}
# Examples:
GET /api/v1/statistics/counter/server/radius-udp/AUTH_SERVER/policy/DEFAULT/handler/PAP_HANDLER/auth_attempts
GET /api/v1/statistics/counter/custom/metrics/login_count
Configuring Counter History
Configure retention and collection intervals using the statistics block. Pattern matching applies to the full namespace path:
statistics {
defaults {
samples 600; # 10 hours at 1m intervals
interval 1m;
}
# Match handler counters (pattern matches anywhere in full namespace path)
# Will match: server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER::auth_attempts
counter /.*::auth.*/ {
samples 8640; # 24 hours at 10s intervals
interval 10s;
}
# Custom application metrics
counter /custom::.*/ {
samples 288; # 24 hours at 5m intervals
interval 5m;
}
}
Pattern matching supports:
- Regex patterns:
/server::.*::error/matches any namespace containing that pattern - Exact matches:
"critical_auth"matches only the leaf counter name - Cascading: Patterns → defaults → built-in defaults (600 samples, 60s interval)
Lua Scripting
Counters can also be incremented from Lua scripts:
-- Simple counter (uses current context namespace)
context.count("auth_attempts")
-- Custom namespace
context.count("custom::metrics::login_count")
Counters vs Cache Increment
Use counters for:
- Permanent metrics that accumulate over server lifetime (never reset)
- Write-only operation in scripts (not readable from Lua/pipeline)
- Monitoring request counts, error rates, success/failure ratios
- Long-term trend analysis with time series history via Management API
- Operational dashboards and alerting
Use cache.increment for:
- Temporary tracking with automatic expiry and reset
- Read/write operations in scripts (can check current value)
- Rate limiting (increment and check within time window)
- Throttling (limit requests per user/IP over sliding window)
- Short-term burst detection with automatic cleanup
See Also
- statistics configuration - Configure counter history and intervals
- cache.increment - Temporary counters with expiry for rate limiting
- set - Assign values to context attributes
- log - Write structured log messages