OpenTelemetry Tracing
Hive Router supports distributed tracing so you can follow requests across the gateway and your subgraphs.
This guide explains how to configure tracing in a practical, developer-friendly way: where to send traces, how to configure OTLP, how to tune throughput, and how to debug missing traces.
Choose your tracing destination
Hive Router supports three tracing paths. You can send traces directly to Hive Console through
telemetry.hive.tracing, send them to an OTLP-compatible backend through
telemetry.tracing.exporters, or use native Datadog tracing through a Datadog Agent.
Teams already running OpenTelemetry infrastructure usually prefer OTLP because it fits into existing collector pipelines and backend routing rules. Use native Datadog tracing when you need Datadog’s sampling, rate limiting, remote configuration, and all-request APM statistics.
Send traces to Hive Console
If you are already using Hive, sending traces to Console is usually the smoothest starting point. It keeps tracing data close to schema and usage insights, so it is easier to move from “this request is slow” to “which operation and field caused it”.
To make this work, Hive Router needs two pieces of information:
an access token with permission to send traces,
and a target reference. The target can be either a
human-readable slug ($organizationSlug/$projectSlug/$targetSlug) or a target UUID
(a0f4c605-6541-4350-8cfe-b31f21a4bf80).
With those values available as environment variables (HIVE_TARGET and HIVE_ACCESS_TOKEN), enable
Hive tracing in the config file:
After enabling tracing, send a few GraphQL queries through your router and open that same target’s Traces view in Hive Console. You should start seeing new traces for recent requests.
If traces do not appear, it usually means one of four things: tracing is not enabled, the token does not have necessary permissions, the configured target reference points to a different target, or the self-hosted endpoint is not reachable from the router runtime.
Send traces to OTLP-compatible backends
If your observability platform already supports OTLP ingestion, Hive Router can push traces straight to that OTLP endpoint. The destination can be an OpenTelemetry Collector or any system that natively understands OTLP.
Once configured, send normal requests through the router and check your backend for fresh traces.
If gRPC export fails, metadata credentials and TLS files are usually the first places to inspect.
Send traces through native Datadog tracing
Native Datadog tracing uses the Datadog Rust tracer and sends traces to a Datadog Agent trace endpoint. This differs from sending generic OpenTelemetry data to a Datadog OTLP endpoint. It preserves Datadog’s native sampling behavior and computes request, error, and latency statistics from every recorded request, including requests whose detailed traces are not retained.
enabled defaults to true. The endpoint is optional and can be a
StringOrExpression. When omitted, Datadog uses its
native configuration, including DD_TRACE_AGENT_URL, DD_AGENT_HOST, and DD_TRACE_AGENT_PORT.
The Agent trace endpoint normally uses port 8126; it is not the OTLP gRPC endpoint commonly
exposed on port 4317.
The router resolves and validates a configured endpoint at startup. An unresolved expression, malformed URL, unsupported Agent URL scheme, or more than one enabled Datadog exporter prevents startup. The router does not probe Agent connectivity. An unavailable Agent therefore does not stop the router from starting, and asynchronous export failures are reported through Datadog logging.
Sampling and mixed exporters
Hive Router uses one shared tracer provider. When a Datadog exporter is enabled, Datadog owns the
provider-wide, parent-aware sampling decision. The router maps collect.sampling to Datadog’s
catch-all sample rate, overriding DD_TRACE_SAMPLE_RATE. More specific DD_TRACE_SAMPLING_RULES
can apply before that rate, and Datadog remote configuration can update native sampling behavior.
The router’s parent_based_sampler option only applies to the generic OpenTelemetry provider.
When explicit sampling is active, Datadog retains at most 100 detailed traces per second by default.
Set DD_TRACE_RATE_LIMIT to change this ceiling. At high request rates, the retained percentage can
be lower than collect.sampling, while all-request request, error, and latency statistics remain
complete. For the same reason, sampling: 0.0 keeps instrumentation active when Datadog is enabled:
no detailed traces are retained, but Datadog can still compute its APM statistics.
You can attach OTLP, stdout, and Hive trace processors to the same Datadog-backed provider. Those
processors receive only sampled spans and ignore Datadog’s RecordOnly spans. Because sampling is
provider-wide, independent per-exporter sampling rates are not supported.
DD_TRACE_ENABLED=false disables the Datadog tracer and every OTLP, stdout, and Hive processor on
the shared Datadog-backed provider. To disable only Datadog, disable its router exporter instead:
Without an enabled Datadog exporter, the router uses its generic OpenTelemetry provider and sampler.
Router resource attributes are passed to Datadog, where native Datadog precedence applies to the
equivalent DD_SERVICE, DD_ENV, and DD_VERSION values.
The router continues to use the propagation formats configured under
telemetry.tracing.propagation, including W3C Trace Context. It does not install Datadog-native
propagation. The Datadog-backed provider also uses the router’s existing force-flush and shutdown
lifecycle.
For native Datadog behavior and configuration details, see the
datadog-opentelemetry API,
Datadog Rust tracing configuration,
trace metrics, and
ingestion mechanisms.
Production baseline
For production workloads, define a clear service identity, begin with conservative sampling rates, and use a single primary propagation format.
This configuration is designed to be a safe, predictable starting point. It gives each deployment a clear identity in your telemetry backend, keeps trace volume under control, and sticks to a single propagation format.
In practice, this means you’ll see enough traces to understand real production behavior without overwhelming storage or blowing up costs.
Batching and throughput tuning
Batching settings control how traces move from the router to your OTLP endpoint. You’re able to tune these settings to control delivery latency of traces, resilience during traffic spikes and memory pressure on the router.
| Field | You’d usually increase this when | Tradeoff |
|---|---|---|
max_queue_size | Traces are dropped during traffic spikes | Higher memory usage |
max_export_batch_size | You want better export throughput per flush | Potentially higher burst latency |
scheduled_delay | You want fewer export calls (higher) or lower latency (lower) | Throughput vs latency |
max_export_timeout | Your OTLP endpoint or network is occasionally slow | Longer waits on blocked exports |
max_concurrent_exports | Your OTLP endpoint can handle more parallel uploads | Higher downstream pressure |
As a quick rule:
- if traces arrive late, lower
scheduled_delay. - if traces drop under burst load, increase
max_queue_sizefirst. - if your OTLP collector has headroom, raise
max_concurrent_exports.
Propagation
Propagation settings control how trace context flows between clients, the router, and subgraphs. In
most modern OpenTelemetry setups, trace_context is the safest default.
You should only enable b3 or jaeger when those formats are required by other components.
If clients send custom tracing headers, make sure your CORS configuration allows those headers through.
Compliance with OpenTelemetry Semantic Conventions
OpenTelemetry has standardized attribute names used on spans. Those conventions ensure that telemetry produced by different services, libraries, and vendors is consistent and understandable across tools.
The behavior is controlled by telemetry.tracing.instrumentation.spans.mode, which selects which
attribute set is written to spans:
spec_compliant(default) - emits only the stable attributesdeprecated- emits only the deprecated attributesspec_and_deprecated- emits both stable and deprecated attributes
Most teams should stay on spec_compliant. The other modes are primarily useful when migrating
legacy dashboards that still expect deprecated attributes.
Subscription errors
GraphQL errors produced while establishing or running WebSocket subscriptions are recorded in traces like errors from HTTP GraphQL requests. This includes authentication, parsing, validation, and execution errors, making subscription failures visible in the same tracing backend as other router traffic.
Troubleshooting
When traces are missing or incomplete, think in layers:
- exporter setup
- sampling behavior
- propagation
- transport
If no traces appear at all, verify if the exporter is enabled, the endpoint is reachable, and credentials are valid.
If spans show up but links are broken, propagation formats are usually misaligned between services.
If under high load, traces are delayed or dropped, then often it’s a batch processor issue. In that case tune the batch processor settings and observe.
Configuration reference
For all options and defaults, see telemetry configuration reference.