The HTTP Log Policy lets you send request and response logs to an HTTP server.
Note: If the
max_batch_sizeargument > 1, a request is logged as an array of JSON objects.
The HTTP Log Policy lets you send request and response logs to an HTTP server.
Note: If the
max_batch_sizeargument > 1, a request is logged as an array of JSON objects.
This Policy logs request and response data for each proxied request.
The AI Gateway process error file is the Nginx error file. You can find it at the following path:
$PREFIX/logs/error.log
Configure the prefix in kong.conf.
Every request is logged separately as a JSON object, separated by a new line \n.
When a request is proxied to an LLM service through an AI Model, the log entry also includes an ai.proxy object with the provider, model, token usage, cost, and latency for that request.
{
"workspace": "b4a1e9a2-6b4a-4e91-9c2e-3b6a9d8f1c72",
"workspace_name": "default",
"source": "upstream",
"upstream_uri": "/v1/chat/completions",
"upstream_status": 200,
"client_ip": "192.168.65.1",
"started_at": 1787113201719,
"tries": [
{
"ip": "162.159.140.245",
"port": 443,
"hostname": "api.openai.com",
"balancer_latency": 0,
"balancer_start": 1787113201722,
"keepalive": true
}
],
"request": {
"id": "9ec9264afbbbad5fe5c64877d92eeb04",
"uri": "/v1/chat/completions",
"url": "http://localhost:8000/v1/chat/completions",
"method": "POST",
"size": 323,
"querystring": {},
"headers": {
"host": "localhost:8000",
"user-agent": "curl/8.7.1",
"content-type": "application/json",
"content-length": "94",
"authorization": "REDACTED"
}
},
"response": {
"status": 200,
"size": 1845,
"headers": {
"content-type": "application/json",
"content-length": "847",
"date": "Wed, 19 Aug 2026 04:20:02 GMT",
"server": "cloudflare",
"via": "1.1 kong/2.0.2-ai-gateway",
"x-kong-request-id": "9ec9264afbbbad5fe5c64877d92eeb04",
"x-kong-proxy-latency": "3",
"x-kong-upstream-latency": "970",
"x-kong-llm-model": "openai/gpt-4o",
"x-ratelimit-remaining-requests": "4999",
"x-ratelimit-remaining-tokens": "799993",
"openai-organization": "org-example123456",
"openai-project": "proj_example7890abcd"
}
},
"latencies": {
"kong": 3,
"proxy": 970,
"request": 976,
"receive": 3
},
"service": {
"id": "947a4e23-b483-5a65-8165-da9aed24565b",
"name": "ai-gateway",
"host": "ai-gateway.upstream.local",
"port": 80,
"protocol": "http"
},
"route": {
"id": "8ae36805-da7a-55b9-b056-72bde6bb937d",
"name": "openai-chat",
"paths": ["/v1/chat/completions"],
"methods": ["POST"]
},
"ai": {
"proxy": {
"tried_targets": [
{
"route_type": "llm/v1/chat",
"provider": "openai",
"host": "api.openai.com",
"port": 443,
"upstream_scheme": "https",
"upstream_uri": "/v1/chat/completions",
"model": "gpt-4o"
}
],
"meta": {
"request_mode": "oneshot",
"provider_name": "openai",
"request_model": "gpt-4o",
"response_model": "gpt-4o-2024-08-06",
"operation_name": "chat",
"llm_latency": 972,
"plugin_id": "f3adc007-171c-5519-8763-3a0eef79bde3"
},
"usage": {
"prompt_tokens": 13,
"completion_tokens": 12,
"total_tokens": 25,
"cost": 0,
"time_per_token": 81,
"time_to_first_token": 971
}
}
}
}The following table describes the core objects in the log. For a full breakdown of the ai.* fields shown in the previous example, see AI Gateway logs.
|
Log item |
Description |
|---|---|
service
|
Properties of the AI Gateway Service associated with the requested Route. |
route
|
Properties of the specific Route requested. |
request
|
Properties of the request sent by the client. |
response
|
Properties of the response sent to the client. |
latencies
|
Latency data for the request. |
tries
|
A list of iterations made by the load balancer for this request, including each upstream target that was tried. |
client_ip
|
The original client IP address. |
upstream_uri
|
The URI, including query parameters, for the configured upstream service. |
consumer
|
The authenticated AI Consumer. Only present if authentication is enabled. |
started_at
|
The Unix timestamp of when the request started to be processed. |
source
|
Indicates whether the response is generated by kong or upstream.
|
upstream_status
|
The status code received from the upstream service in the response. |
ai
|
Present only for requests proxied to an LLM. Contains provider, model, usage, cost, and cache metrics, keyed by Policy name (for example, ai.proxy).
|
The HTTP Log Policy uses internal queues to decouple the production of log entries from their transmission to the upstream server.
With queuing, entries are placed in a configurable queue before being sent in batches to the upstream server. This has the following benefits:
Note: Because queues are structural elements for components in AI Gateway, they only live in the main memory of each worker process and aren’t shared between workers. Therefore, queued content isn’t preserved under abnormal operational situations, like power loss or unexpected worker process shutdown due to memory shortage or program errors.
You can configure several parameters for queuing:
|
Parameters |
Description |
|---|---|
Queue capacity limits:
config.queue.max_entries
config.queue.max_bytes
config.queue.max_batch_size
|
Configure sizes for various aspects of the queue: maximum number of entries, batch size, and queue size in bytes.
When a queue reaches the maximum number of entries and another entry is enqueued, the oldest entry in the queue is deleted to make space for the new entry. The queue code logs a warning when it reaches a capacity threshold of 80% and when it starts to delete entries from the queue, and logs again when the situation normalizes. |
Timer usage:
config.queue.concurrency_limit
|
Only one timer is used to start queue processing in the background by default. Once the queue is empty, the timer handler terminates, and a new timer is created as soon as a new entry is pushed onto the queue. |
Retry logic:
config.queue.initial_retry_delay
config.queue.max_coalescing_delay
config.queue.max_retry_delay
config.queue.max_retry_time
|
If a queue fails to process, it can automatically retry if the failure is temporary, for example due to network problems or upstream unavailability. |
In contrast to other Policies that use queues, all HTTP Log Policy instances that have the same values for the following parameters share one queue:
The config.custom_fields_by_lua configuration lets you dynamically modify log fields using Lua code. The following example configuration removes the route field from the logs:
New fields can be added the same way:
Dot characters (.) in the field key create nested fields. Use a backslash \ to escape a dot if you want to keep it as part of a flat field name instead of nesting it. For example, [my_entry.log\.field] produces a my_entry object with a single log.field key, instead of nesting into log and field.
AI Gateway logs the outcome of an LLM request under a nested ai object, for example ai.$POLICY_NAME.meta, ai.$POLICY_NAME.usage, and, when payload logging is enabled, ai.$POLICY_NAME.payload.request and ai.$POLICY_NAME.payload.response. Because custom_fields_by_lua keys are split into nested table accesses the same way, you can use the same unescaped, dotted-key syntax to remove or override those fields.
For example, to stop logging LLM request and response payloads:
Note: Escaping the dots (for example,
ai\.http-log\.payload\.request) targets a literal flat key instead of the nestedai.http-log.payload.requestfield, so it won’t match. Use unescaped dots to target AI Gateway fields.
Because HTTP Log applies custom_fields_by_lua in its own log phase, which runs after AI Gateway sets the ai.* fields on the request, it can override or remove any ai.* field. The reverse isn’t possible, since AI Gateway can’t run after a logging Policy’s log phase to override a field the Policy already set.
All logging Policies use the same table for logging. If you set config.custom_fields_by_lua in one Policy, all logging Policies that run after it also use that configuration. For example, if you configure fields in the File Log Policy, those same fields appear in the Syslog Policy too, since File Log executes first.
kong.log.set_serialize_value so the function is applied predictably and is easier to manage.return nil in the File Log Policy’s custom_fields_by_lua configuration.Lua code runs in a restricted sandbox environment, whose behavior is governed by the untrusted_lua configuration.
As this code runs in the log phase, only PDK methods that can run in that phase can be used.
When does the HTTP Log Policy record log entries in a request/response timeline?
The log is executed after AI Gateway sends the last response byte to the client.
Can the HTTP Log Policy expose latency metrics for individual phases of the request lifecycle (such as rewrite, access, header_filter, and body_filter)?
The HTTP Log Policy doesn’t provide latency metrics at this granular level. Instead, use Konnect Debugger.