Skip to main content

skywalking-logger

The skywalking-logger plugin sends request and response logs as JSON objects to a SkyWalking OAP server in batches. You can customize the fields included in each log entry.

If there is an existing tracing context, it sets up the trace-log correlation automatically and relies on SkyWalking Cross Process Propagation Headers Protocol.

Examples

The examples show how to send request logs to SkyWalking, customize their contents, and correlate them with distributed traces.

Create the network used by the SkyWalking containers:

docker network create gateway-skywalking-net

If the gateway also runs in Docker, set GATEWAY_CONTAINER and connect it to the network. Skip this step for a host-installed gateway:

export GATEWAY_CONTAINER=replace-with-gateway-container-name
docker network connect gateway-skywalking-net "$GATEWAY_CONTAINER"

Create the following Docker Compose file:

skywalking-compose.yaml
services:
banyandb:
image: apache/skywalking-banyandb:0.11.0
command: standalone
networks:
- skywalking

oap:
image: apache/skywalking-oap-server:11.0.0
environment:
SW_STORAGE: banyandb
SW_STORAGE_BANYANDB_TARGETS: banyandb:17912
ports:
- "127.0.0.1:12800:12800"
depends_on:
- banyandb
networks:
skywalking:
aliases:
- skywalking-oap

horizon:
image: apache/skywalking-ui:horizon-1.0.0
environment:
HORIZON_OAP_QUERY_URL: http://skywalking-oap:12800
HORIZON_OAP_ADMIN_URL: http://skywalking-oap:17128
HORIZON_AUTH_LOCAL_USERS: '[{"username":"admin","passwordHash":"$$argon2id$$v=19$$m=65536,t=3,p=4$$eemqy1r72oSXR58y8VpRqw$$Bn/dULrmJTHEi3263KfgWDEwQmUsqNLi3xwyv/DekHM","roles":["admin"]}]'
ports:
- "127.0.0.1:8081:8081"
depends_on:
- oap
networks:
- skywalking

networks:
skywalking:
name: gateway-skywalking-net
external: true

Start the services:

docker compose -f skywalking-compose.yaml up -d

Horizon is available at http://localhost:8081. Sign in with username admin and password admin.

caution

The local user in this example uses public demonstration credentials. Use it only for a trusted local evaluation. Configure an identity provider or generate a unique password hash before exposing Horizon outside the local environment.

The Admin API and ADC examples below use http://skywalking-oap:12800, the address on the Docker network. For a host-installed gateway, use http://127.0.0.1:12800 instead. If the gateway reaches OAP through Kubernetes, use http://skywalking-oap.skywalking.svc.cluster.local:12800. The Ingress Controller examples already use the Kubernetes Service address.

Log Requests in Default Log Format

The following example sends request logs from one route to SkyWalking.

Create a route with the skywalking-logger plugin and configure the plugin with your OAP server URI:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "skywalking-logger-route",
"uri": "/anything",
"plugins": {
"skywalking-logger": {
"endpoint_addr": "http://skywalking-oap:12800"
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

Send a request to the route:

curl -i "http://127.0.0.1:9080/anything"

You should receive an HTTP/1.1 200 OK response.

In Horizon, navigate to General Service → Logs, select the APISIX service, and run a query. You should see a log entry corresponding to the request. Addresses, timing values, and version details vary by environment:

{
"upstream_latency": 3407,
"request": {
"method": "GET",
"headers": {
"user-agent": "curl/8.7.1",
"host": "127.0.0.1:9080",
"accept": "*/*"
},
"url": "http://127.0.0.1:9080/anything",
"size": 107,
"querystring": {},
"uri": "/anything"
},
"client_ip": "192.168.155.1",
"route_id": "skywalking-logger-route",
"start_time": 1789693705560,
"upstream": "34.195.250.0:80",
"server": {
"version": "3.18.0",
"hostname": "dd2886d0b7bf"
},
"service_id": "",
"response": {
"size": 881,
"status": 200,
"headers": {
"content-type": "application/json",
"date": "Fri, 18 Sep 2026 01:08:29 GMT",
"server": "APISIX/3.18.0",
"access-control-allow-origin": "*",
"connection": "close",
"access-control-allow-credentials": "true",
"content-length": "653"
}
},
"latency": 6791.0001277924,
"apisix_latency": 3384.0001277924
}

Log Request and Response Headers With Plugin Metadata

The following example uses plugin metadata to add selected request and response headers to every skywalking-logger instance. The metadata values reference built-in variables, so one configuration applies the same log fields across multiple routes and services.

First, create a route with the skywalking-logger plugin and configure the plugin with your OAP server URI (same as Log Requests in Default Log Format).

Next, configure the plugin metadata for skywalking-logger:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/skywalking-logger" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"log_format": {
"host": "$host",
"@timestamp": "$time_iso8601",
"client_ip": "$remote_addr",
"env": "$http_env",
"resp_content_type": "$sent_http_Content_Type"
}
}'

