> ## Documentation Index
> Fetch the complete documentation index at: https://tyk.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway Access Logs

> Learn how to configure Tyk Gateway to generate API access logs

## Introduction

An Access Log is a single log line written at `info` severity to `stderr` for every request Tyk Gateway handles, giving you a lightweight, real-time record of individual requests. This is a different mechanism from an [API Traffic Log](https://tyk.io/docs/api-management/logs/traffic-logs.md), which also records individual requests but is written to Redis and processed asynchronously by Tyk Pump, carrying richer detail as a result.

Access Logs are generated by the same logger as Tyk Gateway's Application Log, so their severity, format, and third-party output are all controlled by the same shared settings:

* **verbosity**: which severity levels are written (must be `info` or `debug` for Access Logs to be recorded at all)
* **format**: the structure and timestamp style of each entry
* **log output**: where logs are sent, for example to a third-party aggregator

See [Configuring Application and Access Logs](https://tyk.io/docs/api-management/logs.md#configuring-application-and-access-logs) for details of these and how to configure them.

Access Logs have two additional settings of their own, covered below: whether they're generated at all ([Enabling Access Logs](#enabling-access-logs)), and which fields they include ([Access Log Content](#access-log-content)).

## Availability

| Component | Version | Edition |
| :- | :- | :- |
| Tyk Gateway | Available since [v5.8.0](https://tyk.io/docs/developer-support/release-notes/gateway.md#5-8-0-release-notes) | Community & Enterprise |

> [!NOTE]
>
> Access Logs are not available on Tyk Cloud.

## Enabling Access Logs

Access Logs are disabled by default. Set `access_logs.enabled` to `true` to turn them on:

> [tab] Configuration File
>
> Configuration using `tyk.conf`:
>
> ```json theme={null}
> {
>     "access_logs": {
>         "enabled": true
>     }
> }
> ```

> [tab] Environment Variables
>
> Configuration using environment variables:
>
> ```
> TYK_GW_ACCESSLOGS_ENABLED=true
> ```

## Access Log Content

Each Access Log entry contains:

* timestamp
* the log severity (always `info`)
* `prefix`, always set to `access-log`; this identifies the entry as an Access Log, since Application Log entries are written to the same output but use other `prefix` values.
* a configurable list of key-value pairs giving details of the request (for example API ID or HTTP response status code)

For example:

```
time="2025-01-29T08:27:09Z" level=info api_id=b1a41c9a89984ffd7bb7d4e3c6844ded api_key=00000000 api_name=httpbin api_type=oas client_ip="::1" host="localhost:8080" latency_gateway=1 latency_total=62 method=GET org_id=678e6771247d80fd2c435bf3 original_path=/get path=/get prefix=access-log protocol=HTTP/1.1 remote_addr="[::1]:63251" status=200 trace_id=4bf92f3577b34da6a3ce929d0e0e4736 upstream_addr="http://httpbin.org/get" upstream_latency=61 user_agent=PostmanRuntime/7.43.0
```

The keys that will be included in the logs are configured using an [access log template](#access-log-templates). If no template is configured, then all available fields will be included in each log entry. The `prefix` field is always included, whether or not a template is configured.

The full list of available fields that can be included in an access log is [here](#access-log-field-reference).

> [!NOTE]
>
> Field order is predictable, not arbitrary: `time` and `level` always come first, followed by every other field in alphabetical order.

### Access Log Templates

You can define an access log template to reduce the size of the access log by including only a subset of the available fields. This is a simple list of field names declared in the Tyk Gateway configuration as a `template` array within the `access_logs` object.

For example:

> [tab] Configuration File
>
> Configuration using `tyk.conf`
>
> ```json theme={null}
> {
>     "access_logs": {
>         "enabled": true,
>         "template": [
>             "api_key",
>             "remote_addr",
>             "upstream_addr"
>         ]
>     }
> }
> ```

> [tab] Environment Variables
>
> Configuration using environment variables:
>
> ```
> TYK_GW_ACCESSLOGS_ENABLED=true
> TYK_GW_ACCESSLOGS_TEMPLATE="api_key,remote_addr,upstream_addr"
> ```

Output:

```
time="2025-01-29T08:27:48Z" level=info api_key=00000000 prefix=access-log remote_addr="[::1]:63270" upstream_addr="http://httpbin.org/get"
```

Only the three templated fields appear, plus `prefix`, which is always included regardless of the template.

### MCP-Specific Fields

When the log is generated for a request to an MCP Proxy, MCP-specific fields are added to the access log:

* [`mcp_method`](#param-mcp-method)
* [`mcp_primitive_type`](#param-mcp-primitive-type)
* [`mcp_primitive_name`](#param-mcp-primitive-name)
* [`mcp_error_code`](#param-mcp-error-code)

These fields are omitted when empty, so non-MCP logs are unaffected. For the `mcp_error_code` values and logs for proxies generated from a REST API, see [MCP Gateway Access Logs](https://tyk.io/docs/ai-management/mcp-gateway/mcp-access-logs.md).

For example MCP records, see [Example log records](https://tyk.io/docs/ai-management/mcp-gateway/mcp-access-logs.md#example-log-records).

### Access Log Field Reference

**api\_id**

ID of the requested API definition. Present whenever the request matched an API.

**api\_key**

Obfuscated or hashed API key used in the request.

**api\_name**

Name of the requested API definition. Present whenever the request matched an API.

**api\_type**

API type classification. One of `mcp`, `graphql`, `oas`, or `classic`. Always present.

**circuit\_breaker\_state**

Circuit breaker state (for example, `OPEN`), only present on circuit breaker errors.

**client\_ip**

IP address of the client making the request.

**error\_source**

Gateway component that generated the error, only present on error requests.

**error\_target**

Upstream address being accessed, only present on upstream or proxy errors.

**host**

Hostname of the request.

**latency\_gateway**

Time spent in Tyk Gateway's own processing, separate from the upstream round trip.

**latency\_total**

Total time taken to process the request, including upstream latency and additional gateway processing.

**mcp\_error\_code**

JSON-RPC error code when the MCP request fails, from Tyk or from the upstream MCP server's response. Tyk's codes depend on the protocol version the request uses. See [MCP Error Codes](https://tyk.io/docs/ai-management/mcp-gateway/error-codes.md). Only present when an MCP error occurs.

**mcp\_method**

JSON-RPC method called on an MCP Proxy (for example, `tools/call`, `server/discover`, `initialize`, `resources/read`). Only present on MCP Proxy requests.

**mcp\_primitive\_name**

Name of the MCP tool, resource, or prompt that was invoked. Only present on MCP Proxy requests.

**mcp\_primitive\_type**

MCP primitive type invoked: `tool`, `resource`, or `prompt`. Only present on MCP Proxy requests.

**method**

HTTP method used in the request (for example, GET or POST).

**org\_id**

Organisation ID of the requested API definition. Present whenever the request matched an API.

**original\_path**

The client's request path, captured before Tyk Gateway applies any path-modifying middleware, such as stripping the API's listen path. Equal to `path` unless something changes the path during processing.

**path**

URL path of the request.

**protocol**

Protocol used in the request (for example, HTTP/1.1).

**remote\_addr**

Remote address of the client.

**response\_code\_details**

Detailed error description in snake\_case, only present on error requests.

**response\_flag**

Error classification code, only present on error requests. See [Error Classification](#error-classification).

**status**

HTTP response status code.

**tls\_cert\_expiry**

TLS certificate expiration date in RFC 3339 format, only present on TLS certificate errors.

**tls\_cert\_subject**

TLS certificate subject (for example, `CN=api.example.com`), only present on TLS certificate errors.

**trace\_id**

The OpenTelemetry trace ID for the request (32-character hex W3C trace ID). Only present when OpenTelemetry is enabled and a trace ID is available. Use this to navigate from an access log entry to the corresponding trace in your observability backend.

**upstream\_addr**

Full upstream address, including scheme, host, and path.

**upstream\_latency**

Round-trip duration between the gateway sending the request to the upstream service and receiving the response.

**upstream\_status**

HTTP status code returned by the upstream, only present when the upstream responds with a 5XX status.

**user\_agent**

User agent string provided by the client.

## Error Classification

Access logs include a small set of additional fields when a request fails, so you can diagnose problems, such as TLS certificate expiry, connection refusal, or authentication errors, directly from the log without cross-referencing application or API Traffic Logs. Whether a given field appears depends on the specific error; each field's exact conditions are noted in [Access Log Field Reference](#access-log-field-reference) above. Two fields anchor this classification: `response_flag` and `error_source`.

> [!NOTE]
>
> Error classification fields are omitted entirely, not set to an empty string or zero, when they don't apply. This keeps successful requests and errors that don't trigger a given field unchanged.

### Response Flags

A response flag is a short, fixed code, such as `UCF` or `AKI`, that classifies the specific error condition Tyk Gateway encountered while processing the request. `response_flag` values are shared with Tyk Gateway's [error response customization](https://tyk.io/docs/api-management/custom-error-responses.md) feature, which uses the same flags to match errors you want to override. See the [Flag Reference](https://tyk.io/docs/api-management/custom-error-responses.md#flag-reference) there for the full list, what each one means, and its typical HTTP status.

### Error Source

`error_source` identifies the Gateway component that generated the error, helping you locate where in the request pipeline the failure occurred. It's present alongside `response_flag` on every error entry.

| error\_source | Component | Typical flags |
| :- | :- | :- |
| `ReverseProxy` | Upstream proxy and transport layer | `UCF`, `TLE`, `URT`, `DNS`, `CBO`, `NHU` |
| `Upstream` | The upstream server itself (responded with error) | `URS` |
| `AuthKey` | Auth Token middleware | `AMF`, `AKI`, `TKE` |
| `Oauth2KeyExists` | OAuth2 middleware | `AMF`, `AKI`, `EAD` |
| `JWTMiddleware` | JWT middleware | `AMF`, `TKI`, `TCV`, `TKE` |
| `BasicAuthMiddleware` | Basic Auth middleware | `AMF`, `IHD`, `BIV` |
| `RateLimitAndQuotaCheck` | Rate limiting and quota middleware | `RLT`, `QEX` |
| `APIRateLimitMiddleware` | API-level rate limiting | `RLT` |
| `RequestSizeLimitMiddleware` | Request size limit middleware | `BTL`, `CLM` |
| `ValidateJSONMiddleware` | JSON schema validation middleware | `BIV` |

### Examples

> [accordion] Upstream connection refused (500)
>
> When the upstream server refuses the TCP connection, the access log shows:
>
> ```
> time="2025-02-10T14:23:01Z" level=info api_id=abc123 api_name=my-api api_type=oas
>   error_source=ReverseProxy error_target=api.backend.com:443
>   method=GET path=/users prefix=access-log
>   response_code_details=connection_refused response_flag=UCF status=500
> ```
>
> Key fields:
>
> * `response_flag=UCF` identifies the error as an Upstream Connection Failure.
> * `error_target=api.backend.com:443` shows the specific upstream that refused the connection.
> * `upstream_status` is absent because no HTTP response was received from the upstream.

> [accordion] TLS certificate expired (500)
>
> When the upstream's TLS certificate has expired:
>
> ```
> time="2025-02-10T14:25:33Z" level=info api_id=abc123 api_name=my-api api_type=oas
>   error_source=ReverseProxy error_target=api.backend.com:443
>   method=GET path=/users prefix=access-log
>   response_code_details=tls_certificate_expired response_flag=TLE status=500
>   tls_cert_expiry=2024-01-15T00:00:00Z tls_cert_subject="CN=api.backend.com"
> ```
>
> The `tls_cert_expiry` and `tls_cert_subject` fields help you identify exactly which certificate needs renewal and when it expired.

> [accordion] Circuit breaker open (503)
>
> When a [circuit breaker](https://tyk.io/docs/planning-for-production/ensure-high-availability/circuit-breakers.md) trips for an endpoint, the access log shows:
>
> ```
> time="2025-02-10T14:30:00Z" level=info api_id=abc123 api_name=my-api api_type=oas
>   circuit_breaker_state=OPEN error_source=ReverseProxy error_target=api.backend.com:443/health
>   method=GET path=/health prefix=access-log
>   response_code_details=circuit_breaker_open response_flag=CBO status=503
> ```

> [accordion] Rate limited (429)
>
> When a client exceeds the configured rate limit, the access log shows:
>
> ```
> time="2025-02-10T14:31:22Z" level=info api_id=abc123 api_name=my-api api_type=oas
>   error_source=RateLimitAndQuotaCheck method=POST path=/orders prefix=access-log
>   response_code_details=session_rate_limited response_flag=RLT status=429
> ```
>
> Note that `error_target` is absent for gateway-level errors (authentication, rate limiting, validation) because the request did not reach the upstream.

> [accordion] Upstream returned 503 (5XX passthrough)
>
> When the upstream receives the request but responds with an error status, the access log shows:
>
> ```
> time="2025-02-10T14:32:45Z" level=info api_id=abc123 api_name=my-api api_type=oas
>   error_source=Upstream error_target=api.backend.com:443
>   method=GET path=/health prefix=access-log
>   response_code_details=upstream_response_5xx response_flag=URS status=503
>   upstream_status=503
> ```
>
> Key distinction: `error_source=Upstream` and `upstream_status=503` indicate that the upstream returned an error, unlike a connection failure, where no response was received.

## Performance Considerations

Enabling access logs introduces some performance overhead:

* **Latency:** Increases consistently by approximately 4%-13%, depending on CPU allocation and configuration.
* **Memory Usage:** Memory consumption increases by approximately 6%-7%.
* **Allocations:** The number of memory allocations increases by approximately 5%-6%.

> [!NOTE]
>
> While the overhead of enabling access logs is noticeable, the impact is relatively modest. These findings suggest the performance trade-off may be acceptable depending on the criticality of logging to your application.

## Troubleshooting

> [accordion] Distinguishing Connection Errors from Upstream Response Errors
>
> A common troubleshooting question is whether the upstream received the request or if the connection itself failed. The error classification fields make this distinction clear:
>
> | Scenario | `error_source` | `upstream_status` | `error_target` | Example flags |
> | :- | :- | :- | :- | :- |
> | Connection failed (upstream never received request) | `ReverseProxy` | absent (0) | present | `UCF`, `UCT`, `DNS`, `TLE` |
> | Upstream responded with error | `Upstream` | present (for example, 503) | present | `URS` |
> | Gateway rejected request (never proxied) | middleware name | absent | absent | `RLT`, `AMF`, `BTL` |
