Skip to main content

Version: latest

Log Consumer Labels in Access Log

Consumer labels are key-value pairs attached to consumers that can represent metadata such as department, organization, or service tier. By default, access logs only include the consumer username. This guide shows you how to include consumer labels in the gateway's access log for more granular traffic analysis.

How It Works

The approach uses three components:

  1. Custom NGINX variable: Declare a variable (e.g., $consumer_company) in the gateway configuration and set its default value.
  2. serverless-pre-function: A global plugin that reads the consumer label and assigns it to the variable at runtime.
  3. Access log format: The custom variable is included in the log output.

Prerequisites

  • A running API7 Gateway deployment.
  • Access to the gateway's config.yaml configuration file.

Step 1: Declare the Custom Variable

In the gateway's config.yaml, declare a custom NGINX variable and set its default value. You can declare multiple variables for different labels:

conf/config.yaml
nginx_config:
http_server_location_configuration_snippet: |
set $consumer_company "-";

Step 2: Update the Access Log Format

In the same configuration file, add the custom variable to the access log format:

conf/config.yaml
nginx_config:
http:
access_log_format: >-
$remote_addr - $remote_user [$time_local] $http_host
"$request" $status $body_bytes_sent $request_time
"$http_referer" "$http_user_agent"
$upstream_addr $upstream_status $upstream_response_time
"$consumer_company"

Reload or restart the gateway for the configuration changes to take effect.

Step 3: Assign the Variable with a Serverless Function

Configure serverless-pre-function as a global plugin to read the consumer label and assign it to the custom variable:

curl -k "https://localhost:7443/apisix/admin/global_rules/serverless-pre-function?gateway_group_id={group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function (conf, ctx) ngx.var.consumer_company = ctx.consumer and ctx.consumer.labels and ctx.consumer.labels[\"company\"] or \"unknown\" end"
]
}
}
}'

The function reads the company label from the consumer. If the consumer does not have the label or no consumer is identified (e.g., unauthenticated requests), the value defaults to "unknown".

Step 4: Configure a Consumer and a Protected Route

Create a consumer with the company label and a key authentication credential, then expose a route protected by key-auth:

# Create the consumer with a label
curl -k "https://localhost:7443/apisix/admin/consumers/john?gateway_group_id={group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"username": "john",
"labels": {
"company": "smart-technology"
}
}'

# Add a key-auth credential
curl -k "https://localhost:7443/apisix/admin/consumers/john/credentials/primary-key?gateway_group_id={group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "primary-key",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'

# Create a service with the upstream
curl -k "https://localhost:7443/apisix/admin/services/consumer-label-demo?gateway_group_id={group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "consumer-label-demo",
"upstream": {
"type": "roundrobin",
"nodes": [
{ "host": "httpbin.org", "port": 80, "weight": 1 }
]
}
}'

# Create a route protected by key-auth
curl -k "https://localhost:7443/apisix/admin/routes/consumer-label-demo?gateway_group_id={group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "consumer-label-demo",
"paths": ["/anything"],
"service_id": "consumer-label-demo",
"plugins": {
"key-auth": {}
}
}'

Step 5: Verify

Send a request with a valid consumer key:

curl -i "http://127.0.0.1:9080/anything" -H "apikey: john-key"

You should receive an HTTP/1.1 200 OK response. The access log entry includes the consumer label:

192.168.1.1 - - [18/Mar/2025:09:17:28 +0000] 127.0.0.1:9080 "GET /anything HTTP/1.1" 200 508 1.260 "-" "curl/8.6.0" 13.210.43.76:80 200 1.153 "smart-technology"

Send a request without a key:

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

The access log shows the default value:

192.168.1.1 - - [18/Mar/2025:09:18:27 +0000] 127.0.0.1:9080 "GET /anything HTTP/1.1" 401 52 0.000 "-" "curl/8.6.0" - - - "unknown"

Alternative: Forward Labels as Headers

If you want consumer labels included in structured log entries from logging plugins (e.g., http-logger, kafka-logger), use the attach-consumer-label plugin to map consumer labels to upstream request headers. The headers are then available as NGINX variables (e.g., $http_x_consumer_company) that any logging plugin's log_format can reference.

Update the route from Step 4 to add both plugins alongside key-auth. The example below uses a logging endpoint at http://log-collector:8080/logs:

curl -k "https://localhost:7443/apisix/admin/routes/consumer-label-demo?gateway_group_id={group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "consumer-label-demo",
"paths": ["/anything"],
"service_id": "consumer-label-demo",
"plugins": {
"key-auth": {},
"attach-consumer-label": {
"headers": {
"X-Consumer-Company": "$company"
}
},
"http-logger": {
"uri": "http://log-collector:8080/logs",
"log_format": {
"consumer_company": "$http_x_consumer_company"
}
}
}
}'

The $ prefix in attach-consumer-label references a consumer label key. Requests from authenticated consumers will have the corresponding header injected before reaching the upstream and the logging plugin.

Additional Resources

API7.ai Logo

The digital world is connected by APIs,
API7.ai exists to make APIs more efficient, reliable, and secure.

Sign up for API7 newsletter

Product

API7 Gateway

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2026. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the Apache Software Foundation