Logging and OpenTelemetry in the Grafbase Gateway
The Grafbase Gateway provides logs, traces, and metrics for monitoring the gateway operation and errors. By default, it outputs logs to the standard output. Additionally, the gateway can send monitoring data to an endpoint that implements the OpenTelemetry protocols.
You can define the level of information available by setting the log level command line argument:
--log <LOG_LEVEL>
Set the logging level
[env: GRAFBASE_LOG=]
Possible values:
- off: Completely disables logging
- error: Only errors from Grafbase libraries
- warn: Warnings and errors from Grafbase libraries
- info: Info, warning and error messages from Grafbase libraries
- debug: Debug, info, warning and error messages from Grafbase libraries
- trace: Trace, debug, info, warning and error messages from all dependencies
Keep in mind this setting affects both traces and logs.
The default level is info
, which logs errors with added span information to the standard output during normal operation. The info
level will not include successful requests, which are logged at the debug
level. Using the error
level will only include error messages without spans in the output. The error
level, along with warn
and off
, will also block traces from being sent.
If you want to silence all logs but still export them along with traces and metrics to an OpenTelemetry endpoint, direct the standard output and standard error to /dev/null
.
By default, the system outputs logs to the standard output. The logs can be in two different formats:
--log-style <LOG_STYLE>
Set the style of log output
[env: GRAFBASE_LOG_STYLE=]
[default: text]
Possible values:
- text: Standard text
- json: JSON objects
The default is text
, which is ANSI-colored text for terminal output and ASCII with no coloring for common non-terminal log outputs. The json
format provides logs in JSON format and can be useful if the logging platform supports structured data.
Logs can also be sent to an OpenTelemetry endpoint by enabling the OpenTelemetry exporter in the configuration:
[telemetry.exporters.otlp]
enabled = true
endpoint = "http://localhost:1234"
Additionally, logs can be sent to a separate endpoint different from the global OpenTelemetry settings:
[telemetry.logs.exporters.otlp]
enabled = true
endpoint = "http://localhost:1235"
Read more about the options for OpenTelemetry in the configuration section.
Traces are sent from the info
level and provide information on the request lifecycle to the OpenTelemetry endpoint. The traces have a few important settings to define:
[telemetry.tracing]
enabled = true
sampling = 1
The sampling
setting defines the percentage (a floating point from 0 to 1) of requests traced. For testing purposes or with a small amount of traffic, this can safely be 1
. If the expected traffic is high, sampling every request can be expensive in terms of network, CPU, and storage. The default value is 0.15
, which samples 15% of all requests.
The collect
options define limits per span:
[telemetry.tracing.collect]
max_events_per_span = 128
max_attributes_per_span = 128
max_links_per_span = 128
max_attributes_per_event = 128
max_attributes_per_link = 128
max_events_per_span
specifies the maximum number of events to be recorded per span (default:128
)max_attributes_per_span
specifies the maximum number of attributes to be recorded per span (default:128
)max_links_per_span
specifies the maximum number of links to be recorded per span (default:128
)max_attributes_per_event
specifies the maximum number of attributes one event can have (default:128
)max_attributes_per_link
specifies the maximum number of attributes one link can have (default:128
)
Traces can be sent to an OpenTelemetry endpoint by enabling the OpenTelemetry exporter in the configuration:
[telemetry.exporters.otlp]
enabled = true
endpoint = "http://localhost:1234"
Additionally, traces can be sent to a separate endpoint different from the global OpenTelemetry settings:
[telemetry.tracing.exporters.otlp]
enabled = true
endpoint = "http://localhost:1235"
Read more about the options for OpenTelemetry in the configuration section.
Spans can also be directly written to standard output by enabling the global stdout exporter, which is mostly useful for evaluation and debugging:
[telemetry.exporters.stdout]
enabled = true
Or enabling it only for tracing:
[telemetry.tracing.exporters.stdout]
enabled = true
The Grafbase Gateway can deliver metrics for requests and operations to an OpenTelemetry endpoint. These metrics include request counts, error counts, and histograms with metadata.
Requests are measured from the HTTP server layer and include the following information:
http.response.status_code
: The HTTP status code.http.response.headers.cache_status
: Either HIT or MISS, if available.http.headers.x-grafbase-client-name
: The name of the client that triggered this request, if available.http.headers.x-grafbase-client-version
: The version of the client that triggered this request, if available.gql.response.status
: Whether the underlying GraphQL operation was successful or not, if available.
The request_latency
is an exponential histogram of the request latency.
Operations are measured from the gateway layer and include the following information:
gql.operation.query
: The query of this operation, normalized so all variables are removed. This value cannot contain any private data.gql.operation.type
: The type of the operation, eitherquery
,mutation
, orsubscription
.gql.operation.name
: The name of the operation, if provided.gql.response.cache_status
: EitherHIT
orMISS
, if available.gql.response.status
: Indicates if the response was successful or not.http.headers.x-grafbase-client-name
: The name of the client that triggered this request, if available.http.headers.x-grafbase-client-version
: The version of the client that triggered this request, if available.
The gql_operation_latency
is an exponential histogram of the GraphQL operation.
Metrics can be sent to an OpenTelemetry endpoint by enabling the OpenTelemetry exporter in the configuration:
[telemetry.exporters.otlp]
enabled = true
endpoint = "http://localhost:1234"
Additionally, metrics can be sent to a separate endpoint different from the global OpenTelemetry settings:
[telemetry.metrics.exporters.otlp]
enabled = true
endpoint = "http://localhost:1235"
Read more about the options for OpenTelemetry in the configuration section.
Likewise, spans can be directly written to standard output by enabling the global stdout exporter, which is mostly useful for evaluation and debugging:
[telemetry.exporters.stdout]
enabled = true
Or enabling it only for metrics:
[telemetry.metrics.exporters.stdout]
enabled = true
The OpenTelemetry settings are defined in the telemetry
block of the Gateway configuration:
[telemetry]
service_name = "grafbase-gateway"
Here, the service_name
is included in all the traces, metrics and logs, and should be something unique in your system.
Grafbase sends a standard set of resource attributes for every user. You can also define your own set of attributes, available in all the logs, traces and metrics:
[telemetry.resource_attributes]
custom_key = "custom_value"
other_key = "other_value"
The exporter settings can be defined globally for traces, logs, and metrics. If you need different settings for logs, tracing, or metrics, you need to prefix the exporter settings with the appropriate word. For example, the custom OpenTelemetry exporter settings for tracing use the key telemetry.tracing.exporters.otlp
.
The traces and metrics can additionally be sent to standard output (logs will always be there):
[telemetry.exporters.stdout]
enabled = true
timeout = 60
enabled
: Enables the OpenTelemetry exporter (default:false
).timeout
: The number of seconds data will be kept in memory if the collector does not collect data fast enough (default:60
).
Traces, metrics, and logs can be sent to an external OpenTelemetry collector:
[telemetry.exporters.otlp]
enabled = true
endpoint = "http://localhost:1234"
protocol = "grpc"
timeout = 60
enabled
: Enables the OpenTelemetry exporter (default:false
).endpoint
: Defines the URL for the OpenTelemetry collector.protocol
: Can either begrpc
orhttp
(default:grpc
).timeout
: The number of seconds data will be kept in memory if the collector does not collect data fast enough (default:60
).
Batch exporting
In general, it is not advisable to trigger a request for every single span, trace, and metrics event in the system. Requests should be batched and data sent in regular intervals. This can be configured from the OpenTelemetry batch settings:
[telemetry.exporters.otlp.batch_export]
scheduled_delay = 5
max_queue_size = 2048
max_export_batch_size = 512
max_concurrent_exports = 1
scheduled_delay
: The time in seconds between two consecutive requests (default:5
).max_queue_size
: The maximum queued items for delayed processing. If the queue gets full, the system drops events (default:2048
).max_export_batch_size
The maximum number of events in a single batch. If there are more events before the scheduled delay, it queues the events. (default:512
).max_concurrent_exports
: The number of concurrent senders processing the batches (default:1
).
gRPC settings
If the protocol
is set to grpc
, the Gateway will use these settings.
For collectors using TLS with a custom certificate, define the TLS settings:
[telemetry.exporters.otlp.grpc.tls]
domain_name = "custom_name"
key = "/path/to/key.pem"
cert = "/path/to/cert.pem"
ca = "/path/to/ca.crt"
domain_name
: The domain name against which to verify the server's TLS certificate.key
: Defines the path to the secret key.cert
: Defines the path to the X509 certificate file, which must be in PEM format.ca
: Defines the path to the X509 CA certificate file, which must be in PEM format.
In some cases, the gRPC collector expects custom headers to be set. Define these in the headers section of the configuration:
[[telemetry.exporters.otlp.grpc.headers]]
authorization = "Bearer {{ env.GRPC_TOKEN }}"
[[telemetry.exporters.otlp.grpc.headers]]
custom = "static value"
HTTP settings
If the protocol
is set to http
, the Gateway will use these settings. Define custom headers sent in every request:
[[telemetry.exporters.otlp.grpc.headers]]
authorization = "Bearer {{ env.GRPC_TOKEN }}"
[[telemetry.exporters.otlp.grpc.headers]]
custom = "static value"
Currently, the http
exporter does not support TLS. If needed, use the grpc
exporter.