icon | description |
---|---|
camera-cctv |
Configuring Access Logs for Enhanced Traffic Monitoring. |
{% hint style="info" %} Available since Router 0.118.0 {% endhint %}
Access or request logs provide valuable insights into the traffic passing through your router instances. By default, logs are output to stdout
, but logging to a file is also supported, which is recommended for high-load scenarios. However, only one logging mode—either stdout
or file—can be enabled at any given time. The logs include a predefined set of fields that help identify HTTP requests. Additionally, custom fields can be configured to capture more detailed information from the GraphQL requests.
The following configuration enables logging to stdout
:
access_logs:
enabled: true
output:
stdout:
enabled: true
For environments with high traffic, logging to a file is recommended. Below is an example configuration for logging to a file:
access_logs:
enabled: true
output:
file:
enabled: true
path: /var/log/gateway/access.log
The default log fields provide essential details about each HTTP request. These fields include:
- hostname: The hostname of the machine handling the request.
- pid: The process ID of the router instance.
- request_id: The request ID generated by the router instance.
- trace_id: The Trace ID propagated or generated by the router instance.
- status: The HTTP status code of the request.
- method: The HTTP method used (e.g.,
GET
,POST
). - path: The request path (e.g.,
/graphql
). - query: The query string included in the request URL (e.g.,
/?param=1
). - ip: The client’s IP address (redacted by default).
- user_agent: The
User-Agent
header value provided by the client. - config_version: The version of the router configuration used to handle the request.
- latency: The time taken to process the request, in float seconds.
- log_type: Identifies the type of log (useful for distinguishing access logs from other log types).
An example of a log entry is shown below:
12:21:37 PM INFO /graphql {
"hostname": "dustins-MacBook-Pro.local",
"pid": 13616,
"log_type": "request",
"method": "POST",
"path": "/graphql",
"query": "",
"ip": "[REDACTED]",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
"config_version": "6c6b3f36-99b9-4632-84e1-ca24d95eee8d",
"trace_id": "cc4bccf2e981fecc3f8f3b87257c1ce6",
"latency": 0.019332208,
"status": 200,
"request_id": "dustins-MacBook-Pro.local/TBOXjJsAo5-000007"
}
In addition to the default fields, you can extend the log with custom fields. These can include values extracted from request headers or additional information generated after the GraphQL operation has been processed.
Let's take the following example:
log_level: info
dev_mode: true
access_logs:
enabled: true
output:
file:
enabled: true
path: "access.log"
router:
fields:
- key: "service"
value_from:
request_header: "x-service"
- key: "operationName"
value_from:
context_field: operation_name
- key: "operationSha256"
value_from:
context_field: operation_sha256
- key: "requestError"
value_from:
context_field: request_error
- key: "responseErrorMessage"
value_from:
context_field: response_error_message
- key: "serviceNames"
value_from:
context_field: operation_service_names
- key: "operationHash"
value_from:
context_field: operation_hash
- key: "errorCodes"
value_from:
context_field: graphql_error_codes
- key: "operationType"
value_from:
context_field: operation_type
- key: "persistentOperationSha256"
value_from:
context_field: persisted_operation_sha256
- key: "errorServiceNames"
value_from:
context_field: graphql_error_service_names
- key: "operationParsingTime"
value_from:
context_field: operation_parsing_time
- key: "operationPlanningTime"
value_from:
context_field: operation_planning_time
- key: "operationNormalizationTime"
value_from:
context_field: operation_normalization_time
- key: "operationValidationTime"
value_from:
context_field: operation_validation_time
Here’s an explanation of each field’s meaning:
- service: This field logs the name of the service making the request, extracted from the request header "x-service". It helps identify which specific service is making the API call.
- operationName: This field logs the name of the GraphQL operation being performed. It is extracted from the context of the request and indicates which query or mutation is being executed.
- operationSha256: This field logs the SHA-256 hash of the original GraphQL operation, serving as a unique identifier for the operation's structure. It helps to identify operations in a secure and consistent way.
- requestError: This field is only present when an error has been encountered with the request, and will be
true
if so. - responseErrorMessage: This field logs any error message returned in the response. It captures detailed information about what went wrong during the execution of the operation.
- serviceNames: This field logs the names of all services involved in processing the operation. It can be useful for tracking dependencies or microservices that are part of the request's execution.
- operationHash: This field logs a unique hash generated for the normalized operation. It serves as an identifier for the specific instance of the operation being executed, useful for tracing or debugging.
- errorCodes: This field logs any GraphQL error codes returned in the response. These codes help diagnose issues within the GraphQL schema or logic.
- operationType: This field logs the type of GraphQL operation being executed, such as a query, mutation, or subscription. It helps classify the request.
- persistentOperationSha256: This field logs the SHA-256 hash of the persisted GraphQL operation. Persisted operations are pre-saved on the server for efficiency, and this hash allows tracking them.
- errorServiceNames: This field logs the names of services that were involved when the operation resulted in an error. It helps identify which microservices or external APIs contributed to the issue.
- operationParsingTime: This field logs the amount of time (float seconds) spent parsing the GraphQL operation. It measures how long it took to interpret the operation’s syntax.
- operationPlanningTime: This field logs the time (float seconds) taken for planning the execution of the GraphQL operation, including resolving dependencies or building execution strategies.
- operationNormalizationTime: This field logs the time (float seconds) spent normalizing the GraphQL operation, which involves standardizing the operation to ensure consistency in processing.
- operationValidationTime: This field logs the time (float seconds) spent validating the GraphQL operation, ensuring that the operation is correct and adheres to the GraphQL schema and rules before execution.
In addition to the standard and custom fields typically present in a log, certain fields are included only in error scenarios to capture details about issues that occurred during request processing. These fields are useful for diagnosing errors in GraphQL operations and understanding the root causes.
Here are the fields that are specifically added in error cases:
- graphql_error_service_names:
Lists the names of the services involved in the GraphQL request where an error occurred. This helps in pinpointing which microservice(s) or backend service(s) contributed to the error. - graphql_error_codes:
Provides error codes associated with the GraphQL operation. These codes may correspond to specific validation, execution, or schema-related errors that occurred during processing. - response_error_message:
Contains the actual error message returned in the response. This message can be used to better understand what went wrong and why the request failed. - requestError:
This field is only present when an error has been encountered with the request, and will betrue
if so. This can better help clients filter their logs (ifrequestError: true)
to find error cases.
When extracting values from a header, it can be beneficial to ensure a default value is set. This can be achieved by defining the value as follows:
access_logs:
enabled: true
router:
fields:
- key: "service"
default: "gateway" # Here
value_from:
request_header: "x-service"
12:39:49 PM INFO /graphql {
"hostname": "dustins-MacBook-Pro.local",
"pid": 15142,
"log_type": "request",
"method": "POST",
"path": "/graphql",
"query": "",
"ip": "[REDACTED]",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
"config_version": "6c6b3f36-99b9-4632-84e1-ca24d95eee8d",
"trace_id": "ed9acd8851c666d53f1d7244015cf71a",
"latency": 0.019447292,
"status": 200,
"request_id": "dustins-MacBook-Pro.local/XKchE7RlTu-000001",
"operationSha256": "57fcea4f7ba8da669882d80960c08607fa13873af754642af6769d8d25f09b99",
"serviceNames": ["employees"],
"operationHash": "14226210703439426856",
"operationType": "query",
"operationParsingTime": 0.000066541,
"operationPlanningTime": 0.001880208,
"operationNormalizationTime": 0.000468625,
"operationValidationTime": 0.000281958
}
In development, log lines are formatted for readability using pretty printing. In production mode, all logs are output as newline-separated JSON values.
{% hint style="info" %} Available since Router 0.146.0 {% endhint %}
In addition to router logs, users can enable subgraph
access logs as well, to get detailed logging of requests made to subgraphs. These logs are useful for tracing and debugging interactions between the router and its connected subgraphs. The configuration allows for custom fields to be included in the logs, providing additional context about requests and responses.
To enable Subgraph Access Logs, use the following configuration structure:
access_logs:
subgraphs:
enabled: true
fields:
- key: "my-header"
value_from:
context_field: operation_name
- key: "my-response-header"
value_from:
response_header: "x-foo"
- key: "my-request-header"
value_from:
request_header: "x-service"
{% hint style="info" %} Currently the log output will go to the same place as the router access logs. In the future, we may enable configuration of the subgraph access logs to a different log sink. If you need that feature, please discuss it with us. {% endhint %}
Subgraph Access Logs are structured in JSON format. An example log entry is shown below:
{
"level": "info",
"time": 1733228244528,
"msg": "/graphql",
"hostname": "my-host",
"pid": 9788,
"log_type": "client/subgraph",
"method": "POST",
"path": "/graphql",
"query": "",
"ip": "[REDACTED]",
"user_agent": "",
"config_version": "cca7eda6-e68a-431c-ba59-27718074493e",
"trace_id": "0863b9d74e2e4d520448e5c7f49e7f8f",
"request_id": "test.local/hlUxBfcMgk-000002",
"subgraph_name": "employees",
"subgraph_id": "0",
"url": "https://localhost:1234/graphql",
"status": 200,
"latency": 0.001272029
}
The subgraph access logs contain the same #default-log-fields as the normal router access logs, and as above( #custom-fields), you can extend the log with custom fields. These can include values extracted from request headers or additional information generated after the GraphQL operation has been processed.
There are certain log fields that are only added for subgraph access logs. Those include:
- subgraph_name: The name of the subgraph
- subgraph_id: The subgraph ID, as configured with the router
- url: The URL of the subgraph
Let's take the following example:
log_level: info
dev_mode: true
access_logs:
enabled: true
output:
file:
enabled: true
path: "access.log"
subgraphs:
fields:
- key: "service"
value_from:
request_header: "x-service"
- key: "my_response_header"
value_from:
response_header: "x-my-response"
- key: "operationName"
value_from:
context_field: operation_name
- key: "operationSha256"
value_from:
context_field: operation_sha256
- key: "serviceNames"
value_from:
context_field: operation_service_names
- key: "operationHash"
value_from:
context_field: operation_hash
- key: "operationType"
value_from:
context_field: operation_type
- key: "persistentOperationSha256"
value_from:
context_field: persisted_operation_sha256
- key: "operationParsingTime"
value_from:
context_field: operation_parsing_time
- key: "operationPlanningTime"
value_from:
context_field: operation_planning_time
- key: "operationNormalizationTime"
value_from:
context_field: operation_normalization_time
- key: "operationValidationTime"
value_from:
context_field: operation_validation_time
- key: "requestError"
value_from:
context_field: request_error
- key: "responseErrorMessage"
value_from:
context_field: response_error_message
Here’s an explanation of each field’s meaning:
- service: This field logs the name of the service making the request, extracted from the request header "x-service". It helps identify which specific service is making the API call.
- my_response_header: This field logs a header from the subgraph response, extracted from the response header "x-my-response".
- operationName: This field logs the name of the GraphQL operation being performed. It is extracted from the context of the request and indicates which query or mutation is being executed.
- operationSha256: This field logs the SHA-256 hash of the original GraphQL operation, serving as a unique identifier for the operation's structure. It helps to identify operations in a secure and consistent way.
- serviceNames: This field logs the names of all services involved in processing the operation. It can be useful for tracking dependencies or microservices that are part of the request's execution.
- operationHash: This field logs a unique hash generated for the normalized operation. It serves as an identifier for the specific instance of the operation being executed, useful for tracing or debugging.
- operationType: This field logs the type of GraphQL operation being executed, such as a query, mutation, or subscription. It helps classify the request.
- persistentOperationSha256: This field logs the SHA-256 hash of the persisted GraphQL operation. Persisted operations are pre-saved on the server for efficiency, and this hash allows tracking them.
- operationParsingTime: This field logs the amount of time (float seconds) spent parsing the GraphQL operation. It measures how long it took to interpret the operation’s syntax.
- operationPlanningTime: This field logs the time (float seconds) taken for planning the execution of the GraphQL operation, including resolving dependencies or building execution strategies.
- operationNormalizationTime: This field logs the time (float seconds) spent normalizing the GraphQL operation, which involves standardizing the operation to ensure consistency in processing.
- operationValidationTime: This field logs the time (float seconds) spent validating the GraphQL operation, ensuring that the operation is correct and adheres to the GraphQL schema and rules before execution.
- requestError: This field is only present when an error has been encountered with the request to the subgraph, and will be
true
if so. - responseErrorMessage: This field logs any error message returned in the response from the subgraph. It captures detailed information about what went wrong during the execution of the operation.
Currently, the following context fields available in router access logs are not available in Subgraph Access Logs:
graphql_error_codes
graphql_error_service_names
By configuring access logs, you can gather vital data on the traffic processed by your router. This helps in monitoring performance, debugging issues, and understanding request patterns. Whether logging to stdout
or to a file, the logs provide flexibility with both default and custom fields to suit your specific needs.