Upgraded DataDog tracing library to 1.14.0
This commit is contained in:
parent
1f2fe08c33
commit
adc2b62c22
13 changed files with 485 additions and 60 deletions
8
Gopkg.lock
generated
8
Gopkg.lock
generated
|
@ -1864,7 +1864,7 @@
|
|||
version = "v1.20.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b886012746f19e2a7c6c3901ea9f86e8a5e32ff2b4407086f4f3181269976957"
|
||||
digest = "1:b49eceff862a3048ec28dad1fce40bcbdc1703119dbad35d7e5f1beb4f9a4527"
|
||||
name = "gopkg.in/DataDog/dd-trace-go.v1"
|
||||
packages = [
|
||||
"ddtrace",
|
||||
|
@ -1872,10 +1872,11 @@
|
|||
"ddtrace/internal",
|
||||
"ddtrace/opentracer",
|
||||
"ddtrace/tracer",
|
||||
"internal/globalconfig",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "7fb2bce4b1ed6ab61f7a9e1be30dea56de19db7c"
|
||||
version = "v1.8.0"
|
||||
revision = "c19e9e56d5b5b71b6507ce1b0ec06d85aa3705a1"
|
||||
version = "v1.14.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c970218a20933dd0a2eb2006de922217fa9276f57d25009b2a934eb1c50031cc"
|
||||
|
@ -2287,6 +2288,7 @@
|
|||
"github.com/opentracing/opentracing-go/log",
|
||||
"github.com/openzipkin-contrib/zipkin-go-opentracing",
|
||||
"github.com/patrickmn/go-cache",
|
||||
"github.com/pmezard/go-difflib/difflib",
|
||||
"github.com/prometheus/client_golang/prometheus",
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp",
|
||||
"github.com/prometheus/client_model/go",
|
||||
|
|
|
@ -285,7 +285,7 @@ required = [
|
|||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/DataDog/dd-trace-go.v1"
|
||||
version = "1.7.0"
|
||||
version = "1.13.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/instana/go-sensor"
|
||||
|
|
10
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ddtrace.go
generated
vendored
10
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ddtrace.go
generated
vendored
|
@ -91,6 +91,12 @@ type FinishConfig struct {
|
|||
|
||||
// NoDebugStack will prevent any set errors from generating an attached stack trace tag.
|
||||
NoDebugStack bool
|
||||
|
||||
// StackFrames specifies the number of stack frames to be attached in spans that finish with errors.
|
||||
StackFrames uint
|
||||
|
||||
// SkipStackFrames specifies the offset at which to start reporting stack frames from the stack.
|
||||
SkipStackFrames uint
|
||||
}
|
||||
|
||||
// StartSpanConfig holds the configuration for starting a new span. It is usually passed
|
||||
|
@ -108,4 +114,8 @@ type StartSpanConfig struct {
|
|||
// Tags holds a set of key/value pairs that should be set as metadata on the
|
||||
// new span.
|
||||
Tags map[string]interface{}
|
||||
|
||||
// Force-set the SpanID, rather than use a random number. If no Parent SpanContext is present,
|
||||
// then this will also set the TraceID to the same value.
|
||||
SpanID uint64
|
||||
}
|
||||
|
|
25
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/tags.go
generated
vendored
25
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/tags.go
generated
vendored
|
@ -27,10 +27,15 @@ const (
|
|||
// HTTPURL sets the HTTP URL for a span.
|
||||
HTTPURL = "http.url"
|
||||
|
||||
// TODO: In the next major version, suffix these constants (SpanType, etc)
|
||||
// with "*Key" (SpanTypeKey, etc) to more easily differentiate between
|
||||
// TODO: In the next major version, prefix these constants (SpanType, etc)
|
||||
// with "Key*" (KeySpanType, etc) to more easily differentiate between
|
||||
// constants representing tag values and constants representing keys.
|
||||
|
||||
// SpanName is a pseudo-key for setting a span's operation name by means of
|
||||
// a tag. It is mostly here to facilitate vendor-agnostic frameworks like Opentracing
|
||||
// and OpenCensus.
|
||||
SpanName = "span.name"
|
||||
|
||||
// SpanType defines the Span type (web, db, cache).
|
||||
SpanType = "span.type"
|
||||
|
||||
|
@ -54,4 +59,20 @@ const (
|
|||
|
||||
// Environment specifies the environment to use with a trace.
|
||||
Environment = "env"
|
||||
|
||||
// EventSampleRate specifies the rate at which this span will be sampled
|
||||
// as an APM event.
|
||||
EventSampleRate = "_dd1.sr.eausr"
|
||||
|
||||
// AnalyticsEvent specifies whether the span should be recorded as a Trace
|
||||
// Search & Analytics event.
|
||||
AnalyticsEvent = "analytics.event"
|
||||
|
||||
// ManualKeep is a tag which specifies that the trace to which this span
|
||||
// belongs to should be kept when set to true.
|
||||
ManualKeep = "manual.keep"
|
||||
|
||||
// ManualDrop is a tag which specifies that the trace to which this span
|
||||
// belongs to should be dropped when set to true.
|
||||
ManualDrop = "manual.drop"
|
||||
)
|
||||
|
|
5
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer/option.go
generated
vendored
5
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer/option.go
generated
vendored
|
@ -18,6 +18,11 @@ func ResourceName(name string) opentracing.StartSpanOption {
|
|||
return opentracing.Tag{Key: ext.ResourceName, Value: name}
|
||||
}
|
||||
|
||||
// SpanName sets the Datadog operation name for the span.
|
||||
func SpanName(name string) opentracing.StartSpanOption {
|
||||
return opentracing.Tag{Key: ext.SpanName, Value: name}
|
||||
}
|
||||
|
||||
// SpanType can be used with opentracing.StartSpan to set the type of a span.
|
||||
func SpanType(name string) opentracing.StartSpanOption {
|
||||
return opentracing.Tag{Key: ext.SpanType, Value: name}
|
||||
|
|
55
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/option.go
generated
vendored
55
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/option.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package tracer
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -8,6 +9,7 @@ import (
|
|||
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
|
||||
)
|
||||
|
||||
// config holds the tracer configuration.
|
||||
|
@ -21,7 +23,7 @@ type config struct {
|
|||
// sampler specifies the sampler that will be used for sampling traces.
|
||||
sampler Sampler
|
||||
|
||||
// agentAddr specifies the hostname and of the agent where the traces
|
||||
// agentAddr specifies the hostname and port of the agent where the traces
|
||||
// are sent to.
|
||||
agentAddr string
|
||||
|
||||
|
@ -37,6 +39,10 @@ type config struct {
|
|||
|
||||
// httpRoundTripper defines the http.RoundTripper used by the agent transport.
|
||||
httpRoundTripper http.RoundTripper
|
||||
|
||||
// hostname is automatically assigned when the DD_TRACE_REPORT_HOSTNAME is set to true,
|
||||
// and is added as a special tag to the root span of traces.
|
||||
hostname string
|
||||
}
|
||||
|
||||
// StartOption represents a function that can be provided as a parameter to Start.
|
||||
|
@ -47,6 +53,14 @@ func defaults(c *config) {
|
|||
c.serviceName = filepath.Base(os.Args[0])
|
||||
c.sampler = NewAllSampler()
|
||||
c.agentAddr = defaultAddress
|
||||
|
||||
if os.Getenv("DD_TRACE_REPORT_HOSTNAME") == "true" {
|
||||
var err error
|
||||
c.hostname, err = os.Hostname()
|
||||
if err != nil {
|
||||
log.Printf("%sunable to look up hostname: %v\n", errorPrefix, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithPrioritySampling is deprecated, and priority sampling is enabled by default.
|
||||
|
@ -117,6 +131,22 @@ func WithHTTPRoundTripper(r http.RoundTripper) StartOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithAnalytics allows specifying whether Trace Search & Analytics should be enabled
|
||||
// for integrations.
|
||||
func WithAnalytics(on bool) StartOption {
|
||||
if on {
|
||||
return WithAnalyticsRate(1.0)
|
||||
}
|
||||
return WithAnalyticsRate(0.0)
|
||||
}
|
||||
|
||||
// WithAnalyticsRate sets the global sampling rate for sampling APM events.
|
||||
func WithAnalyticsRate(rate float64) StartOption {
|
||||
return func(_ *config) {
|
||||
globalconfig.SetAnalyticsRate(rate)
|
||||
}
|
||||
}
|
||||
|
||||
// StartSpanOption is a configuration option for StartSpan. It is aliased in order
|
||||
// to help godoc group all the functions returning it together. It is considered
|
||||
// more correct to refer to it as the type as the origin, ddtrace.StartSpanOption.
|
||||
|
@ -149,6 +179,15 @@ func SpanType(name string) StartSpanOption {
|
|||
return Tag(ext.SpanType, name)
|
||||
}
|
||||
|
||||
// WithSpanID sets the SpanID on the started span, instead of using a random number.
|
||||
// If there is no parent Span (eg from ChildOf), then the TraceID will also be set to the
|
||||
// value given here.
|
||||
func WithSpanID(id uint64) StartSpanOption {
|
||||
return func(cfg *ddtrace.StartSpanConfig) {
|
||||
cfg.SpanID = id
|
||||
}
|
||||
}
|
||||
|
||||
// ChildOf tells StartSpan to use the given span context as a parent for the
|
||||
// created span.
|
||||
func ChildOf(ctx ddtrace.SpanContext) StartSpanOption {
|
||||
|
@ -179,7 +218,8 @@ func FinishTime(t time.Time) FinishOption {
|
|||
}
|
||||
|
||||
// WithError marks the span as having had an error. It uses the information from
|
||||
// err to set tags such as the error message, error type and stack trace.
|
||||
// err to set tags such as the error message, error type and stack trace. It has
|
||||
// no effect if the error is nil.
|
||||
func WithError(err error) FinishOption {
|
||||
return func(cfg *ddtrace.FinishConfig) {
|
||||
cfg.Error = err
|
||||
|
@ -194,3 +234,14 @@ func NoDebugStack() FinishOption {
|
|||
cfg.NoDebugStack = true
|
||||
}
|
||||
}
|
||||
|
||||
// StackFrames limits the number of stack frames included into erroneous spans to n, starting from skip.
|
||||
func StackFrames(n, skip uint) FinishOption {
|
||||
if n == 0 {
|
||||
return NoDebugStack()
|
||||
}
|
||||
return func(cfg *ddtrace.FinishConfig) {
|
||||
cfg.StackFrames = n
|
||||
cfg.SkipStackFrames = skip
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/sampler.go
generated
vendored
2
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/sampler.go
generated
vendored
|
@ -140,5 +140,5 @@ func (ps *prioritySampler) apply(spn *span) {
|
|||
} else {
|
||||
spn.SetTag(ext.SamplingPriority, ext.PriorityAutoReject)
|
||||
}
|
||||
spn.SetTag(samplingPriorityRateKey, rate)
|
||||
spn.SetTag(keySamplingPriorityRate, rate)
|
||||
}
|
||||
|
|
99
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span.go
generated
vendored
99
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span.go
generated
vendored
|
@ -5,7 +5,9 @@ package tracer
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -30,6 +32,13 @@ var (
|
|||
_ msgp.Decodable = (*spanLists)(nil)
|
||||
)
|
||||
|
||||
// errorConfig holds customization options for setting error tags.
|
||||
type errorConfig struct {
|
||||
noDebugStack bool
|
||||
stackFrames uint
|
||||
stackSkip uint
|
||||
}
|
||||
|
||||
// span represents a computation. Callers must call Finish when a span is
|
||||
// complete to ensure it's submitted.
|
||||
type span struct {
|
||||
|
@ -80,8 +89,13 @@ func (s *span) SetTag(key string, value interface{}) {
|
|||
if s.finished {
|
||||
return
|
||||
}
|
||||
if key == ext.Error {
|
||||
s.setTagError(value, true)
|
||||
switch key {
|
||||
case ext.Error:
|
||||
s.setTagError(value, &errorConfig{})
|
||||
return
|
||||
}
|
||||
if v, ok := value.(bool); ok {
|
||||
s.setTagBool(key, v)
|
||||
return
|
||||
}
|
||||
if v, ok := value.(string); ok {
|
||||
|
@ -99,7 +113,7 @@ func (s *span) SetTag(key string, value interface{}) {
|
|||
|
||||
// setTagError sets the error tag. It accounts for various valid scenarios.
|
||||
// This method is not safe for concurrent use.
|
||||
func (s *span) setTagError(value interface{}, debugStack bool) {
|
||||
func (s *span) setTagError(value interface{}, cfg *errorConfig) {
|
||||
if s.finished {
|
||||
return
|
||||
}
|
||||
|
@ -117,8 +131,12 @@ func (s *span) setTagError(value interface{}, debugStack bool) {
|
|||
s.Error = 1
|
||||
s.Meta[ext.ErrorMsg] = v.Error()
|
||||
s.Meta[ext.ErrorType] = reflect.TypeOf(v).String()
|
||||
if debugStack {
|
||||
s.Meta[ext.ErrorStack] = string(debug.Stack())
|
||||
if !cfg.noDebugStack {
|
||||
if cfg.stackFrames == 0 {
|
||||
s.Meta[ext.ErrorStack] = string(debug.Stack())
|
||||
} else {
|
||||
s.Meta[ext.ErrorStack] = takeStacktrace(cfg.stackFrames, cfg.stackSkip)
|
||||
}
|
||||
}
|
||||
case nil:
|
||||
// no error
|
||||
|
@ -130,9 +148,40 @@ func (s *span) setTagError(value interface{}, debugStack bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// takeStacktrace takes stacktrace
|
||||
func takeStacktrace(n, skip uint) string {
|
||||
var builder strings.Builder
|
||||
pcs := make([]uintptr, n)
|
||||
|
||||
// +2 to exclude runtime.Callers and takeStacktrace
|
||||
numFrames := runtime.Callers(2+int(skip), pcs)
|
||||
if numFrames == 0 {
|
||||
return ""
|
||||
}
|
||||
frames := runtime.CallersFrames(pcs[:numFrames])
|
||||
for i := 0; ; i++ {
|
||||
frame, more := frames.Next()
|
||||
if i != 0 {
|
||||
builder.WriteByte('\n')
|
||||
}
|
||||
builder.WriteString(frame.Function)
|
||||
builder.WriteByte('\n')
|
||||
builder.WriteByte('\t')
|
||||
builder.WriteString(frame.File)
|
||||
builder.WriteByte(':')
|
||||
builder.WriteString(strconv.Itoa(frame.Line))
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// setTagString sets a string tag. This method is not safe for concurrent use.
|
||||
func (s *span) setTagString(key, v string) {
|
||||
switch key {
|
||||
case ext.SpanName:
|
||||
s.Name = v
|
||||
case ext.ServiceName:
|
||||
s.Service = v
|
||||
case ext.ResourceName:
|
||||
|
@ -144,13 +193,39 @@ func (s *span) setTagString(key, v string) {
|
|||
}
|
||||
}
|
||||
|
||||
// setTagBool sets a boolean tag on the span.
|
||||
func (s *span) setTagBool(key string, v bool) {
|
||||
switch key {
|
||||
case ext.AnalyticsEvent:
|
||||
if v {
|
||||
s.setTagNumeric(ext.EventSampleRate, 1.0)
|
||||
} else {
|
||||
s.setTagNumeric(ext.EventSampleRate, 0.0)
|
||||
}
|
||||
case ext.ManualDrop:
|
||||
if v {
|
||||
s.setTagNumeric(ext.SamplingPriority, ext.PriorityUserReject)
|
||||
}
|
||||
case ext.ManualKeep:
|
||||
if v {
|
||||
s.setTagNumeric(ext.SamplingPriority, ext.PriorityUserKeep)
|
||||
}
|
||||
default:
|
||||
if v {
|
||||
s.setTagString(key, "true")
|
||||
} else {
|
||||
s.setTagString(key, "false")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setTagNumeric sets a numeric tag, in our case called a metric. This method
|
||||
// is not safe for concurrent use.
|
||||
func (s *span) setTagNumeric(key string, v float64) {
|
||||
switch key {
|
||||
case ext.SamplingPriority:
|
||||
// setting sampling priority per spec
|
||||
s.Metrics[samplingPriorityKey] = v
|
||||
s.Metrics[keySamplingPriority] = v
|
||||
s.context.setSamplingPriority(int(v))
|
||||
default:
|
||||
s.Metrics[key] = v
|
||||
|
@ -172,7 +247,11 @@ func (s *span) Finish(opts ...ddtrace.FinishOption) {
|
|||
}
|
||||
if cfg.Error != nil {
|
||||
s.Lock()
|
||||
s.setTagError(cfg.Error, !cfg.NoDebugStack)
|
||||
s.setTagError(cfg.Error, &errorConfig{
|
||||
noDebugStack: cfg.NoDebugStack,
|
||||
stackFrames: cfg.StackFrames,
|
||||
stackSkip: cfg.SkipStackFrames,
|
||||
})
|
||||
s.Unlock()
|
||||
}
|
||||
s.finish(t)
|
||||
|
@ -236,6 +315,8 @@ func (s *span) String() string {
|
|||
}
|
||||
|
||||
const (
|
||||
samplingPriorityKey = "_sampling_priority_v1"
|
||||
samplingPriorityRateKey = "_sampling_priority_rate_v1"
|
||||
keySamplingPriority = "_sampling_priority_v1"
|
||||
keySamplingPriorityRate = "_sampling_priority_rate_v1"
|
||||
keyOrigin = "_dd.origin"
|
||||
keyHostname = "_dd.hostname"
|
||||
)
|
||||
|
|
104
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/spancontext.go
generated
vendored
104
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/spancontext.go
generated
vendored
|
@ -25,10 +25,9 @@ type spanContext struct {
|
|||
traceID uint64
|
||||
spanID uint64
|
||||
|
||||
mu sync.RWMutex // guards below fields
|
||||
baggage map[string]string
|
||||
priority int
|
||||
hasPriority bool
|
||||
mu sync.RWMutex // guards below fields
|
||||
baggage map[string]string
|
||||
origin string // e.g. "synthetics"
|
||||
}
|
||||
|
||||
// newSpanContext creates a new SpanContext to serve as context for the given
|
||||
|
@ -42,15 +41,10 @@ func newSpanContext(span *span, parent *spanContext) *spanContext {
|
|||
spanID: span.SpanID,
|
||||
span: span,
|
||||
}
|
||||
if v, ok := span.Metrics[samplingPriorityKey]; ok {
|
||||
context.hasPriority = true
|
||||
context.priority = int(v)
|
||||
}
|
||||
if parent != nil {
|
||||
context.trace = parent.trace
|
||||
context.drop = parent.drop
|
||||
context.hasPriority = parent.hasSamplingPriority()
|
||||
context.priority = parent.samplingPriority()
|
||||
context.origin = parent.origin
|
||||
parent.ForeachBaggageItem(func(k, v string) bool {
|
||||
context.setBaggageItem(k, v)
|
||||
return true
|
||||
|
@ -59,6 +53,10 @@ func newSpanContext(span *span, parent *spanContext) *spanContext {
|
|||
if context.trace == nil {
|
||||
context.trace = newTrace()
|
||||
}
|
||||
if context.trace.root == nil {
|
||||
// first span in the trace can safely be assumed to be the root
|
||||
context.trace.root = span
|
||||
}
|
||||
// put span in context's trace
|
||||
context.trace.push(span)
|
||||
return context
|
||||
|
@ -82,22 +80,21 @@ func (c *spanContext) ForeachBaggageItem(handler func(k, v string) bool) {
|
|||
}
|
||||
|
||||
func (c *spanContext) setSamplingPriority(p int) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.priority = p
|
||||
c.hasPriority = true
|
||||
if c.trace == nil {
|
||||
c.trace = newTrace()
|
||||
}
|
||||
c.trace.setSamplingPriority(float64(p))
|
||||
}
|
||||
|
||||
func (c *spanContext) samplingPriority() int {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.priority
|
||||
if c.trace == nil {
|
||||
return 0
|
||||
}
|
||||
return c.trace.samplingPriority()
|
||||
}
|
||||
|
||||
func (c *spanContext) hasSamplingPriority() bool {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.hasPriority
|
||||
return c.trace != nil && c.trace.hasSamplingPriority()
|
||||
}
|
||||
|
||||
func (c *spanContext) setBaggageItem(key, val string) {
|
||||
|
@ -116,15 +113,23 @@ func (c *spanContext) baggageItem(key string) string {
|
|||
}
|
||||
|
||||
// finish marks this span as finished in the trace.
|
||||
func (c *spanContext) finish() { c.trace.ackFinish() }
|
||||
func (c *spanContext) finish() { c.trace.finishedOne(c.span) }
|
||||
|
||||
// trace holds information about a specific trace. This structure is shared
|
||||
// between all spans in a trace.
|
||||
// trace contains shared context information about a trace, such as sampling
|
||||
// priority, the root reference and a buffer of the spans which are part of the
|
||||
// trace, if these exist.
|
||||
type trace struct {
|
||||
mu sync.RWMutex // guards below fields
|
||||
spans []*span // all the spans that are part of this trace
|
||||
finished int // the number of finished spans
|
||||
full bool // signifies that the span buffer is full
|
||||
priority *float64 // sampling priority
|
||||
locked bool // specifies if the sampling priority can be altered
|
||||
|
||||
// root specifies the root of the trace, if known; it is nil when a span
|
||||
// context is extracted from a carrier, at which point there are no spans in
|
||||
// the trace yet.
|
||||
root *span
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -146,6 +151,42 @@ func newTrace() *trace {
|
|||
return &trace{spans: make([]*span, 0, traceStartSize)}
|
||||
}
|
||||
|
||||
func (t *trace) hasSamplingPriority() bool {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
return t.priority != nil
|
||||
}
|
||||
|
||||
func (t *trace) samplingPriority() int {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
if t.priority == nil {
|
||||
return 0
|
||||
}
|
||||
return int(*t.priority)
|
||||
}
|
||||
|
||||
func (t *trace) setSamplingPriority(p float64) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.setSamplingPriorityLocked(p)
|
||||
}
|
||||
|
||||
func (t *trace) setSamplingPriorityLocked(p float64) {
|
||||
if t.locked {
|
||||
return
|
||||
}
|
||||
if t.root == nil {
|
||||
// this trace is distributed (no local root); modifications
|
||||
// to the sampling priority are not allowed.
|
||||
t.locked = true
|
||||
}
|
||||
if t.priority == nil {
|
||||
t.priority = new(float64)
|
||||
}
|
||||
*t.priority = p
|
||||
}
|
||||
|
||||
// push pushes a new span into the trace. If the buffer is full, it returns
|
||||
// a errBufferFull error.
|
||||
func (t *trace) push(sp *span) {
|
||||
|
@ -164,12 +205,16 @@ func (t *trace) push(sp *span) {
|
|||
}
|
||||
return
|
||||
}
|
||||
if v, ok := sp.Metrics[keySamplingPriority]; ok {
|
||||
t.setSamplingPriorityLocked(v)
|
||||
}
|
||||
t.spans = append(t.spans, sp)
|
||||
}
|
||||
|
||||
// ackFinish aknowledges that another span in the trace has finished, and checks
|
||||
// if the trace is complete, in which case it calls the onFinish function.
|
||||
func (t *trace) ackFinish() {
|
||||
// finishedOne aknowledges that another span in the trace has finished, and checks
|
||||
// if the trace is complete, in which case it calls the onFinish function. It uses
|
||||
// the given priority, if non-nil, to mark the root span.
|
||||
func (t *trace) finishedOne(s *span) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.full {
|
||||
|
@ -180,6 +225,13 @@ func (t *trace) ackFinish() {
|
|||
return
|
||||
}
|
||||
t.finished++
|
||||
if s == t.root && t.priority != nil {
|
||||
// after the root has finished we lock down the priority;
|
||||
// we won't be able to make changes to a span after finishing
|
||||
// without causing a race condition.
|
||||
t.root.Metrics[keySamplingPriority] = *t.priority
|
||||
t.locked = true
|
||||
}
|
||||
if len(t.spans) != t.finished {
|
||||
return
|
||||
}
|
||||
|
|
180
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/textmap.go
generated
vendored
180
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/textmap.go
generated
vendored
|
@ -2,10 +2,12 @@ package tracer
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
|
||||
)
|
||||
|
||||
// HTTPHeadersCarrier wraps an http.Header as a TextMapWriter and TextMapReader, allowing
|
||||
|
@ -54,6 +56,11 @@ func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
headerPropagationStyleInject = "DD_PROPAGATION_STYLE_INJECT"
|
||||
headerPropagationStyleExtract = "DD_PROPAGATION_STYLE_EXTRACT"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultBaggageHeaderPrefix specifies the prefix that will be used in
|
||||
// HTTP headers or text maps to prefix baggage keys.
|
||||
|
@ -72,6 +79,10 @@ const (
|
|||
DefaultPriorityHeader = "x-datadog-sampling-priority"
|
||||
)
|
||||
|
||||
// originHeader specifies the name of the header indicating the origin of the trace.
|
||||
// It is used with the Synthetics product and usually has the value "synthetics".
|
||||
const originHeader = "x-datadog-origin"
|
||||
|
||||
// PropagatorConfig defines the configuration for initializing a propagator.
|
||||
type PropagatorConfig struct {
|
||||
// BaggagePrefix specifies the prefix that will be used to store baggage
|
||||
|
@ -110,21 +121,86 @@ func NewPropagator(cfg *PropagatorConfig) Propagator {
|
|||
if cfg.PriorityHeader == "" {
|
||||
cfg.PriorityHeader = DefaultPriorityHeader
|
||||
}
|
||||
return &propagator{cfg}
|
||||
return &chainedPropagator{
|
||||
injectors: getPropagators(cfg, headerPropagationStyleInject),
|
||||
extractors: getPropagators(cfg, headerPropagationStyleExtract),
|
||||
}
|
||||
}
|
||||
|
||||
// propagator implements a propagator which uses TextMap internally.
|
||||
// It propagates the trace and span IDs, as well as the baggage from the
|
||||
// context.
|
||||
type propagator struct{ cfg *PropagatorConfig }
|
||||
// chainedPropagator implements Propagator and applies a list of injectors and extractors.
|
||||
// When injecting, all injectors are called to propagate the span context.
|
||||
// When extracting, it tries each extractor, selecting the first successful one.
|
||||
type chainedPropagator struct {
|
||||
injectors []Propagator
|
||||
extractors []Propagator
|
||||
}
|
||||
|
||||
// getPropagators returns a list of propagators based on the list found in the
|
||||
// given environment variable. If the list doesn't contain a value or has invalid
|
||||
// values, the default propagator will be returned.
|
||||
func getPropagators(cfg *PropagatorConfig, env string) []Propagator {
|
||||
dd := &propagator{cfg}
|
||||
ps := os.Getenv(env)
|
||||
if ps == "" {
|
||||
return []Propagator{dd}
|
||||
}
|
||||
var list []Propagator
|
||||
for _, v := range strings.Split(ps, ",") {
|
||||
switch strings.ToLower(v) {
|
||||
case "datadog":
|
||||
list = append(list, dd)
|
||||
case "b3":
|
||||
list = append(list, &propagatorB3{})
|
||||
default:
|
||||
// TODO(cgilmour): consider logging something for invalid/unknown styles.
|
||||
}
|
||||
}
|
||||
if len(list) == 0 {
|
||||
// return the default
|
||||
return []Propagator{dd}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// Inject defines the Propagator to propagate SpanContext data
|
||||
// out of the current process. The implementation propagates the
|
||||
// TraceID and the current active SpanID, as well as the Span baggage.
|
||||
func (p *chainedPropagator) Inject(spanCtx ddtrace.SpanContext, carrier interface{}) error {
|
||||
for _, v := range p.injectors {
|
||||
err := v.Inject(spanCtx, carrier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Extract implements Propagator.
|
||||
func (p *chainedPropagator) Extract(carrier interface{}) (ddtrace.SpanContext, error) {
|
||||
for _, v := range p.extractors {
|
||||
ctx, err := v.Extract(carrier)
|
||||
if ctx != nil {
|
||||
// first extractor returns
|
||||
return ctx, nil
|
||||
}
|
||||
if err == ErrSpanContextNotFound {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, ErrSpanContextNotFound
|
||||
}
|
||||
|
||||
// propagator implements Propagator and injects/extracts span contexts
|
||||
// using datadog headers. Only TextMap carriers are supported.
|
||||
type propagator struct {
|
||||
cfg *PropagatorConfig
|
||||
}
|
||||
|
||||
func (p *propagator) Inject(spanCtx ddtrace.SpanContext, carrier interface{}) error {
|
||||
switch v := carrier.(type) {
|
||||
switch c := carrier.(type) {
|
||||
case TextMapWriter:
|
||||
return p.injectTextMap(spanCtx, v)
|
||||
return p.injectTextMap(spanCtx, c)
|
||||
default:
|
||||
return ErrInvalidCarrier
|
||||
}
|
||||
|
@ -141,6 +217,9 @@ func (p *propagator) injectTextMap(spanCtx ddtrace.SpanContext, writer TextMapWr
|
|||
if ctx.hasSamplingPriority() {
|
||||
writer.Set(p.cfg.PriorityHeader, strconv.Itoa(ctx.samplingPriority()))
|
||||
}
|
||||
if ctx.origin != "" {
|
||||
writer.Set(originHeader, ctx.origin)
|
||||
}
|
||||
// propagate OpenTracing baggage
|
||||
for k, v := range ctx.baggage {
|
||||
writer.Set(p.cfg.BaggagePrefix+k, v)
|
||||
|
@ -148,11 +227,10 @@ func (p *propagator) injectTextMap(spanCtx ddtrace.SpanContext, writer TextMapWr
|
|||
return nil
|
||||
}
|
||||
|
||||
// Extract implements Propagator.
|
||||
func (p *propagator) Extract(carrier interface{}) (ddtrace.SpanContext, error) {
|
||||
switch v := carrier.(type) {
|
||||
switch c := carrier.(type) {
|
||||
case TextMapReader:
|
||||
return p.extractTextMap(v)
|
||||
return p.extractTextMap(c)
|
||||
default:
|
||||
return nil, ErrInvalidCarrier
|
||||
}
|
||||
|
@ -180,6 +258,8 @@ func (p *propagator) extractTextMap(reader TextMapReader) (ddtrace.SpanContext,
|
|||
return ErrSpanContextCorrupted
|
||||
}
|
||||
ctx.setSamplingPriority(priority)
|
||||
case originHeader:
|
||||
ctx.origin = v
|
||||
default:
|
||||
if strings.HasPrefix(key, p.cfg.BaggagePrefix) {
|
||||
ctx.setBaggageItem(strings.TrimPrefix(key, p.cfg.BaggagePrefix), v)
|
||||
|
@ -195,3 +275,83 @@ func (p *propagator) extractTextMap(reader TextMapReader) (ddtrace.SpanContext,
|
|||
}
|
||||
return &ctx, nil
|
||||
}
|
||||
|
||||
const (
|
||||
b3TraceIDHeader = "x-b3-traceid"
|
||||
b3SpanIDHeader = "x-b3-spanid"
|
||||
b3SampledHeader = "x-b3-sampled"
|
||||
)
|
||||
|
||||
// propagatorB3 implements Propagator and injects/extracts span contexts
|
||||
// using B3 headers. Only TextMap carriers are supported.
|
||||
type propagatorB3 struct{}
|
||||
|
||||
func (p *propagatorB3) Inject(spanCtx ddtrace.SpanContext, carrier interface{}) error {
|
||||
switch c := carrier.(type) {
|
||||
case TextMapWriter:
|
||||
return p.injectTextMap(spanCtx, c)
|
||||
default:
|
||||
return ErrInvalidCarrier
|
||||
}
|
||||
}
|
||||
|
||||
func (*propagatorB3) injectTextMap(spanCtx ddtrace.SpanContext, writer TextMapWriter) error {
|
||||
ctx, ok := spanCtx.(*spanContext)
|
||||
if !ok || ctx.traceID == 0 || ctx.spanID == 0 {
|
||||
return ErrInvalidSpanContext
|
||||
}
|
||||
writer.Set(b3TraceIDHeader, strconv.FormatUint(ctx.traceID, 16))
|
||||
writer.Set(b3SpanIDHeader, strconv.FormatUint(ctx.spanID, 16))
|
||||
if ctx.hasSamplingPriority() {
|
||||
if ctx.samplingPriority() >= ext.PriorityAutoKeep {
|
||||
writer.Set(b3SampledHeader, "1")
|
||||
} else {
|
||||
writer.Set(b3SampledHeader, "0")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *propagatorB3) Extract(carrier interface{}) (ddtrace.SpanContext, error) {
|
||||
switch c := carrier.(type) {
|
||||
case TextMapReader:
|
||||
return p.extractTextMap(c)
|
||||
default:
|
||||
return nil, ErrInvalidCarrier
|
||||
}
|
||||
}
|
||||
|
||||
func (*propagatorB3) extractTextMap(reader TextMapReader) (ddtrace.SpanContext, error) {
|
||||
var ctx spanContext
|
||||
err := reader.ForeachKey(func(k, v string) error {
|
||||
var err error
|
||||
key := strings.ToLower(k)
|
||||
switch key {
|
||||
case b3TraceIDHeader:
|
||||
ctx.traceID, err = strconv.ParseUint(v, 16, 64)
|
||||
if err != nil {
|
||||
return ErrSpanContextCorrupted
|
||||
}
|
||||
case b3SpanIDHeader:
|
||||
ctx.spanID, err = strconv.ParseUint(v, 16, 64)
|
||||
if err != nil {
|
||||
return ErrSpanContextCorrupted
|
||||
}
|
||||
case b3SampledHeader:
|
||||
priority, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return ErrSpanContextCorrupted
|
||||
}
|
||||
ctx.setSamplingPriority(priority)
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ctx.traceID == 0 || ctx.spanID == 0 {
|
||||
return nil, ErrSpanContextNotFound
|
||||
}
|
||||
return &ctx, nil
|
||||
}
|
||||
|
|
25
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/tracer.go
generated
vendored
25
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/tracer.go
generated
vendored
|
@ -44,6 +44,8 @@ type tracer struct {
|
|||
|
||||
// prioritySampling holds an instance of the priority sampler.
|
||||
prioritySampling *prioritySampler
|
||||
// pid of the process
|
||||
pid string
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -131,6 +133,7 @@ func newTracer(opts ...StartOption) *tracer {
|
|||
errorBuffer: make(chan error, errorBufferSize),
|
||||
stopped: make(chan struct{}),
|
||||
prioritySampling: newPrioritySampler(),
|
||||
pid: strconv.Itoa(os.Getpid()),
|
||||
}
|
||||
|
||||
go t.worker()
|
||||
|
@ -230,7 +233,10 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt
|
|||
context = ctx
|
||||
}
|
||||
}
|
||||
id := random.Uint64()
|
||||
id := opts.SpanID
|
||||
if id == 0 {
|
||||
id = random.Uint64()
|
||||
}
|
||||
// span defaults
|
||||
span := &span{
|
||||
Name: operationName,
|
||||
|
@ -248,19 +254,28 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt
|
|||
span.TraceID = context.traceID
|
||||
span.ParentID = context.spanID
|
||||
if context.hasSamplingPriority() {
|
||||
span.Metrics[samplingPriorityKey] = float64(context.samplingPriority())
|
||||
span.Metrics[keySamplingPriority] = float64(context.samplingPriority())
|
||||
}
|
||||
if context.span != nil {
|
||||
// it has a local parent, inherit the service
|
||||
// local parent, inherit service
|
||||
context.span.RLock()
|
||||
span.Service = context.span.Service
|
||||
context.span.RUnlock()
|
||||
} else {
|
||||
// remote parent
|
||||
if context.origin != "" {
|
||||
// mark origin
|
||||
span.Meta[keyOrigin] = context.origin
|
||||
}
|
||||
}
|
||||
}
|
||||
span.context = newSpanContext(span, context)
|
||||
if context == nil || context.span == nil {
|
||||
// this is either a root span or it has a remote parent, we should add the PID.
|
||||
span.SetTag(ext.Pid, strconv.Itoa(os.Getpid()))
|
||||
span.SetTag(ext.Pid, t.pid)
|
||||
if t.hostname != "" {
|
||||
span.SetTag(keyHostname, t.hostname)
|
||||
}
|
||||
}
|
||||
// add tags from options
|
||||
for k, v := range opts.Tags {
|
||||
|
@ -361,7 +376,7 @@ const sampleRateMetricKey = "_sample_rate"
|
|||
|
||||
// Sample samples a span with the internal sampler.
|
||||
func (t *tracer) sample(span *span) {
|
||||
if span.context.hasPriority {
|
||||
if span.context.hasSamplingPriority() {
|
||||
// sampling decision was already made
|
||||
return
|
||||
}
|
||||
|
|
2
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/transport.go
generated
vendored
2
vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/transport.go
generated
vendored
|
@ -15,7 +15,7 @@ import (
|
|||
var (
|
||||
// TODO(gbbr): find a more effective way to keep this up to date,
|
||||
// e.g. via `go generate`
|
||||
tracerVersion = "v1.7.0"
|
||||
tracerVersion = "v1.13.1"
|
||||
|
||||
// We copy the transport to avoid using the default one, as it might be
|
||||
// augmented with tracing and we don't want these calls to be recorded.
|
||||
|
|
28
vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig/globalconfig.go
generated
vendored
Normal file
28
vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig/globalconfig.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Package globalconfig stores configuration which applies globally to both the tracer
|
||||
// and integrations.
|
||||
package globalconfig
|
||||
|
||||
import "sync"
|
||||
|
||||
var cfg = &config{}
|
||||
|
||||
type config struct {
|
||||
mu sync.RWMutex
|
||||
analyticsRate float64
|
||||
}
|
||||
|
||||
// AnalyticsRate returns the sampling rate at which events should be marked. It uses
|
||||
// synchronizing mechanisms, meaning that for optimal performance it's best to read it
|
||||
// once and store it.
|
||||
func AnalyticsRate() float64 {
|
||||
cfg.mu.RLock()
|
||||
defer cfg.mu.RUnlock()
|
||||
return cfg.analyticsRate
|
||||
}
|
||||
|
||||
// SetAnalyticsRate sets the given event sampling rate globally.
|
||||
func SetAnalyticsRate(rate float64) {
|
||||
cfg.mu.Lock()
|
||||
cfg.analyticsRate = rate
|
||||
cfg.mu.Unlock()
|
||||
}
|
Loading…
Reference in a new issue