Skip to content

Configure OpenTelemetry

Valkey GLIDE 2.0 introduces support for OpenTelemetry (OTel), enabling developers to gain deep insights into client-side performance and behavior in distributed systems.

To begin collecting telemetry data with GLIDE 2.0:

  • Set up an OpenTelemetry Collector to receive trace and metric data.
  • Configure the GLIDE client with the endpoint to your collector.
  • Alternatively, you can configure GLIDE to export telemetry data directly to a local file for development or debugging purposes, without requiring a running collector.

GLIDE does not export data directly to third-party services—instead, it sends data to your collector, which routes it to your backend (e.g., CloudWatch, Prometheus, Jaeger).

from glide import OpenTelemetry, OpenTelemetryConfig, OpenTelemetryTracesConfig, OpenTelemetryMetricsConfig
OpenTelemetry.init(OpenTelemetryConfig(
traces=OpenTelemetryTracesConfig(
endpoint="http://localhost:4318/v1/traces",
sample_percentage=10 # Optional, defaults to 1. Can also be changed at runtime via set_sample_percentage().
),
metrics=OpenTelemetryMetricsConfig(
endpoint="http://localhost:4318/v1/metrics"
),
flush_interval_ms=1000 # Optional, defaults to 5000
))

When initializing OpenTelemetry, you can customize behavior using the configuration object.

ConfigurationTypeRequiredDefaultDescription
traces.endpointStringYes (if traces enabled)-The trace collector endpoint URL. Supports http://, https://, grpc://, or file:// protocols.
traces.samplePercentageIntegerNo1Percentage (0–100) of commands to sample for tracing. For production, a low sampling rate (1–5%) is recommended to balance performance and insight. Can be changed at runtime.
metrics.endpointStringYes (if metrics enabled)-The metrics collector endpoint URL. Supports http://, https://, grpc://, or file:// protocols.
flushIntervalMsIntegerNo5000Time in milliseconds between flushes to the collector. Must be a positive integer.

You can configure the OTel collector endpoint using one of the following protocols:

  • http:// or https:// - Send data via HTTP(S)
  • grpc:// - Use gRPC for efficient telemetry transmission
  • file:// - Write telemetry data to a local file (ideal for local dev/debugging)

If using file:// as the endpoint:

  • The path must begin with file://.
  • If a directory is provided (or no file extension), data is written to signals.json in that directory.
  • If a filename is included, it will be used as-is.
  • The parent directory must already exist.
  • Data is appended, not overwritten.
  • Flush interval must be a positive integer.
  • Sample percentage must be between 0 and 100.
  • File exporter paths must start with file:// and have an existing parent directory.
  • Invalid configuration will throw an error synchronously when calling initialization.
  • Use TLS for collector endpoints — GLIDE supports https:// and grpc:// endpoints. Always use encrypted transport in production to prevent telemetry data from being intercepted in transit.
  • Protect file exporter output — When using the file:// exporter for local development, telemetry files may contain command-level details. Restrict file permissions and avoid writing to shared or world-readable directories.
  • Minimize sampling in production — Use a low sample percentage (1–5%) to limit the volume of potentially sensitive operational data collected.
  • Review exported data — GLIDE traces include command names, latency measurements, and error status. While GLIDE does not include command arguments or key values in trace spans, always review what your collector pipeline forwards to third-party backends.

GLIDE can attach its command spans as children of your application’s existing OpenTelemetry trace, giving end-to-end visibility from your application code through to Valkey operations—without GLIDE depending on go.opentelemetry.io/otel.

This is achieved by registering a span context extractor function that bridges your application’s trace context into GLIDE’s internal tracing.

import (
"context"
"log"
"github.com/valkey-io/valkey-glide/go/v2"
"go.opentelemetry.io/otel/trace"
)
// Initialize OpenTelemetry tracing first
config := glide.OpenTelemetryConfig{
Traces: &glide.OpenTelemetryTracesConfig{
Endpoint: "http://localhost:4318/v1/traces",
},
}
if err := glide.GetOtelInstance().Init(config); err != nil {
log.Fatalf("Failed to initialize OpenTelemetry: %v", err)
}
// Register a thread-safe span context extractor
glide.GetOtelInstance().SetSpanContextExtractor(func(ctx context.Context) (glide.SpanContext, bool) {
spanContext := trace.SpanContextFromContext(ctx)
if !spanContext.IsValid() {
return glide.SpanContext{}, false
}
return glide.SpanContext{
TraceID: spanContext.TraceID().String(),
SpanID: spanContext.SpanID().String(),
TraceFlags: byte(spanContext.TraceFlags()),
TraceState: spanContext.TraceState().String(),
}, true
})

The SpanContext struct is a dependency-free representation of an OTel span context with the following fields:

  • TraceID (32 hex chars)
  • SpanID (16 hex chars)
  • TraceFlags (byte)
  • TraceState (string)

The TraceState field, if non-empty, is validated against W3C Trace Context rules. If the extractor returns true but the SpanContext fails validation (e.g., invalid hex length, all-zero IDs, or malformed TraceState), GLIDE silently falls back to the next resolution option.

When creating a command span, GLIDE selects the parent using this fallback order:

  1. Span context extractor — if registered via SetSpanContextExtractor and returns a valid context (can be set/cleared at runtime)
  2. SpanFromContext — the span-pointer configured via OpenTelemetryConfig.SpanFromContext at Init() time (fixed for client lifetime)
  3. No parent — standalone span