Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added methods for SpanID and TraceID on bridgeSpanContext #3966

Merged
merged 14 commits into from
Apr 25, 2023
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
This adds an implementation requirement to set the interface default behavior for unimplemented methods. (#3916)
- Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#3941)
- `metric.NewNoopMeterProvider` is replaced with `noop.NewMeterProvider`
- Promoted all the methods from `otel.SpanContext` to `bridgeSpanContext` by embedding `otel.SpanContext` in `bridgeSpanContext`. (#3966)
Kaushal28 marked this conversation as resolved.
Show resolved Hide resolved

### Fixed

Expand Down
17 changes: 11 additions & 6 deletions bridge/opentracing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,22 @@ When you have started an OpenTracing Span, make sure the OpenTelemetry knows abo

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`.
Any [`SpanContext`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanContext) method can be accessed as following:
Kaushal28 marked this conversation as resolved.
Show resolved Hide resolved

```go
type samplable interface {
type spanContextProvider interface {
IsSampled() bool
TraceID() trace.TraceID
SpanID() trace.SpanID
TraceFlags() trace.TraceFlags
... // any other available method can be added here to access it
}

var sc opentracing.SpanContext = ...
if s, ok := sc.(samplable); ok && s.IsSampled() {
// Do something with sc knowing it is sampled.
if s, ok := sc.(spanContextProvider); ok {
// Use TraceID by s.TraceID()
// Use SpanID by s.SpanID()
// Use TraceFlags by s.TraceFlags()
...
}
```
26 changes: 11 additions & 15 deletions bridge/opentracing/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ var (
)

type bridgeSpanContext struct {
bag baggage.Baggage
otelSpanContext trace.SpanContext
bag baggage.Baggage
trace.SpanContext
}

var _ ot.SpanContext = &bridgeSpanContext{}

func newBridgeSpanContext(otelSpanContext trace.SpanContext, parentOtSpanContext ot.SpanContext) *bridgeSpanContext {
bCtx := &bridgeSpanContext{
bag: baggage.Baggage{},
otelSpanContext: otelSpanContext,
bag: baggage.Baggage{},
SpanContext: otelSpanContext,
}
if parentOtSpanContext != nil {
parentOtSpanContext.ForeachBaggageItem(func(key, value string) bool {
Expand All @@ -72,10 +72,6 @@ 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)
Expand Down Expand Up @@ -429,7 +425,7 @@ func (t *BridgeTracer) StartSpan(operationName string, opts ...ot.StartSpanOptio
attributes, kind, hadTrueErrorTag := otTagsToOTelAttributesKindAndError(sso.Tags)
checkCtx := migration.WithDeferredSetup(context.Background())
if parentBridgeSC != nil {
checkCtx = trace.ContextWithRemoteSpanContext(checkCtx, parentBridgeSC.otelSpanContext)
checkCtx = trace.ContextWithRemoteSpanContext(checkCtx, parentBridgeSC.SpanContext)
}
checkCtx2, otelSpan := t.setTracer.tracer().Start(
checkCtx,
Expand Down Expand Up @@ -610,7 +606,7 @@ func otSpanReferencesToParentAndLinks(references []ot.SpanReference) (*bridgeSpa

func otSpanReferenceToOTelLink(bridgeSC *bridgeSpanContext, refType ot.SpanReferenceType) trace.Link {
return trace.Link{
SpanContext: bridgeSC.otelSpanContext,
SpanContext: bridgeSC.SpanContext,
Attributes: otSpanReferenceTypeToOTelLinkAttributes(refType),
}
}
Expand Down Expand Up @@ -655,7 +651,7 @@ func (t *BridgeTracer) Inject(sm ot.SpanContext, format interface{}, carrier int
if !ok {
return ot.ErrInvalidSpanContext
}
if !bridgeSC.otelSpanContext.IsValid() {
if !bridgeSC.IsValid() {
return ot.ErrInvalidSpanContext
}

Expand Down Expand Up @@ -687,7 +683,7 @@ func (t *BridgeTracer) Inject(sm ot.SpanContext, format interface{}, carrier int

fs := fakeSpan{
Span: noopSpan,
sc: bridgeSC.otelSpanContext,
sc: bridgeSC.SpanContext,
}
ctx := trace.ContextWithSpan(context.Background(), fs)
ctx = baggage.ContextWithBaggage(ctx, bridgeSC.bag)
Expand Down Expand Up @@ -729,10 +725,10 @@ func (t *BridgeTracer) Extract(format interface{}, carrier interface{}) (ot.Span
ctx := t.getPropagator().Extract(context.Background(), textCarrier)
bag := baggage.FromContext(ctx)
bridgeSC := &bridgeSpanContext{
bag: bag,
otelSpanContext: trace.SpanContextFromContext(ctx),
bag: bag,
SpanContext: trace.SpanContextFromContext(ctx),
}
if !bridgeSC.otelSpanContext.IsValid() {
if !bridgeSC.IsValid() {
return nil, ot.ErrSpanContextNotFound
}
return bridgeSC, nil
Expand Down
56 changes: 51 additions & 5 deletions bridge/opentracing/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,12 @@ func TestBridgeTracer_ExtractAndInject(t *testing.T) {
bsc, ok := spanContext.(*bridgeSpanContext)
assert.True(t, ok)
require.NotNil(t, bsc)
require.NotNil(t, bsc.otelSpanContext)
require.NotNil(t, bsc.otelSpanContext.SpanID())
require.NotNil(t, bsc.otelSpanContext.TraceID())
require.NotNil(t, bsc.SpanContext)
require.NotNil(t, bsc.SpanID())
require.NotNil(t, bsc.TraceID())

assert.Equal(t, spanID.String(), bsc.otelSpanContext.SpanID().String())
assert.Equal(t, traceID.String(), bsc.otelSpanContext.TraceID().String())
assert.Equal(t, spanID.String(), bsc.SpanID().String())
assert.Equal(t, traceID.String(), bsc.TraceID().String())
}
}
})
Expand Down Expand Up @@ -546,3 +546,49 @@ func TestBridge_SpanContext_IsSampled(t *testing.T) {
})
}
}

func TestBridge_SpanContext_Promoted_Methods(t *testing.T) {
Kaushal28 marked this conversation as resolved.
Show resolved Hide resolved
bridge := NewBridgeTracer()
bridge.SetTextMapPropagator(new(testTextMapPropagator))

tmc := newTextCarrier()

type spanContextProvider interface {
HasTraceID() bool
TraceID() trace.TraceID
HasSpanID() bool
SpanID() trace.SpanID
}

testCases := []struct {
name string
traceID trace.TraceID
spanID trace.SpanID
}{
{
name: "support for getting spanID and traceID",
traceID: [16]byte{byte(1)},
spanID: [8]byte{byte(2)},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
Kaushal28 marked this conversation as resolved.
Show resolved Hide resolved
err := bridge.Inject(newBridgeSpanContext(trace.NewSpanContext(trace.SpanContextConfig{
TraceID: tc.traceID,
SpanID: tc.spanID,
}), nil), ot.TextMap, tmc)
assert.NoError(t, err)

spanContext, err := bridge.Extract(ot.TextMap, tmc)
assert.NoError(t, err)

assert.NotPanics(t, func() {
assert.Equal(t, spanID.String(), spanContext.(spanContextProvider).SpanID().String())
assert.Equal(t, traceID.String(), spanContext.(spanContextProvider).TraceID().String())
assert.True(t, spanContext.(spanContextProvider).HasSpanID())
assert.True(t, spanContext.(spanContextProvider).HasTraceID())
})
})
}
}