Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 2 additions & 29 deletions middleware/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,21 @@ package middleware

import (
"context"
"crypto/rand"

"github.com/go-coldbrew/log"
"github.com/go-coldbrew/tracing"
"github.com/go-coldbrew/workers"
oteltrace "go.opentelemetry.io/otel/trace"
)

// Tracing creates an OTEL span per cycle via go-coldbrew/tracing.
// Tracing creates an OTEL root span per cycle via go-coldbrew/tracing.
// The span is named "worker:<name>:cycle" and records errors.
//
// Worker spans are always sampled regardless of the global
// TracerProvider's sampler. This prevents silent span drops when
// using ParentBased(TraceIDRatioBased(ratio)), where worker root
// spans (which have no parent) would otherwise be probabilistically
// dropped.
// Sampling is determined by the global TracerProvider's sampler.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
//
Comment thread
ankurs marked this conversation as resolved.
Outdated
// The OTEL trace ID is injected into the log context as "trace"
// for correlation with the tracing backend.
func Tracing() workers.Middleware {
return func(ctx context.Context, info *workers.WorkerInfo, next workers.CycleFunc) error {
ctx = ensureSampled(ctx)
span, ctx := tracing.NewInternalSpan(ctx, "worker:"+info.GetName()+":cycle")
defer span.Finish()

Expand All @@ -38,23 +31,3 @@ func Tracing() workers.Middleware {
return err
}
}

// ensureSampled injects a sampled remote span context so that
// ParentBased samplers always sample the next span created from
// this context. If the context already has a sampled span, it is
// returned unchanged.
func ensureSampled(ctx context.Context) context.Context {
if oteltrace.SpanFromContext(ctx).SpanContext().IsSampled() {
return ctx
}
var traceID oteltrace.TraceID
var spanID oteltrace.SpanID
_, _ = rand.Read(traceID[:])
_, _ = rand.Read(spanID[:])
return oteltrace.ContextWithRemoteSpanContext(ctx, oteltrace.NewSpanContext(oteltrace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
TraceFlags: oteltrace.FlagsSampled,
Remote: true,
}))
}
40 changes: 0 additions & 40 deletions middleware/tracing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/go-coldbrew/workers"
"github.com/stretchr/testify/assert"
oteltrace "go.opentelemetry.io/otel/trace"
)

func TestTracing_NoPanic(t *testing.T) {
Expand All @@ -33,42 +32,3 @@ func TestTracing_PropagatesError(t *testing.T) {

assert.ErrorIs(t, err, assert.AnError)
}

func TestEnsureSampled(t *testing.T) {
// From a bare context (no span), ensureSampled should inject a
// sampled remote span context.
ctx := ensureSampled(context.Background())
sc := oteltrace.SpanContextFromContext(ctx)

assert.True(t, sc.IsSampled(), "should be sampled")
assert.True(t, sc.IsRemote(), "should be remote")
assert.True(t, sc.HasTraceID(), "should have a trace ID")
assert.True(t, sc.HasSpanID(), "should have a span ID")
}

func TestEnsureSampled_AlreadySampled(t *testing.T) {
// If context already has a sampled span, ensureSampled is a no-op.
existing := oteltrace.NewSpanContext(oteltrace.SpanContextConfig{
TraceID: oteltrace.TraceID{1, 2, 3},
SpanID: oteltrace.SpanID{4, 5, 6},
TraceFlags: oteltrace.FlagsSampled,
Remote: true,
})
ctx := oteltrace.ContextWithRemoteSpanContext(context.Background(), existing)

ctx = ensureSampled(ctx)
sc := oteltrace.SpanContextFromContext(ctx)

assert.Equal(t, existing.TraceID(), sc.TraceID(), "should keep existing trace ID")
assert.Equal(t, existing.SpanID(), sc.SpanID(), "should keep existing span ID")
}

func TestEnsureSampled_UniqueIDs(t *testing.T) {
ctx1 := ensureSampled(context.Background())
ctx2 := ensureSampled(context.Background())

sc1 := oteltrace.SpanContextFromContext(ctx1)
sc2 := oteltrace.SpanContextFromContext(ctx2)

assert.NotEqual(t, sc1.TraceID(), sc2.TraceID(), "each call should generate unique trace IDs")
}
Loading