Files
llmgw/internal/obs/trace_test.go
T
Ilker ManapandClaude Opus 5.5 e725adc2f0 Tracing beyond the router: reconcile passes, placement and a replica's start traced down to the node
A reconcile pass that does something is a trace, with placement (where it
went, or every candidate turned down), scale-up/down, drain, stop, eviction,
preemption, reaping and restarts beneath it. A replica's start is a span open
from placement until it serves; the start command carries its context in a
new ControlMessage.trace field, and the agent continues the trace through
the weights fetch, engine launch, rendezvous and readiness wait. Stops,
drains, adoption and engine installs are traced on the node, model jobs are
a trace with a span per step linked to the replica's start, and agent.yaml
takes the same tracing block as server.yaml. Off, every span is the no-op one
and commands carry nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 00:03:17 +02:00

83 lines
2.9 KiB
Go

package obs
import (
"context"
"errors"
"testing"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
)
func TestTracingIsOffUntilGivenSomewhereToSend(t *testing.T) {
t.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "")
stop, err := SetupTracing(context.Background(), TracingOptions{Service: "t"})
if err != nil || stop(context.Background()) != nil {
t.Fatal(err)
}
for _, bad := range []string{"otel:4318", "ftp://otel:4318", "http://"} {
if _, err := SetupTracing(context.Background(), TracingOptions{Endpoint: bad}); err == nil {
t.Errorf("%q accepted", bad)
}
}
}
func TestATraceCrossesAMessageAndContinuesOnTheOtherSide(t *testing.T) {
rec := tracetest.NewSpanRecorder()
prevTP, prevProp := otel.GetTracerProvider(), otel.GetTextMapPropagator()
otel.SetTracerProvider(sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(rec)))
otel.SetTextMapPropagator(propagation.TraceContext{})
t.Cleanup(func() { otel.SetTracerProvider(prevTP); otel.SetTextMapPropagator(prevProp) })
if m := Inject(context.Background()); m != nil {
t.Errorf("a context with no span carried %v", m)
}
if ctx := Extract(context.Background(), nil); trace.SpanContextFromContext(ctx).IsValid() {
t.Error("nothing was carried, yet a trace continued")
}
ctx, sent := Tracer("t").Start(context.Background(), "send")
carried := Inject(ctx)
sent.End()
if carried["traceparent"] == "" {
t.Fatalf("no traceparent carried: %v", carried)
}
_, got := Tracer("t").Start(Extract(context.Background(), carried), "receive")
End(got, errors.New("it broke"))
spans := rec.Ended()
if len(spans) != 2 {
t.Fatalf("%d spans", len(spans))
}
recv := spans[1]
if recv.Parent().SpanID() != sent.SpanContext().SpanID() || recv.SpanContext().TraceID() != sent.SpanContext().TraceID() {
t.Error("the receiving span is not the sending one's child")
}
if recv.Status().Code != codes.Error || recv.Status().Description != "it broke" {
t.Errorf("a failure was not recorded: %+v", recv.Status())
}
}
func TestWithTracingOffAMessageCarriesNothing(t *testing.T) {
// What a process that never called SetupTracing has: spans that are not
// recorded and contexts with nothing to propagate.
prevTP, prevProp := otel.GetTracerProvider(), otel.GetTextMapPropagator()
otel.SetTracerProvider(noop.NewTracerProvider())
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator())
t.Cleanup(func() { otel.SetTracerProvider(prevTP); otel.SetTextMapPropagator(prevProp) })
ctx, span := Tracer("t").Start(context.Background(), "send")
defer span.End()
if span.IsRecording() {
t.Error("a span is recorded with tracing off")
}
if m := Inject(ctx); m != nil {
t.Errorf("a message carries %v with tracing off", m)
}
}