1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-05 22:54:18 +02:00

Added methods for SpanID and TraceID on bridgeSpanContext (#3966)

* Added methods for SpanID and TraceID on bridgeSpanContext

* changed test name

* Added entry in changelog, updated readme, added comments on methods and fixed test case

* updated CHANGELOG.md

* promoted all methods from SpanContext to bridgeSpanContext

* fixed readme and removed redudant IsSampled() from bridgeContext

* fixed readme lint

* Apply suggestions from code review

Co-authored-by: Robert Pająk <pellared@hotmail.com>

* addressed code review comment

---------

Co-authored-by: Robert Pająk <pellared@hotmail.com>
This commit is contained in:
Kaushal Shah 2023-04-25 22:41:03 +05:30 committed by GitHub
parent 6acade86c5
commit 86f325839c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 26 deletions

View File

@ -35,6 +35,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) 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) - 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` - `metric.NewNoopMeterProvider` is replaced with `noop.NewMeterProvider`
- Add all the methods from `"go.opentelemetry.io/otel/trace".SpanContext` to `bridgeSpanContext` by embedding `otel.SpanContext` in `bridgeSpanContext`. (#3966)
- Wrap `UploadMetrics` error in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/` to improve error message when encountering generic grpc errors. (#3974) - Wrap `UploadMetrics` error in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/` to improve error message when encountering generic grpc errors. (#3974)
- The measurement methods for all instruments in `go.opentelemetry.io/otel/metric/instrument` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971) - The measurement methods for all instruments in `go.opentelemetry.io/otel/metric/instrument` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971)
- The `Int64Counter.Add` method now accepts `...AddOption` - The `Int64Counter.Add` method now accepts `...AddOption`

View File

