2018-06-28 16:40:04 +00:00
|
|
|
package tracer
|
|
|
|
|
|
|
|
import (
|
2019-01-16 16:08:06 +00:00
|
|
|
"net/http"
|
2018-06-28 16:40:04 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
|
|
|
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
|
2019-05-15 16:04:06 +00:00
|
|
|
"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
|
2019-07-18 19:36:05 +00:00
|
|
|
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
|
2018-06-28 16:40:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// config holds the tracer configuration.
|
|
|
|
type config struct {
|
|
|
|
// debug, when true, writes details to logs.
|
|
|
|
debug bool
|
|
|
|
|
|
|
|
// serviceName specifies the name of this application.
|
|
|
|
serviceName string
|
|
|
|
|
|
|
|
// sampler specifies the sampler that will be used for sampling traces.
|
|
|
|
sampler Sampler
|
|
|
|
|
2019-05-15 16:04:06 +00:00
|
|
|
// agentAddr specifies the hostname and port of the agent where the traces
|
2018-06-28 16:40:04 +00:00
|
|
|
// are sent to.
|
|
|
|
agentAddr string
|
|
|
|
|
|
|
|
// globalTags holds a set of tags that will be automatically applied to
|
|
|
|
// all spans.
|
|
|
|
globalTags map[string]interface{}
|
|
|
|
|
|
|
|
// transport specifies the Transport interface which will be used to send data to the agent.
|
|
|
|
transport transport
|
|
|
|
|
|
|
|
// propagator propagates span context cross-process
|
|
|
|
propagator Propagator
|
2019-01-16 16:08:06 +00:00
|
|
|
|
|
|
|
// httpRoundTripper defines the http.RoundTripper used by the agent transport.
|
|
|
|
httpRoundTripper http.RoundTripper
|
2019-05-15 16:04:06 +00:00
|
|
|
|
|
|
|
// 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
|
2019-07-18 19:36:05 +00:00
|
|
|
|
|
|
|
// logger specifies the logger to use when printing errors. If not specified, the "log" package
|
|
|
|
// will be used.
|
|
|
|
logger ddtrace.Logger
|
2018-06-28 16:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// StartOption represents a function that can be provided as a parameter to Start.
|
|
|
|
type StartOption func(*config)
|
|
|
|
|
|
|
|
// defaults sets the default values for a config.
|
|
|
|
func defaults(c *config) {
|
|
|
|
c.serviceName = filepath.Base(os.Args[0])
|
|
|
|
c.sampler = NewAllSampler()
|
|
|
|
c.agentAddr = defaultAddress
|
2019-05-15 16:04:06 +00:00
|
|
|
|
|
|
|
if os.Getenv("DD_TRACE_REPORT_HOSTNAME") == "true" {
|
|
|
|
var err error
|
|
|
|
c.hostname, err = os.Hostname()
|
|
|
|
if err != nil {
|
2019-07-18 19:36:05 +00:00
|
|
|
log.Warn("unable to look up hostname: %v", err)
|
2019-05-15 16:04:06 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-28 16:40:04 +00:00
|
|
|
}
|
|
|
|
|
2019-07-18 19:36:05 +00:00
|
|
|
// WithLogger sets logger as the tracer's error printer.
|
|
|
|
func WithLogger(logger ddtrace.Logger) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.logger = logger
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-16 16:08:06 +00:00
|
|
|
// WithPrioritySampling is deprecated, and priority sampling is enabled by default.
|
|
|
|
// When using distributed tracing, the priority sampling value is propagated in order to
|
|
|
|
// get all the parts of a distributed trace sampled.
|
|
|
|
// To learn more about priority sampling, please visit:
|
|
|
|
// https://docs.datadoghq.com/tracing/getting_further/trace_sampling_and_storage/#priority-sampling-for-distributed-tracing
|
|
|
|
func WithPrioritySampling() StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
// This is now enabled by default.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 16:40:04 +00:00
|
|
|
// WithDebugMode enables debug mode on the tracer, resulting in more verbose logging.
|
|
|
|
func WithDebugMode(enabled bool) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.debug = enabled
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithPropagator sets an alternative propagator to be used by the tracer.
|
|
|
|
func WithPropagator(p Propagator) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.propagator = p
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithServiceName sets the default service name to be used with the tracer.
|
|
|
|
func WithServiceName(name string) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.serviceName = name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithAgentAddr sets the address where the agent is located. The default is
|
|
|
|
// localhost:8126. It should contain both host and port.
|
|
|
|
func WithAgentAddr(addr string) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.agentAddr = addr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithGlobalTag sets a key/value pair which will be set as a tag on all spans
|
|
|
|
// created by tracer. This option may be used multiple times.
|
|
|
|
func WithGlobalTag(k string, v interface{}) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
if c.globalTags == nil {
|
|
|
|
c.globalTags = make(map[string]interface{})
|
|
|
|
}
|
|
|
|
c.globalTags[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithSampler sets the given sampler to be used with the tracer. By default
|
|
|
|
// an all-permissive sampler is used.
|
|
|
|
func WithSampler(s Sampler) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.sampler = s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-16 16:08:06 +00:00
|
|
|
// WithHTTPRoundTripper allows customizing the underlying HTTP transport for
|
|
|
|
// emitting spans. This is useful for advanced customization such as emitting
|
|
|
|
// spans to a unix domain socket. The default should be used in most cases.
|
|
|
|
func WithHTTPRoundTripper(r http.RoundTripper) StartOption {
|
|
|
|
return func(c *config) {
|
|
|
|
c.httpRoundTripper = r
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 16:04:06 +00:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 16:40:04 +00:00
|
|
|
// 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.
|
|
|
|
type StartSpanOption = ddtrace.StartSpanOption
|
|
|
|
|
|
|
|
// Tag sets the given key/value pair as a tag on the started Span.
|
|
|
|
func Tag(k string, v interface{}) StartSpanOption {
|
|
|
|
return func(cfg *ddtrace.StartSpanConfig) {
|
|
|
|
if cfg.Tags == nil {
|
|
|
|
cfg.Tags = map[string]interface{}{}
|
|
|
|
}
|
|
|
|
cfg.Tags[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ServiceName sets the given service name on the started span. For example "http.server".
|
|
|
|
func ServiceName(name string) StartSpanOption {
|
|
|
|
return Tag(ext.ServiceName, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResourceName sets the given resource name on the started span. A resource could
|
|
|
|
// be an SQL query, a URL, an RPC method or something else.
|
|
|
|
func ResourceName(name string) StartSpanOption {
|
|
|
|
return Tag(ext.ResourceName, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SpanType sets the given span type on the started span. Some examples in the case of
|
|
|
|
// the Datadog APM product could be "web", "db" or "cache".
|
|
|
|
func SpanType(name string) StartSpanOption {
|
|
|
|
return Tag(ext.SpanType, name)
|
|
|
|
}
|
|
|
|
|
2019-05-15 16:04:06 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 16:40:04 +00:00
|
|
|
// ChildOf tells StartSpan to use the given span context as a parent for the
|
|
|
|
// created span.
|
|
|
|
func ChildOf(ctx ddtrace.SpanContext) StartSpanOption {
|
|
|
|
return func(cfg *ddtrace.StartSpanConfig) {
|
|
|
|
cfg.Parent = ctx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// StartTime sets a custom time as the start time for the created span. By
|
|
|
|
// default a span is started using the creation time.
|
|
|
|
func StartTime(t time.Time) StartSpanOption {
|
|
|
|
return func(cfg *ddtrace.StartSpanConfig) {
|
|
|
|
cfg.StartTime = t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FinishOption is a configuration option for FinishSpan. 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.FinishOption.
|
|
|
|
type FinishOption = ddtrace.FinishOption
|
|
|
|
|
|
|
|
// FinishTime sets the given time as the finishing time for the span. By default,
|
|
|
|
// the current time is used.
|
|
|
|
func FinishTime(t time.Time) FinishOption {
|
|
|
|
return func(cfg *ddtrace.FinishConfig) {
|
|
|
|
cfg.FinishTime = t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-19 15:40:03 +00:00
|
|
|
// WithError marks the span as having had an error. It uses the information from
|
2019-05-15 16:04:06 +00:00
|
|
|
// err to set tags such as the error message, error type and stack trace. It has
|
|
|
|
// no effect if the error is nil.
|
2018-06-28 16:40:04 +00:00
|
|
|
func WithError(err error) FinishOption {
|
|
|
|
return func(cfg *ddtrace.FinishConfig) {
|
|
|
|
cfg.Error = err
|
|
|
|
}
|
|
|
|
}
|
2018-11-19 15:40:03 +00:00
|
|
|
|
|
|
|
// NoDebugStack prevents any error presented using the WithError finishing option
|
|
|
|
// from generating a stack trace. This is useful in situations where errors are frequent
|
|
|
|
// and performance is critical.
|
|
|
|
func NoDebugStack() FinishOption {
|
|
|
|
return func(cfg *ddtrace.FinishConfig) {
|
|
|
|
cfg.NoDebugStack = true
|
|
|
|
}
|
|
|
|
}
|
2019-05-15 16:04:06 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|