Skip to main content
Version: Next

Router Access Log Fields Reference

Kthena emits one access-log entry after each /v1/* inference request. Requests routed through Gateway API on other paths currently do not emit an access-log entry. Each recorded entry contains the HTTP result, routing selection, token counts, timing checkpoints, and any router error captured during processing.

Formats and defaults

Access logs support two formats:

  • text is the current Helm default and preserves existing installations.
  • json is recommended for log aggregation and field-based queries, but must be enabled explicitly.

The text representation is a single line with this shape:

[timestamp] "METHOD /path PROTOCOL" status_code [error=type:message] [model_name=name] [model_route=route] [model_server=server] [selected_pod=pod] [request_id=id] [gateway=gateway] [http_route=route] [inference_pool=pool] [tokens=input/output] timings=totalms(request+upstream+response)

Fields in square brackets are omitted when no value is available. JSON uses the names in the tables below.

HTTP fields

FieldTypePresenceDescriptionExample
timestampRFC3339 timestampAlwaysTime the router received the request2026-01-09T14:35:22.147Z
methodStringAlwaysHTTP methodPOST
pathStringAlwaysURL path only; the query string is not included/v1/chat/completions
protocolStringAlwaysHTTP protocol reported by GoHTTP/1.1
status_codeIntegerAlwaysFinal HTTP response status200

Error fields

The error object is omitted from JSON when the router did not record an error. In text logs it appears immediately after the status code.

FieldTypeDescriptionExample
error.typeStringStable error category assigned by the routerpod_discovery
error.messageStringDiagnostic message for this failureno available pods for model server: default/llama2-server

Current router error categories are:

Error typeFailure area
request_parsingRequest body or required model field could not be parsed
prompt_parsingPrompt extraction failed
input_rate_limitInput-token limit was exceeded
output_rate_limitOutput-token limit was exceeded
rate_limitGeneral request/token rate limit was exceeded
model_server_matchingNo matching ModelServer could be selected
pod_discoveryBackend pod lookup failed or returned no available pods
inference_pool_selectionA matched HTTPRoute had no eligible InferencePool backend
inference_pool_discoveryThe selected InferencePool could not be found
port_discoveryAn InferencePool had no usable target port
route_not_foundNeither ModelRoute nor HTTPRoute routing matched
schedulingQueue admission or backend scheduling failed
proxyForwarding to the selected backend failed

An HTTP status is not uniquely determined by error.type; consult status_code for the actual result.

Model and routing fields

FieldTypePresenceDescriptionExample
model_nameStringAlways in JSON; may be empty when parsing failsModel requested by the clientllama2-7b
model_routeStringWhen selectedNamespaced ModelRoutedefault/llama2-route-v1
model_serverStringWhen selectedNamespaced ModelServerdefault/llama2-server
selected_podStringWhen selectedBackend pod namellama2-deployment-5f7b8c9d-xk2p4
request_idStringNormally presentIncoming x-request-id, or an ID generated by the access-log middleware550e8400-e29b-41d4-a716-446655440000
gatewayStringGateway API requestsNamespaced Gatewaydefault/inference-gateway
http_routeStringHTTPRoute requestsNamespaced HTTPRoutedefault/inference-route
inference_poolStringInference Extension requestsNamespaced InferencePooldefault/llama2-pool

Token fields

FieldTypePresenceDescriptionExample
input_tokensIntegerJSON omits zeroPrompt-token count calculated by the router150
output_tokensIntegerJSON omits zeroCompletion-token count parsed from the backend response when available75

Text output includes tokens=input/output when either count is nonzero.

Timing fields

All timing values are integer milliseconds.

FieldTypeDescriptionExample
duration_totalIntegerEnd-to-end time from receipt until access-log finalization2350
duration_request_processingIntegerInitial router parsing and tokenization phase45
duration_upstream_processingIntegerMarked backend-proxy phase2180
duration_response_processingIntegerMarked response-processing phase5

There is no duration_queue field and no access-log field uses an _ms suffix. duration_total is authoritative. The phase fields are independently rounded checkpoints and may not sum to the total, including when rate limiting, routing, scheduling, or queue time falls between marked phases.

Examples

Successful JSON entry

{
"timestamp": "2026-01-09T14:35:22.147Z",
"method": "POST",
"path": "/v1/chat/completions",
"protocol": "HTTP/1.1",
"status_code": 200,
"model_name": "llama2-7b",
"model_route": "default/llama2-route-v1",
"model_server": "default/llama2-server",
"selected_pod": "llama2-deployment-5f7b8c9d-xk2p4",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"input_tokens": 150,
"output_tokens": 75,
"duration_total": 2350,
"duration_request_processing": 45,
"duration_upstream_processing": 2180,
"duration_response_processing": 5
}

Failed JSON entry

{
"timestamp": "2026-01-09T14:35:28.456Z",
"method": "POST",
"path": "/v1/chat/completions",
"protocol": "HTTP/1.1",
"status_code": 503,
"error": {
"type": "pod_discovery",
"message": "no available pods for model server: default/llama2-server"
},
"model_name": "llama2-7b",
"request_id": "660e8400-e29b-41d4-a716-446655440001",
"input_tokens": 200,
"duration_total": 51,
"duration_request_processing": 4,
"duration_upstream_processing": 47,
"duration_response_processing": 0
}

Text entry

[2026-01-09T14:35:22.147Z] "POST /v1/chat/completions HTTP/1.1" 200 model_name=llama2-7b model_route=default/llama2-route-v1 model_server=default/llama2-server selected_pod=llama2-deployment-5f7b8c9d-xk2p4 request_id=550e8400-e29b-41d4-a716-446655440000 tokens=150/75 timings=2350ms(45+2180+5)

Helm configuration

The root chart uses the following values. The defaults shown here preserve the current text-format behavior:

networking:
kthenaRouter:
accessLog:
enabled: true
format: text
output: stdout

Set format: json explicitly when a structured log pipeline requires JSON.

For the standalone networking subchart, omit the networking prefix:

kthenaRouter:
accessLog:
enabled: true
format: json
output: stdout

Environment variables

The deployment maps Helm values to these router environment variables:

VariableDescriptionHelm defaultAccepted values
ACCESS_LOG_ENABLEDEnable access loggingtrueValues accepted by Go's boolean parser
ACCESS_LOG_FORMATOutput formattexttext, json
ACCESS_LOG_OUTPUTDestinationstdoutstdout, stderr, or a file path

Prefer stdout for Kubernetes workloads. A file path writes inside the router container and requires a mounted volume plus a separate collection strategy.