1
0
Fork 0

Added integration support for DataDog APM Tracing

This commit is contained in:
Alex Antonov 2018-06-28 11:40:04 -05:00 committed by Traefiker Bot
parent ba8c9295ac
commit 3192307d59
61 changed files with 9999 additions and 5 deletions

View file

@ -0,0 +1,24 @@
package opentracer // import "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer"
import (
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
opentracing "github.com/opentracing/opentracing-go"
)
// ServiceName can be used with opentracing.StartSpan to set the
// service name of a span.
func ServiceName(name string) opentracing.StartSpanOption {
return opentracing.Tag{Key: ext.ServiceName, Value: name}
}
// ResourceName can be used with opentracing.StartSpan to set the
// resource name of a span.
func ResourceName(name string) opentracing.StartSpanOption {
return opentracing.Tag{Key: ext.ResourceName, 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}
}

View file

@ -0,0 +1,83 @@
package opentracer
import (
"fmt"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
opentracing "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/log"
)
var _ opentracing.Span = (*span)(nil)
// span implements opentracing.Span on top of ddtrace.Span.
type span struct {
ddtrace.Span
*opentracer
}
func (s *span) Context() opentracing.SpanContext { return s.Span.Context() }
func (s *span) Finish() { s.Span.Finish() }
func (s *span) Tracer() opentracing.Tracer { return s.opentracer }
func (s *span) LogEvent(event string) { /* deprecated */ }
func (s *span) LogEventWithPayload(event string, payload interface{}) { /* deprecated */ }
func (s *span) Log(data opentracing.LogData) { /* deprecated */ }
func (s *span) FinishWithOptions(opts opentracing.FinishOptions) {
for _, lr := range opts.LogRecords {
if len(lr.Fields) > 0 {
s.LogFields(lr.Fields...)
}
}
s.Span.Finish(tracer.FinishTime(opts.FinishTime))
}
func (s *span) LogFields(fields ...log.Field) {
// catch standard opentracing keys and adjust to internal ones as per spec:
// https://github.com/opentracing/specification/blob/master/semantic_conventions.md#log-fields-table
for _, f := range fields {
switch f.Key() {
case "event":
if v, ok := f.Value().(string); ok && v == "error" {
s.SetTag("error", true)
}
case "error", "error.object":
if err, ok := f.Value().(error); ok {
s.SetTag("error", err)
}
case "message":
s.SetTag(ext.ErrorMsg, fmt.Sprint(f.Value()))
case "stack":
s.SetTag(ext.ErrorStack, fmt.Sprint(f.Value()))
default:
// not implemented
}
}
}
func (s *span) LogKV(keyVals ...interface{}) {
fields, err := log.InterleavedKVToFields(keyVals...)
if err != nil {
// TODO(gbbr): create a log package
return
}
s.LogFields(fields...)
}
func (s *span) SetBaggageItem(key, val string) opentracing.Span {
s.Span.SetBaggageItem(key, val)
return s
}
func (s *span) SetOperationName(operationName string) opentracing.Span {
s.Span.SetOperationName(operationName)
return s
}
func (s *span) SetTag(key string, value interface{}) opentracing.Span {
s.Span.SetTag(key, value)
return s
}

View file

@ -0,0 +1,81 @@
// Package opentracer provides a wrapper on top of the Datadog tracer that can be used with Opentracing.
// It also provides a set of opentracing.StartSpanOption that are specific to Datadog's APM product.
// To use it, simply call "New".
//
// Note that there are currently some small incompatibilities between the Opentracing spec and the Datadog
// APM product, which we are in the process of addressing on the long term. When using Datadog, the
// Opentracing operation name is what is called resource in Datadog's terms and the Opentracing "component"
// tag is Datadog's operation name. Meaning that in order to define (in Opentracing terms) a span that
// has the operation name "/user/profile" and the component "http.request", one would do:
// opentracing.StartSpan("http.request", opentracer.ResourceName("/user/profile"))
//
// Some libraries and frameworks are supported out-of-the-box by using our integrations. You can see a list
// of supported integrations here: https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/contrib. They are fully
// compatible with the Opentracing implementation.
package opentracer
import (
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/internal"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
opentracing "github.com/opentracing/opentracing-go"
)
// New creates, instantiates and returns an Opentracing compatible version of the
// Datadog tracer using the provided set of options.
func New(opts ...tracer.StartOption) opentracing.Tracer {
tracer.Start(opts...)
return &opentracer{internal.GetGlobalTracer()}
}
var _ opentracing.Tracer = (*opentracer)(nil)
// opentracer implements opentracing.Tracer on top of ddtrace.Tracer.
type opentracer struct{ ddtrace.Tracer }
// StartSpan implements opentracing.Tracer.
func (t *opentracer) StartSpan(operationName string, options ...opentracing.StartSpanOption) opentracing.Span {
var sso opentracing.StartSpanOptions
for _, o := range options {
o.Apply(&sso)
}
opts := []ddtrace.StartSpanOption{tracer.StartTime(sso.StartTime)}
for _, ref := range sso.References {
if v, ok := ref.ReferencedContext.(ddtrace.SpanContext); ok && ref.Type == opentracing.ChildOfRef {
opts = append(opts, tracer.ChildOf(v))
break // can only have one parent
}
}
for k, v := range sso.Tags {
opts = append(opts, tracer.Tag(k, v))
}
return &span{
Span: t.Tracer.StartSpan(operationName, opts...),
opentracer: t,
}
}
// Inject implements opentracing.Tracer.
func (t *opentracer) Inject(ctx opentracing.SpanContext, format interface{}, carrier interface{}) error {
sctx, ok := ctx.(ddtrace.SpanContext)
if !ok {
return opentracing.ErrUnsupportedFormat
}
switch format {
case opentracing.TextMap, opentracing.HTTPHeaders:
return t.Tracer.Inject(sctx, carrier)
default:
return opentracing.ErrUnsupportedFormat
}
}
// Extract implements opentracing.Tracer.
func (t *opentracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
switch format {
case opentracing.TextMap, opentracing.HTTPHeaders:
return t.Tracer.Extract(carrier)
default:
return nil, opentracing.ErrUnsupportedFormat
}
}