Namespaces

Understanding namespace hierarchies in logging and counters

Overview

Namespaces provide hierarchical context for log messages and counters in Radiator. They identify where an activity occurred within the server's execution flow, creating a structured path from the server level down to specific components.

Namespaces use the :: separator to create hierarchies: server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER

Namespace Structure

The namespace hierarchy depends on the execution context:

Server Context (Automatic)

When executing within a handler, the namespace automatically includes the full server context:

server::<transport>::<server>::policy::<policy>::handler::<handler>

Example: server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER

Components:

  • server: Fixed prefix for all server-level operations
  • transport: Transport type (radius-udp, radius-tcp, radsec-tcp)
  • server: Server name from configuration
  • policy: Fixed label separating the policy name
  • policy name: Policy name from configuration
  • handler: Fixed label separating the handler name
  • handler name: Handler name from configuration

Backend Context (Automatic)

Backend counters are in their own top-level backend:: namespace, independent of which server or handler invoked them:

backend::<type>::<name>                         # top-level backend counters
backend::<type>::<name>::query::<query>         # per-query counters
backend::<type>::<name>::statement::<statement> # per-statement counters

Examples:

  • backend::File::FILE_USERS::Totals
  • backend::SQLite::SQL_USERS::query::FIND_USER::Hits
  • backend::SQLite::LAST_LOGIN_DB::statement::UPDATE_LAST_LOGIN::Success

Custom Context (Explicit)

When using :: explicitly in counter names or log namespaces, you create a custom hierarchy independent of server context:

custom::app::requests
myapp::metrics::login_count

Custom namespaces bypass the automatic server context and use only the specified path.

Namespaces in Logging

Every log message includes a namespace array showing its origin:

{
  "timestamp": "2025-01-25T10:30:45.123456+00:00",
  "level": "INFO",
  "namespace": [
    "server",
    "radius-udp",
    "AUTH_SERVER",
    "policy",
    "DEFAULT",
    "handler",
    "PAP_HANDLER"
  ],
  "message": "AAA accept",
  "fields": {
    "username": "alice@example.com"
  }
}

The namespace array is rendered as server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER in counter paths and traditional log formats.

Namespace Depth Examples

ContextNamespace
Server startup["server", "radius-udp", "AUTH_SERVER"]
Policy execution["server", "radius-udp", "AUTH_SERVER", "policy", "DEFAULT"]
Handler pipeline["server", "radius-udp", "AUTH_SERVER", "policy", "DEFAULT", "handler", "PAP_HANDLER"]
Backend counters["backend", "File", "FILE_USERS"]
Backend query["backend", "SQLite", "SQL_USERS", "query", "FIND_USER"]
Configuration["configuration"]

Namespaces in Counters

Counters use namespaces to organize metrics hierarchically. The count action creates counters whose namespace depends on the :: separator:

Context-Inherited Counters

Without ::, counters inherit the current execution context:

servers {
    radius "AUTH_SERVER" { ... }
}

aaa {
    policy "DEFAULT" {
        handler "PAP_HANDLER" {
            conditions all {
                radius.request.code == radius.ACCESS_REQUEST;
            }

            @final-execute {
                count "auth_attempts";
                # Namespace: server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER::auth_attempts
            }
        }
    }
}

Custom Namespace Counters

With ::, counters use the explicit namespace:

@final-execute {
    count "custom::app::requests";
    # Namespace: custom::app::requests

    count "myapp::errors";
    # Namespace: myapp::errors
}

API Access

Counter API

Access counters via the statistics API using the namespace path:

# Full namespace path
GET /api/v1/statistics/counter/server/radius-udp/AUTH_SERVER/policy/DEFAULT/handler/PAP_HANDLER/auth_attempts

# Custom namespace
GET /api/v1/statistics/counter/custom/app/requests

Log Summary API

Query the hierarchical counter tree:

# Get handler-level counters
GET /api/v1/clog/summary?ns=server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER

# Get custom namespace counters
GET /api/v1/clog/summary?ns=custom::app

Prometheus Metrics

Counters are exported to Prometheus with the namespace as a label:

# Context-inherited counter
radiator_log_total{namespace="server::radius-udp::AUTH_SERVER::policy::DEFAULT::handler::PAP_HANDLER",message="auth_attempts"} 1234

# Custom namespace counter
radiator_log_total{namespace="custom::app",message="requests"} 5678

Namespace Best Practices

Use Context-Inherited for Operational Metrics

Let the server context provide natural hierarchy for operational counters:

handler "PAP_HANDLER" {
    @execute {
        count "attempts";
        count "failures";
    }
}

These automatically organize under the handler's namespace.

Use Custom Namespaces for Business Metrics

Create explicit hierarchies for application-specific metrics:

@final-execute {
    count "custom::billing::premium_users";
    count "custom::billing::trial_users";
    count "custom::metrics::api_calls";
}

This keeps business logic separate from server topology.

See Also