This document outlines migrating from an older version of the Datadog tracer (v1.x.x) to v2.
Datadog's v2 version of the Go tracer provides a significant refactor of our API, moving away from interfaces to provide flexibility in future works, isolating our integrations to prevent false-positives from security scanners, and enforcing proper library patterns to prevent misuse. This update is the result of continuous feedback from customers, the community, as well as our extensive internal usage, introducing better maintainability, simplified APIs, and unlocking performance benefits.
As is common and recommended in the Go community, the best way to approach migrating to this new API is by using the gradual code repair method. We have done the same internally and it has worked just great! For this exact reason we have provided a new, semver friendly import path to help with using both tracers in parallel, without conflict, for the duration of the migration. This new path is github.com/DataDog/dd-trace-go/v2.
We have also provided a new migration tool v2fix to help with the most essential changes made in v2, which you can read about here.
Our godoc page should be helpful during this process. We also have the official documentation, which contains a couple of examples.
Please follow this guide for migrating from v1 to v2 and creating new services using v2 directly. This document will further outline some before and after examples.
In v2, we have moved away from using gopkg.in in our import URLs in favor of github.com. To import the tracer library, you would have before:
import "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"Becomes:
import "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"It is important to run go mod tidy after changing any import.
It is also important to note that when using our contrib libraries, import URLs may be impacted differently. This will be covered in the section below Independent contrib packages.
For customers that have large codebases and that are unable to immediately upgrade services to the v2 tracer, we are offering a special transitional version of the v1 tracer, the v1 transitional version which is essentially a wrapper that preserves the API from v1 but uses v2 under the hood.
It’s safe for different services within your organization to use different tracer versions during the transition, some can use v1 while others adopt v2. Staggering the upgrade per service can minimize downtime and help ensure stability throughout your transition.
The transitional version is the only v1 version that allows both v1 and v2 to be imported in the same service, which enables you to migrate a service gradually. Using this v1 transitional version doesn’t require any code changes, but it also won’t support any new features introduced in v2.
When using the v1 transitional version, it is possible to gradually migrate a codebase to v2 by replacing imports and adapting the instrumentation to the new API file by file.
This version upgrade comes with a large overhaul of what was previously one single package that held all of our integrations. In v2, we introduce independent packages for each of our contribs, which will prevent false-positives in security scanners that were caused by indirect dependencies. As a result, importing contribs will also change. Before:
import "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http"Becomes:
import "github.com/DataDog/dd-trace-go/contrib/net/http/v2"If you are unsure of which import URL to use, please refer to our godoc, which will include example code for each contrib.
Span and SpanContext are now represented as a struct rather than an interface, which means that references to these types must use a pointer. They have also been moved to live within the tracer package, so they must be accessed using tracer.Span rather than ddtrace.Span. Before:
var sp ddtrace.Span = tracer.StartSpan("opname")
var ctx ddtrace.SpanContext = sp.Context()Becomes:
var sp *tracer.Span = tracer.StartSpan("opname")
var ctx *tracer.SpanContext = sp.Context()All the interfaces in ddtrace have been removed in favor of struct types, except for SpanContext. The new types have moved into ddtrace/tracer.
The following constants and functions have been removed:
ddtrace/ext.AppTypeWebddtrace/ext.CassandraQueryddtrace/ext.CassandraBatchddtrace/tracer.WithPrioritySampling; priority sampling is enabled by default.ddtrace/tracer.WithHTTPRoundTripper; useWithHTTPClientinstead.
Child spans can be started with StartChild rather than ChildOf. Before:
import "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
func main() {
tracer.Start()
defer tracer.Stop()
parent := tracer.StartSpan("op").Context()
child := tracer.StartSpan("op", tracer.ChildOf(parent))
}Becomes:
import "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
func main() {
tracer.Start()
defer tracer.Stop()
parent := tracer.StartSpan("op")
child := parent.StartChild("op")
}Rather than a uint64, trace IDs are now represented as a string. This change will allow support for 128-bit trace IDs. Old behavior may still be accessed by using the new TraceIDLower() method, though switching to 128-bit IDs is recommended. Before:
sp := tracer.StartSpan("opname")
fmt.Printf("traceID: %d\n", sp.Context().TraceID())Becomes:
sp := tracer.StartSpan("opname")
fmt.Printf("traceID: %s\n", sp.Context().TraceID()) //recommended for using 128-bit IDs
fmt.Printf("traceID: %d\n", sp.Context().TraceIDLower()) // for maintaining old behavior with 64-bit IDsSpan.AddSpanLink has been renamed to Span.AddLink.
The previously deprecated tracer.WithServiceName has been fully removed and replaced with the method tracer.WithService. If you would like to specify a service name upon starting the tracer, you would have before:
tracer.Start(tracer.WithServiceName("service"))After:
tracer.Start(tracer.WithService("service"))tracer.WithDogstatsdAddress has been renamed as tracer.WithDogstatsdAddr. If you would like to specify a different DogStatsD address upon starting the tracer, you would have before:
tracer.Start(tracer.WithDogstatsdAddress("10.1.0.12:4002"))After:
tracer.Start(tracer.WithDogstatsdAddr("10.1.0.12:4002"))tracer.WithAgentURL sets the address by URL where the agent is located, in addition to the existing WithAgentAddr option. It is useful for setups where the agent is listening to a Unix Domain Socket:
tracer.Start(tracer.WithAgentURL("unix:///var/run/datadog/apm.socket"))These functional options for ddtrace/tracer.Tracer.StartSpan and ddtrace/tracer.Span.Finish reduces the number of calls (in functional option form) in hot loops by giving the freedom to prepare a common span configuration in hot paths.
Before:
var err error
span := tracer.StartSpan(
"operation",
ChildOf(parent.Context()),
Measured(),
ResourceName("resource"),
ServiceName(service),
SpanType(ext.SpanTypeWeb),
Tag("key", "value"),
)
defer span.Finish(tracer.NoDebugStack())After:
cfg := tracer.NewStartSpanConfig(
tracer.Measured(),
tracer.ResourceName("resource"),
tracer.ServiceName(service),
tracer.SpanType(ext.SpanTypeWeb),
tracer.Tag("key", "value"),
)
finishCfg := tracer.NewFinishConfig(
NoDebugStack(),
)
// [...]
// Reuse the configuration in your hot path:
span := parent.StartChild("operation", tracer.WithStartSpanConfig(cfg))
defer span.Finish(tracer.WithFinishConfig(finishCfg))The following functions have been removed in favour of SpanSamplingRules and TraceSamplingRules:
NameRuleNameServiceRuleRateRuleServiceRuleSpanNameServiceMPSRuleSpanNameServiceRuleSpanTagsResourceRuleTagsResourceRule
Also, ext.SamplingPriority tag is deprecated. Use ext.ManualKeep and ext.ManualDrop instead.
A support package to create contribs without depending on internal packages is available in instrumentation. Please refer to instrumentation godoc page and existing contribs for more detail.
appsec package offers a new API for user monitoring; essentially deprecating login success & failure event functions, replacing them with versions that accept a login field, which is to be used by user monitoring rules (ATO monitoring & protection). Before:
appsec.TrackUserLoginSuccessEvent(...)
appsec.TrackUserLoginFailureEvent(...)Becomes:
appsec.TrackUserLoginSuccess(...)
appsec.TrackUserLoginFailure(...)The API Security sampler now takes decisions specific to a given endpoint (method + route + response status code) instead of using a simplistic sampling rate. This allows for improved coverage and accuracy of schema extraction as part of API Security.
opentracer is in "Maintenance" mode and limited support was offered in v1. We recommend to use OpenTelemetry or ddtrace/tracer directly. For additional details, please see our Support Policy.
SQLCommentInjectionMode values have been replaced by DBMPropagationMode values. Before:
SQLInjectionUndefined // SQLInjectionUndefined represents the comment injection mode is not set. This is the same as SQLInjectionDisabled.
SQLInjectionDisabled // SQLInjectionDisabled represents the comment injection mode where all injection is disabled.
SQLInjectionModeService // SQLInjectionModeService represents the comment injection mode where only service tags (name, env, version) are injected.
SQLInjectionModeFull // SQLInjectionModeFull represents the comment injection mode where both service tags and tracing tags. Tracing tags include span id, trace id and sampling priority.After:
DBMPropagationModeUndefined // DBMPropagationModeUndefined represents the dbm propagation mode not being set. This is the same as DBMPropagationModeDisabled.
DBMPropagationModeDisabled // DBMPropagationModeDisabled represents the dbm propagation mode where all propagation is disabled.
DBMPropagationModeService // DBMPropagationModeService represents the dbm propagation mode where only service tags (name, env, version) are propagated to dbm.
DBMPropagationModeFull // DBMPropagationModeFull represents the dbm propagation mode where both service tags and tracing tags are propagated. Tracing tags include span id, trace id and the sampled flag.- package level documentation of the
tracerpackage for a better overview. - official documentation