Cross application tracing with Go

The Go agent supports cross application tracing (CAT). Cross application tracing links transactions between APM apps, which is vital for applications implementing a service-oriented or microservices architecture.

Distributed tracing is now available. Distributed tracing is an improvement on cross application tracing and is recommended for large, distributed systems.

Enable cross application tracing with Go

You can enable or disable cross application tracing in the Go agent by using the CrossApplicationTracer.Enabled configuration flag.

Transaction and HTTP request guidelines with Go

Even with cross application tracing enabled, you'll need to make sure your application follows a few simple conventions when responding to HTTP(s) requests, making its own HTTP(s) requests, or creating its own transactions.

Creating transactions via http.ServeMux

If you're using Go's http.ServeMux and want CAT support, you'll need to use the agent's WrapHandle and WrapHandleFunc wrappers. These wrappers automatically start and end transactions with the request and response writer, which will automatically add the correct CAT headers. Your code should look similar to the following:

    http.HandleFunc("/users", usersHandler)
    http.HandleFunc(newrelic.WrapHandleFunc(app, "/users", usersHandler))

You can read more about these wrappers in Instrument Go transactions.

Creating web transactions manually

When creating your own transactions with app.StartTransaction, ensure that all calls to StartTransaction include the response writer and request. For example, a transaction started with the following code will have CAT enabled:

    txn := app.StartTransaction("transactionName", responseWriter, request)
    defer txn.End()

However, a transaction started without the second and third parameters will not have CAT enabled:

    txn := app.StartTransaction("backgroundTask", nil, nil)
    defer txn.End()

Additionally, if you're setting HTTP response codes, use the Go agent's txn.WriteHeader method rather than the standard library's http.ResponseWriter.WriteHeader method.

    //old code
    //replace with this
    txn := app.StartTransaction("transaction_name", w http.ResponseWriter, r *http.Request)
    /* ... */
Making HTTP requests

In order to have your outbound HTTP(s) requests eligible for CAT, you'll need to create an external segment.

The easiest way to create an external segment for your outbound HTTP(s) request is to use the newrelic.NewRoundTripper method. For example, this code will make a request to that includes the outgoing CAT headers.

    func useNewRoundTripper(txn newrelic.Transaction) (*http.Response, error) {
        client := &http.Client{}
        client.Transport = newrelic.NewRoundTripper(txn, nil)
        resp, err := client.Get("")
        return resp,err;

If you have a more complex request that uses the Go standard library's http.Request, you'll need to use the newrelic.StartExternalSegment method to ensure your outbound request is eligible for CAT.

func external(txn newrelic.Transaction, req *http.Request) (*http.Response, error) { s := newrelic.StartExternalSegment(txn, req) response, err := http.DefaultClient.Do(req) s.Response = response s.End() return response, err }

While it's also possible to create an ExternalSegment via a struct literal, this segment will not be eligible for CAT. Because of this, New Relic recommends using newrelic.NewRoundTripper or newrelic.ExternalSegment.

    func noGoodForCat(txn newrelic.Transaction, url string) (*http.Response, error) {
      defer newrelic.ExternalSegment{
        StartTime: newrelic.StartSegmentNow(txn),
        URL:   url,

      return http.Get(url)

Get distributed tracing

New Relic also offers distributed tracing. Distributed tracing is an improvement on cross application tracing and is recommended for large, distributed systems.

For more help

Recommendations for learning more: