mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 19:01:42 +00:00
75 lines
2.3 KiB
Go
75 lines
2.3 KiB
Go
package testutil
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/propagation"
|
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
"go.opentelemetry.io/otel/sdk/trace/tracetest"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
// RecordSpans installs a recording tracer provider and the W3C trace-context
|
|
// propagator for the duration of the test, restoring both afterwards. The
|
|
// defaults are no-ops, so without this a span assertion sees nothing.
|
|
//
|
|
// Both are process globals, so a test using this cannot run in parallel.
|
|
func RecordSpans(t *testing.T) *tracetest.SpanRecorder {
|
|
t.Helper()
|
|
recorder := tracetest.NewSpanRecorder()
|
|
previousTracer := otel.GetTracerProvider()
|
|
previousPropagator := otel.GetTextMapPropagator()
|
|
otel.SetTracerProvider(sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(recorder)))
|
|
otel.SetTextMapPropagator(propagation.TraceContext{})
|
|
t.Cleanup(func() {
|
|
otel.SetTracerProvider(previousTracer)
|
|
otel.SetTextMapPropagator(previousPropagator)
|
|
})
|
|
return recorder
|
|
}
|
|
|
|
// SpanAttribute returns span's value for key, failing the test when absent.
|
|
func SpanAttribute(t *testing.T, span sdktrace.ReadOnlySpan, key string) attribute.Value {
|
|
t.Helper()
|
|
for _, attr := range span.Attributes() {
|
|
if string(attr.Key) == key {
|
|
return attr.Value
|
|
}
|
|
}
|
|
t.Fatalf("span %q has no attribute %q", span.Name(), key)
|
|
return attribute.Value{}
|
|
}
|
|
|
|
// SpansByKind returns the last recorded span of each kind (owner-first routing
|
|
// can record several client legs; the last answered). Servers reply before
|
|
// ending their span, so this waits for one and fails the test if none ends.
|
|
func SpansByKind(t *testing.T, recorder *tracetest.SpanRecorder) (client, server sdktrace.ReadOnlySpan) {
|
|
t.Helper()
|
|
deadline := time.Now().Add(5 * time.Second)
|
|
for {
|
|
client, server = lastSpansByKind(recorder.Ended())
|
|
if server != nil {
|
|
return client, server
|
|
}
|
|
if time.Now().After(deadline) {
|
|
t.Fatal("no server span recorded within 5s")
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func lastSpansByKind(spans []sdktrace.ReadOnlySpan) (client, server sdktrace.ReadOnlySpan) {
|
|
for _, span := range spans {
|
|
switch span.SpanKind() {
|
|
case trace.SpanKindClient:
|
|
client = span
|
|
case trace.SpanKindServer:
|
|
server = span
|
|
}
|
|
}
|
|
return client, server
|
|
}
|