diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e55a1a3a5c..e57d47702b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ Main (unreleased) - update promtail converter to use `file_match` block for `loki.source.file` instead of going through `local.file_match`. (@kalleep) +- Added `send_traceparent` option for `tracing` config to enable traceparent header propagation. (@MyDigitalLife) + - Add `meta_cache_address` to `beyla.ebpf` component. (@skl) ### Bugfixes diff --git a/docs/sources/reference/config-blocks/tracing.md b/docs/sources/reference/config-blocks/tracing.md index 208a8b8c1f3..e04cf265ee7 100644 --- a/docs/sources/reference/config-blocks/tracing.md +++ b/docs/sources/reference/config-blocks/tracing.md @@ -26,9 +26,10 @@ tracing { You can use the following arguments with `tracing`: | Name | Type | Description | Default | Required | -| ------------------- | ------------------------ | --------------------------------------------------- | ------- | -------- | +|---------------------|--------------------------|-----------------------------------------------------|---------|----------| | `sampling_fraction` | `number` | Fraction of traces to keep. | `0.1` | no | | `write_to` | `list(otelcol.Consumer)` | Inputs from `otelcol` components to send traces to. | `[]` | no | +| `send_traceparent` | `bool` | Send traceparent header with requests. | `false` | no | The `write_to` argument controls which components to send traces to for processing. The elements in the array can be any `otelcol` component that accept traces, including processors and exporters. @@ -42,6 +43,8 @@ The `sampling_fraction` argument controls what percentage of generated traces sh When set to `1` or greater, 100% of traces are kept. When set to `0` or lower, 0% of traces are kept. +The `send_traceparent` argument controls whether the `traceparent` header is sent with requests to other services. + ## Blocks You can use the following blocks with `tracing`: @@ -85,6 +88,7 @@ If the remote sampling strategy exceeds the limit, sampling decisions fall back ```alloy tracing { sampling_fraction = 0.1 + send_traceparent = true write_to = [otelcol.exporter.otlp.tempo.input] } diff --git a/internal/runtime/tracing/tracing.go b/internal/runtime/tracing/tracing.go index 7f87d520f3e..56d7f4671f9 100644 --- a/internal/runtime/tracing/tracing.go +++ b/internal/runtime/tracing/tracing.go @@ -11,7 +11,9 @@ import ( "github.com/grafana/alloy/internal/build" "github.com/grafana/alloy/internal/component/otelcol" "github.com/grafana/alloy/internal/runtime/tracing/internal/jaegerremote" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.37.0" @@ -25,6 +27,7 @@ var ( DefaultOptions = Options{ SamplingFraction: 0.1, // Keep 10% of spans WriteTo: []otelcol.Consumer{}, // Don't send spans anywhere. + SendTraceparent: false, } DefaultJaegerRemoteSamplerOptions = JaegerRemoteSamplerOptions{ @@ -39,6 +42,7 @@ type Options struct { // SamplingFraction determines which rate of traces to sample. A value of 1 // means to keep 100% of traces. A value of 0 means to keep 0% of traces. SamplingFraction float64 `alloy:"sampling_fraction,attr,optional"` + SendTraceparent bool `alloy:"send_traceparent,attr,optional"` // Sampler holds optional samplers to configure on top of the sampling // fraction. @@ -109,6 +113,8 @@ func New(cfg Options) (*Tracer, error) { var sampler lazySampler sampler.SetSampler(tracesdk.TraceIDRatioBased(cfg.SamplingFraction)) + setOTELTraceContextPropagators(cfg) + shimClient := &client{} exp := otlptrace.NewUnstarted(shimClient) @@ -136,6 +142,8 @@ func (t *Tracer) Update(opts Options) error { t.samplerMut.Lock() defer t.samplerMut.Unlock() + setOTELTraceContextPropagators(opts) + t.client.UpdateWriteTo(opts.WriteTo) // Stop the previous instance of the Jaeger remote sampler if it exists. The @@ -169,6 +177,19 @@ func (t *Tracer) Update(opts Options) error { return nil } +func setOTELTraceContextPropagators(opts Options) { + var propagators []propagation.TextMapPropagator + if opts.SendTraceparent { + propagators = append( + propagators, + propagation.TraceContext{}, + propagation.Baggage{}, + ) + } + + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagators...)) +} + // Run starts the tracing subsystem and runs it until the provided context is // canceled. If the tracing subsystem could not be started, an error is // returned.