From 69d09462dbd8497416857dc18542232857d152c1 Mon Sep 17 00:00:00 2001 From: Pijus Navickas Date: Thu, 23 Feb 2023 23:11:48 +0200 Subject: [PATCH] Implement IsSampled for OpenTelemetry bridgeSpanContext (#3570) * Add IsSampled to OpenTracing bridge * Add entry to CHANGELOG * Add note to the README * Update CHANGELOG.md Co-authored-by: Tyler Yahn * Update bridge/opentracing/README.md Co-authored-by: Tyler Yahn * Update bridge/opentracing/README.md Co-authored-by: Tyler Yahn * Update bridge/opentracing/README.md Co-authored-by: Tyler Yahn * Update bridge/opentracing/README.md Co-authored-by: Tyler Yahn * Add PR ID to changelog note --------- Co-authored-by: Tyler Yahn --- CHANGELOG.md | 1 + bridge/opentracing/README.md | 19 +++++++++++++++ bridge/opentracing/bridge.go | 4 ++++ bridge/opentracing/bridge_test.go | 36 +++++++++++++++++++++++++++++ bridge/opentracing/internal/mock.go | 3 ++- 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de8428f827..c58eb5fc67f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `OtelLibraryName` -> `OTelLibraryName` - `OtelLibraryVersion` -> `OTelLibraryVersion` - `OtelStatusDescription` -> `OTelStatusDescription` +- Add `bridgetSpanContext.IsSampled` to `go.opentelemetry.io/otel/bridget/opentracing` to expose whether span is sampled or not. (#3570) - The `WithInstrumentationAttributes` option to `go.opentelemetry.io/otel/metric`. (#3738) - The `WithInstrumentationAttributes` option to `go.opentelemetry.io/otel/trace`. (#3739) diff --git a/bridge/opentracing/README.md b/bridge/opentracing/README.md index a4477a87306..d6af6b1fbcf 100644 --- a/bridge/opentracing/README.md +++ b/bridge/opentracing/README.md @@ -38,3 +38,22 @@ When you have started an OpenTracing Span, make sure the OpenTelemetry knows abo // Propagate the otSpan to both OpenTracing and OpenTelemetry // instrumentation by using the ctxWithOTAndOTelSpan context. ``` + +## Extended Functionality + +The bridge functionality can be extended beyond the OpenTracing API. + +### `SpanContext.IsSampled` + +Return the underlying OpenTelemetry [`Span.IsSampled`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanContext.IsSampled) value by converting a `bridgeSpanContext`. + +```go +type samplable interface { + IsSampled() bool +} + +var sc opentracing.SpanContext = ... +if s, ok := sc.(samplable); ok && s.IsSampled() { + // Do something with sc knowing it is sampled. +} +``` diff --git a/bridge/opentracing/bridge.go b/bridge/opentracing/bridge.go index 4fcb532f04a..867a2a8c387 100644 --- a/bridge/opentracing/bridge.go +++ b/bridge/opentracing/bridge.go @@ -72,6 +72,10 @@ func (c *bridgeSpanContext) ForeachBaggageItem(handler func(k, v string) bool) { } } +func (c *bridgeSpanContext) IsSampled() bool { + return c.otelSpanContext.IsSampled() +} + func (c *bridgeSpanContext) setBaggageItem(restrictedKey, value string) { crk := http.CanonicalHeaderKey(restrictedKey) m, err := baggage.NewMember(crk, value) diff --git a/bridge/opentracing/bridge_test.go b/bridge/opentracing/bridge_test.go index 696f406371b..20c21a87565 100644 --- a/bridge/opentracing/bridge_test.go +++ b/bridge/opentracing/bridge_test.go @@ -257,6 +257,10 @@ func (t *testTextMapWriter) Set(key, val string) { (*t.m)[key] = val } +type samplable interface { + IsSampled() bool +} + func TestBridgeTracer_ExtractAndInject(t *testing.T) { bridge := NewBridgeTracer() bridge.SetTextMapPropagator(new(testTextMapPropagator)) @@ -510,3 +514,35 @@ func Test_otTagsToOTelAttributesKindAndError(t *testing.T) { }) } } + +func TestBridge_SpanContext_IsSampled(t *testing.T) { + testCases := []struct { + name string + flags trace.TraceFlags + expected bool + }{ + { + name: "not sampled", + flags: 0, + expected: false, + }, + { + name: "sampled", + flags: trace.FlagsSampled, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tracer := internal.NewMockTracer() + tracer.TraceFlags = tc.flags + + b, _ := NewTracerPair(tracer) + s := b.StartSpan("abc") + sc := s.Context() + + assert.Equal(t, tc.expected, sc.(samplable).IsSampled()) + }) + } +} diff --git a/bridge/opentracing/internal/mock.go b/bridge/opentracing/internal/mock.go index 99585c7562c..bb44e93d1f3 100644 --- a/bridge/opentracing/internal/mock.go +++ b/bridge/opentracing/internal/mock.go @@ -48,6 +48,7 @@ type MockTracer struct { SpareTraceIDs []trace.TraceID SpareSpanIDs []trace.SpanID SpareContextKeyValues []MockContextKeyValue + TraceFlags trace.TraceFlags randLock sync.Mutex rand *rand.Rand @@ -76,7 +77,7 @@ func (t *MockTracer) Start(ctx context.Context, name string, opts ...trace.SpanS spanContext := trace.NewSpanContext(trace.SpanContextConfig{ TraceID: t.getTraceID(ctx, &config), SpanID: t.getSpanID(), - TraceFlags: 0, + TraceFlags: t.TraceFlags, }) span := &MockSpan{ mockTracer: t,