@ -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. The bridge functionality can be extended beyond the OpenTracing API.
### `SpanContext.IsSampled` Any [`trace.SpanContext`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanContext) method can be accessed as following:
Return the underlying OpenTelemetry [`Span.IsSampled`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanContext.IsSampled) value by converting a `bridgeSpanContext`.
```go ```go
type samplable interface { type spanContextProvider interface {
IsSampled() bool 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 = ... var sc opentracing.SpanContext = ...
if s, ok := sc.(samplable); ok && s.IsSampled() { if s, ok := sc.(spanContextProvider); ok {
// Do something with sc knowing it is sampled. // Use TraceID by s.TraceID()
// Use SpanID by s.SpanID()
// Use TraceFlags by s.TraceFlags()
...
} }
``` ```

View File

@ -44,16 +44,16 @@ var (
) )
type bridgeSpanContext struct { type bridgeSpanContext struct {
bag baggage.Baggage bag baggage.Baggage
otelSpanContext trace.SpanContext trace.SpanContext
} }
var _ ot.SpanContext = &bridgeSpanContext{} var _ ot.SpanContext = &bridgeSpanContext{}
func newBridgeSpanContext(otelSpanContext trace.SpanContext, parentOtSpanContext ot.SpanContext) *bridgeSpanContext { func newBridgeSpanContext(otelSpanContext trace.SpanContext, parentOtSpanContext ot.SpanContext) *bridgeSpanContext {
bCtx := &bridgeSpanContext{ bCtx := &bridgeSpanContext{
bag: baggage.Baggage{}, bag: baggage.Baggage{},
otelSpanContext: otelSpanContext, SpanContext: otelSpanContext,
} }
if parentOtSpanContext != nil { if parentOtSpanContext != nil {
parentOtSpanContext.ForeachBaggageItem(func(key, value string) bool { parentOtSpanContext.ForeachBaggageItem(func(key, value string) bool {
@ -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) { func (c *bridgeSpanContext) setBaggageItem(restrictedKey, value string) {
crk := http.CanonicalHeaderKey(restrictedKey) crk := http.CanonicalHeaderKey(restrictedKey)
m, err := baggage.NewMember(crk, value) m, err := baggage.NewMember(crk, value)
@ -429,7 +425,7 @@ func (t *BridgeTracer) StartSpan(operationName string, opts ...ot.StartSpanOptio
attributes, kind, hadTrueErrorTag := otTagsToOTelAttributesKindAndError(sso.Tags) attributes, kind, hadTrueErrorTag := otTagsToOTelAttributesKindAndError(sso.Tags)
checkCtx := migration.WithDeferredSetup(context.Background()) checkCtx := migration.WithDeferredSetup(context.Background())
if parentBridgeSC != nil { if parentBridgeSC != nil {
checkCtx = trace.ContextWithRemoteSpanContext(checkCtx, parentBridgeSC.otelSpanContext) checkCtx = trace.ContextWithRemoteSpanContext(checkCtx, parentBridgeSC.SpanContext)
} }
checkCtx2, otelSpan := t.setTracer.tracer().Start( checkCtx2, otelSpan := t.setTracer.tracer().Start(
checkCtx, checkCtx,
@ -610,7 +606,7 @@ func otSpanReferencesToParentAndLinks(references []ot.SpanReference) (*bridgeSpa
func otSpanReferenceToOTelLink(bridgeSC *bridgeSpanContext, refType ot.SpanReferenceType) trace.Link { func otSpanReferenceToOTelLink(bridgeSC *bridgeSpanContext, refType ot.SpanReferenceType) trace.Link {
return trace.Link{ return trace.Link{
SpanContext: bridgeSC.otelSpanContext, SpanContext: bridgeSC.SpanContext,
Attributes: otSpanReferenceTypeToOTelLinkAttributes(refType), Attributes: otSpanReferenceTypeToOTelLinkAttributes(refType),
} }
} }
@ -655,7 +651,7 @@ func (t *BridgeTracer) Inject(sm ot.SpanContext, format interface{}, carrier int
if !ok { if !ok {
return ot.ErrInvalidSpanContext return ot.ErrInvalidSpanContext
} }
if !bridgeSC.otelSpanContext.IsValid() { if !bridgeSC.IsValid() {
return ot.ErrInvalidSpanContext return ot.ErrInvalidSpanContext
} }
@ -687,7 +683,7 @@ func (t *BridgeTracer) Inject(sm ot.SpanContext, format interface{}, carrier int
fs := fakeSpan{ fs := fakeSpan{
Span: noopSpan, Span: noopSpan,
sc: bridgeSC.otelSpanContext, sc: bridgeSC.SpanContext,
} }
ctx := trace.ContextWithSpan(context.Background(), fs) ctx := trace.ContextWithSpan(context.Background(), fs)
ctx = baggage.ContextWithBaggage(ctx, bridgeSC.bag) ctx = baggage.ContextWithBaggage(ctx, bridgeSC.bag)
@ -729,10 +725,10 @@ func (t *BridgeTracer) Extract(format interface{}, carrier interface{}) (ot.Span
ctx := t.getPropagator().Extract(context.Background(), textCarrier) ctx := t.getPropagator().Extract(context.Background(), textCarrier)
bag := baggage.FromContext(ctx) bag := baggage.FromContext(ctx)
bridgeSC := &bridgeSpanContext{ bridgeSC := &bridgeSpanContext{
bag: bag, bag: bag,
otelSpanContext: trace.SpanContextFromContext(ctx), SpanContext: trace.SpanContextFromContext(ctx),
} }
if !bridgeSC.otelSpanContext.IsValid() { if !bridgeSC.IsValid() {
return nil, ot.ErrSpanContextNotFound return nil, ot.ErrSpanContextNotFound
} }
return bridgeSC, nil return bridgeSC, nil

View File

@ -366,12 +366,12 @@ func TestBridgeTracer_ExtractAndInject(t *testing.T) {
bsc, ok := spanContext.(*bridgeSpanContext) bsc, ok := spanContext.(*bridgeSpanContext)
assert.True(t, ok) assert.True(t, ok)
require.NotNil(t, bsc) require.NotNil(t, bsc)
require.NotNil(t, bsc.otelSpanContext) require.NotNil(t, bsc.SpanContext)
require.NotNil(t, bsc.otelSpanContext.SpanID()) require.NotNil(t, bsc.SpanID())
require.NotNil(t, bsc.otelSpanContext.TraceID()) require.NotNil(t, bsc.TraceID())
assert.Equal(t, spanID.String(), bsc.otelSpanContext.SpanID().String()) assert.Equal(t, spanID.String(), bsc.SpanID().String())
assert.Equal(t, traceID.String(), bsc.otelSpanContext.TraceID().String()) assert.Equal(t, traceID.String(), bsc.TraceID().String())
} }
} }
}) })
@ -546,3 +546,33 @@ func TestBridge_SpanContext_IsSampled(t *testing.T) {
}) })
} }
} }
func TestBridgeSpanContextPromotedMethods(t *testing.T) {
bridge := NewBridgeTracer()
bridge.SetTextMapPropagator(new(testTextMapPropagator))
tmc := newTextCarrier()
type spanContextProvider interface {
HasTraceID() bool
TraceID() trace.TraceID
HasSpanID() bool
SpanID() trace.SpanID
}
err := bridge.Inject(newBridgeSpanContext(trace.NewSpanContext(trace.SpanContextConfig{
TraceID: [16]byte{byte(1)},
SpanID: [8]byte{byte(2)},
}), 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())
})
}