Skip to main content

rocketmq-logger

The rocketmq-logger plugin sends gateway request and response logs to Apache RocketMQ in batches. It supports the default structured log format, the original HTTP request format, and customized log fields.

Examples​

The examples below configure the rocketmq-logger plugin for common logging scenarios.

To follow the examples, start a RocketMQ NameServer and broker. The Docker setup uses a dedicated network so that a running APISIX or API7 Gateway container can reach RocketMQ by container name.

Set GATEWAY_CONTAINER to the name of the running APISIX or API7 Gateway container. Create a dedicated Docker network and connect the gateway to it:

export GATEWAY_CONTAINER=replace-with-gateway-container-name

docker network create gateway-rocketmq-net
docker network connect gateway-rocketmq-net "$GATEWAY_CONTAINER"

Create the Docker Compose file:

docker-compose.yml
services:
rocketmq-namesrv:
image: apache/rocketmq:5.5.0
container_name: rocketmq-namesrv
restart: unless-stopped
command: ["nameserver"]
networks:
- gateway-rocketmq-net

rocketmq-broker:
image: apache/rocketmq:5.5.0
container_name: rocketmq-broker
restart: unless-stopped
depends_on:
- rocketmq-namesrv
environment:
NAMESRV_ADDR: rocketmq-namesrv:9876
command: ["broker", "-n", "rocketmq-namesrv:9876"]
networks:
- gateway-rocketmq-net

networks:
gateway-rocketmq-net:
external: true

Start containers:

docker compose up -d

Wait for the broker to register with the NameServer:

until docker exec rocketmq-namesrv sh mqadmin clusterList \
-n rocketmq-namesrv:9876 2>/dev/null | grep -q "DefaultCluster"; do
sleep 2
done

Create the TopicTest topic:

docker exec rocketmq-namesrv sh mqadmin updateTopic \
-n rocketmq-namesrv:9876 \
-t TopicTest \
-c DefaultCluster

Inspect RocketMQ Messages​

After sending a request in the following examples, use the command for your environment to inspect messages in TopicTest:

docker exec rocketmq-namesrv sh mqadmin printMsg \
-n rocketmq-namesrv:9876 \
-t TopicTest

Compare Structured and Original Request Logs​

The default metadata format sends a structured JSON log entry, while the origin format sends the original HTTP request. This example configures both formats so that you can compare their output.

Create a route with rocketmq-logger as follows:

curl "http://127.0.0.1:9180/apisix/admin/routes/rocketmq-logger-route" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/anything",
"plugins": {
"rocketmq-logger": {
"nameserver_list": [ "rocketmq-namesrv:9876" ],
"topic": "TopicTest",
"key": "key1",
"timeout": 30,
"meta_format": "default",
"batch_max_size": 1
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

❶ meta_format: use the structured JSON log format.

❷ batch_max_size: send each log entry immediately for testing.

Send a request to the route to generate a log entry:

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

Use the inspection command for your environment. The message body should contain a log entry similar to the following:

{
"client_ip": "127.0.0.1",
"upstream": "34.197.122.172:80",
"start_time": 1789377954622,
"request": {
"headers": {
"host": "127.0.0.1:9080",
"accept": "*/*",
"user-agent": "curl/8.6.0"
},
"querystring": {},
"size": 86,
"uri": "/anything",
"url": "http://127.0.0.1:9080/anything",
"method": "GET"
},
"route_id": "rocketmq-logger-route",
"apisix_latency": 8.9998455047607,
"upstream_latency": 503,
"latency": 511.99984550476,
"response": {
"size": 617,
"headers": {
"content-length": "391",
"connection": "close",
"date": "Mon, 14 Sep 2026 09:25:54 GMT",
"server": "APISIX/3.18.0",
"content-type": "application/json"
},
"status": 200
},
"server": {
"hostname": "apisix",
"version": "3.18.0"
},
"service_id": ""
}

Update the rocketmq-logger meta log format to origin:

curl "http://127.0.0.1:9180/apisix/admin/routes/rocketmq-logger-route" -X PATCH \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"plugins": {
"rocketmq-logger": {
"meta_format": "origin"
}
}
}'

Send a request to the route again to generate a new log entry:

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

Use the inspection command again. The new message body should contain the request in its original HTTP format:

GET /anything HTTP/1.1
host: 127.0.0.1:9080
user-agent: curl/8.6.0
accept: */*

Customize Log Fields With Plugin Metadata​

Use plugin metadata to apply a common log format to every rocketmq-logger instance. The following configuration uses built-in variables to record a request header and a response header.

First, create a route with rocketmq-logger as follows:

curl "http://127.0.0.1:9180/apisix/admin/routes/rocketmq-logger-route" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/anything",
"plugins": {
"rocketmq-logger": {
"nameserver_list": [ "rocketmq-namesrv:9876" ],
"topic": "TopicTest",
"key": "key1",
"timeout": 30,
"meta_format": "default",
"batch_max_size": 1
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

❶ meta_format: use default because plugin metadata does not customize logs in the origin format.

❷ batch_max_size: send each log entry immediately for testing.

Next, configure the plugin metadata for rocketmq-logger:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/rocketmq-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"
}
}'

❶ Record the custom request header env.

❷ Record 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"

Use the inspection command. The message body should contain a log entry similar to the following:

{
"host": "127.0.0.1",
"client_ip": "127.0.0.1",
"resp_content_type": "application/json",
"route_id": "rocketmq-logger-route",
"env": "dev",
"@timestamp": "2026-09-14T09:28:24+00:00"
}

Log Request Bodies Conditionally​

The following example records the request body only when the log_body query parameter is yes.

Create a route with rocketmq-logger as follows:

curl "http://127.0.0.1:9180/apisix/admin/routes/rocketmq-logger-route" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"plugins": {
"rocketmq-logger": {
"nameserver_list": [ "rocketmq-namesrv:9876" ],
"topic": "TopicTest",
"key": "key1",
"timeout": 30,
"meta_format": "default",
"batch_max_size": 1,
"include_req_body": true,
"include_req_body_expr": [["arg_log_body", "==", "yes"]]
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
},
"uri": "/anything"
}'

❶ include_req_body: enable request body logging.

❷ include_req_body_expr: record the body only when the log_body query parameter is yes.

Send a request with log_body=yes:

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

Use the inspection command. The message body should include the request body:

{
...,
"request": {
...,
"method": "POST",
"body": "{\"env\": \"dev\"}",
"size": 183
}
}

Send another request without the query parameter:

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

Use the inspection command again. The new message body should not include 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.