❶ Log the custom request header env.

❷ Log the response header Content-Type.

Send a request to the route with the env header:

curl -i "http://127.0.0.1:9080/anything" -H "env: dev"

You should receive an HTTP/1.1 200 OK response. In Horizon, navigate to General Service → Logs, select the APISIX service, and run a query. The log entry should contain the configured fields:

[
{
"route_id": "skywalking-logger-route",
"client_ip": "192.168.65.1",
"@timestamp": "2026-09-18T01:08:29+00:00",
"host": "127.0.0.1",
"env": "dev",
"resp_content_type": "application/json"
}
]

Log Request Bodies Conditionally

The following example logs the request body only when the request matches the configured condition.

Create a route with the skywalking-logger plugin:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "skywalking-logger-route",
"uri": "/anything",
"plugins": {
"skywalking-logger": {
"endpoint_addr": "http://skywalking-oap:12800",
"include_req_body": true,
"include_req_body_expr": [["arg_log_body", "==", "yes"]]
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

include_req_body: Set to true to include request body.

include_req_body_expr: Only include request body if the URL query string log_body is yes.

Send a request to the route with a URL query string satisfying the condition:

curl -i "http://127.0.0.1:9080/anything?log_body=yes" -X POST -d '{"env": "dev"}'

You should receive an HTTP/1.1 200 OK response. In Horizon, navigate to General Service → Logs, select the APISIX service, and run a query. The log entry should include the request body:

[
{
"request": {
"url": "http://127.0.0.1:9080/anything?log_body=yes",
"querystring": {
"log_body": "yes"
},
"uri": "/anything?log_body=yes",
...,
"body": "{\"env\": \"dev\"}",
},
...
}
]

Send a request to the route without any URL query string:

curl -i "http://127.0.0.1:9080/anything" -X POST -d '{"env": "dev"}'

You should not observe a log entry without the request body.

info

Custom log formats do not add collected request or response bodies automatically. Include the corresponding variables in the format:

{
"include_req_body": true,
"include_resp_body": true,
"log_format": {
"request_body": "$request_body",
"response_body": "$resp_body"
}
}

Body size limits still apply. Use log_format_extra to add custom fields without replacing the default log entry.

Associate Traces with Logs

The following example enables tracing and request logging on one route so Horizon can link each log entry to its trace.

SkyWalking setup

This example also requires the skywalking plugin to be enabled globally and configured with a reachable OAP endpoint address. For Helm deployments, see the SkyWalking plugin setup.

Create a route with the skywalking-logger plugin and configure the plugin with your OAP server URI:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "skywalking-logger-route",
"uri": "/anything",
"plugins": {
"skywalking": {
"sample_ratio": 1
},
"skywalking-logger": {
"endpoint_addr": "http://skywalking-oap:12800"
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

Generate a few requests to the route:

curl -i "http://127.0.0.1:9080/anything"

You should receive HTTP/1.1 200 OK responses.

In Horizon, navigate to General Service → Logs and run a query. The correlated request log includes a trace link that opens its trace:

Horizon showing APISIX request logs linked to their traces