-
Notifications
You must be signed in to change notification settings - Fork 436
/
tracer.go
99 lines (82 loc) · 3.09 KB
/
tracer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2023 Datadog, Inc.
package opentelemetry
import (
"context"
"encoding/binary"
"encoding/hex"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry"
oteltrace "go.opentelemetry.io/otel/trace"
)
var _ oteltrace.Tracer = (*oteltracer)(nil)
var telemetryTags = []string{`"integration_name":"otel"`}
type oteltracer struct {
provider *TracerProvider
ddtrace.Tracer
}
func (t *oteltracer) Start(ctx context.Context, spanName string, opts ...oteltrace.SpanStartOption) (context.Context, oteltrace.Span) {
var ssConfig = oteltrace.NewSpanStartConfig(opts...)
var ddopts []ddtrace.StartSpanOption
if !ssConfig.NewRoot() {
if s, ok := tracer.SpanFromContext(ctx); ok {
// if the span originates from the Datadog tracer,
// inherit given span context as a parent
ddopts = append(ddopts, tracer.ChildOf(s.Context()))
} else if sctx := oteltrace.SpanFromContext(ctx).SpanContext(); sctx.IsValid() {
// if the span doesn't originate from the Datadog tracer,
// use SpanContextW3C implementation struct to pass span context information
ddopts = append(ddopts, tracer.ChildOf(&otelCtxToDDCtx{sctx}))
}
}
if t := ssConfig.Timestamp(); !t.IsZero() {
ddopts = append(ddopts, tracer.StartTime(ssConfig.Timestamp()))
}
for _, attr := range ssConfig.Attributes() {
ddopts = append(ddopts, tracer.Tag(string(attr.Key), attr.Value.AsInterface()))
}
if k := ssConfig.SpanKind(); k != 0 {
ddopts = append(ddopts, tracer.SpanType(k.String()))
}
if opts, ok := spanOptionsFromContext(ctx); ok {
ddopts = append(ddopts, opts...)
}
telemetry.GlobalClient.Count(telemetry.NamespaceTracers, "spans_created", 1.0, telemetryTags, true)
s := tracer.StartSpan(spanName, ddopts...)
os := oteltrace.Span(&span{
Span: s,
oteltracer: t,
})
// Erase the start span options from the context to prevent them from being propagated to children
ctx = context.WithValue(ctx, startOptsKey, nil)
// Wrap the span in Opentelemetry and Datadog contexts to propagate span context values
ctx = oteltrace.ContextWithSpan(tracer.ContextWithSpan(ctx, s), os)
return ctx, os
}
type otelCtxToDDCtx struct {
oc oteltrace.SpanContext
}
func (c *otelCtxToDDCtx) TraceID() uint64 {
id := c.oc.TraceID()
return binary.BigEndian.Uint64(id[8:])
}
func (c *otelCtxToDDCtx) SpanID() uint64 {
id := c.oc.SpanID()
return binary.BigEndian.Uint64(id[:])
}
func (c *otelCtxToDDCtx) ForeachBaggageItem(_ func(k, v string) bool) {}
func (c *otelCtxToDDCtx) TraceID128() string {
id := c.oc.TraceID()
return hex.EncodeToString(id[:])
}
func (c *otelCtxToDDCtx) TraceID128Bytes() [16]byte {
return c.oc.TraceID()
}
var _ oteltrace.Tracer = (*noopOteltracer)(nil)
type noopOteltracer struct{}
func (n *noopOteltracer) Start(_ context.Context, _ string, _ ...oteltrace.SpanStartOption) (context.Context, oteltrace.Span) {
return nil, nil
}