Enrich access logs
Use a transformation template to inject additional metadata to your access logs.
In this guide, you use an Inja function to extract an environment variable value from the gateway proxy pod and add this value to the dynamic metadata filter in Envoy. Then, you inject the value that you stored in the dynamic metadata filter when writing access logs.
This guide uses a subset of the supported transformation template attributes. To review all the attributes that you can set, see Templating language.
Before you begin
Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.
Get the external address of the gateway and save it in an environment variable.
Enable access logs
Create a ListenerOption resource to define your access logging rules. The following example writes access logs to the
stdout
stream of the gateway proxy container by using a custom string format that is defined in thejsonFormat
field. If no custom string format is defined, the default Envoy format is used.kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: ListenerOption metadata: name: access-logs namespace: gloo-system spec: targetRefs: - group: gateway.networking.k8s.io kind: Gateway name: http options: accessLoggingService: accessLog: - fileSink: path: /dev/stdout jsonFormat: start_time: "%START_TIME%" method: "%REQ(X-ENVOY-ORIGINAL-METHOD?:METHOD)%" path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" protocol: "%PROTOCOL%" response_code: "%RESPONSE_CODE%" response_flags: "%RESPONSE_FLAGS%" bytes_received: "%BYTES_RECEIVED%" bytes_sent: "%BYTES_SENT%" total_duration: "%DURATION%" resp_upstream_service_time: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%" req_x_forwarded_for: "%REQ(X-FORWARDED-FOR)%" user_agent: "%REQ(USER-AGENT)%" request_id: "%REQ(X-REQUEST-ID)%" authority: "%REQ(:AUTHORITY)%" upstreamHost: "%UPSTREAM_HOST%" upstreamCluster: "%UPSTREAM_CLUSTER%" EOF
Send a request to the httpbin app on the
www.example.com
domain. Verify that your request succeeds and that you get back a 200 HTTP response code.Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * date: Fri, 07 Jun 2024 21:10:03 GMT x-envoy-upstream-service-time: 2 server: envoy transfer-encoding: chunked
Get the logs for the gateway pod and verify that you see an entry for each request that you sent to the httpbin app.
kubectl -n gloo-system logs deployments/gloo-proxy-http | tail -1 | jq --sort-keys
Example output:
{ "authority": "www.example.com:8080", "bytes_received": 0, "bytes_sent": 0, "method": "GET", "path": "/status/200", "protocol": "HTTP/1.1", "req_x_forwarded_for": null, "request_id": "a6758866-0f26-4c95-95d9-4032c365c498", "resp_upstream_service_time": "0", "response_code": 200, "response_flags": "-", "start_time": "2024-08-19T20:57:57.511Z", "total_duration": 1, "upstreamCluster": "kube-svc:httpbin-httpbin-8000_httpbin", "upstreamHost": "10.36.0.14:8080", "user_agent": "curl/7.77.0" }
Enrich access logs
Create a RouteOption or VirtualHostOption resource with the following transformation rules:
- The
env
Inja function is used to extract thePOD_NAME
environment variable from the gateway proxy pod. - The value of the environment variable is added to the
pod_name
key in the dynamic metadata values.
- The
Update the ListenerOption resource to include the
pod_name
from the dynamic metadata values.kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: ListenerOption metadata: name: access-logs namespace: gloo-system spec: targetRefs: - group: gateway.networking.k8s.io kind: Gateway name: http options: accessLoggingService: accessLog: - fileSink: path: /dev/stdout jsonFormat: start_time: "%START_TIME%" method: "%REQ(X-ENVOY-ORIGINAL-METHOD?:METHOD)%" path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" protocol: "%PROTOCOL%" response_code: "%RESPONSE_CODE%" response_flags: "%RESPONSE_FLAGS%" bytes_received: "%BYTES_RECEIVED%" bytes_sent: "%BYTES_SENT%" total_duration: "%DURATION%" resp_upstream_service_time: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%" req_x_forwarded_for: "%REQ(X-FORWARDED-FOR)%" user_agent: "%REQ(USER-AGENT)%" request_id: "%REQ(X-REQUEST-ID)%" authority: "%REQ(:AUTHORITY)%" upstreamHost: "%UPSTREAM_HOST%" upstreamCluster: "%UPSTREAM_CLUSTER%" pod_name: '%DYNAMIC_METADATA(io.solo.transformation:pod_name)%' EOF
Send another request to the httpbin app.
Review the access logs and verify that the
pod_name
is now injected into your access logs.kubectl -n gloo-system logs deployments/gloo-proxy-http | tail -1 | jq --sort-keys
Example output:
{ "authority": "www.example.com:8080", "bytes_received": 0, "bytes_sent": 0, "method": "GET", "path": "/status/200", "pod_name": "gloo-proxy-http-844ff8bc4d-dh4pn", "protocol": "HTTP/1.1", "req_x_forwarded_for": null, "request_id": "132892e6-085e-400f-98da-c055ca04b714", "resp_upstream_service_time": "2", "response_code": 200, "response_flags": "-", "start_time": "2025-05-14T16:43:07.506Z", "total_duration": 2, "upstreamCluster": "kube-svc_httpbin-httpbin-8000_httpbin_httpbin_httpbin_8000", "upstreamHost": "10.0.12.250:8080", "user_agent": "curl/8.7.1" }
Cleanup
You can remove the resources that you created in this guide.
kubectl delete virtualhostoption transformation -n gloo-system
kubectl delete routeoption transformation -n httpbin
kubectl delete listeneroption access-logs -n gloo-system