The Go agent supports cross application tracing (CAT). Cross application tracing links transactions between APM-monitored app, 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'sWrapHandle
andWrapHandleFunc
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 you also callTransaction.SetWebRequest
andTransaction.SetWebResponse
. For example, a transaction started with the following code will have CAT enabled:txn := app.StartTransaction("transactionName") // req is a *http.Request, this marks the transaction as a web transaction txn.SetWebRequestHTTP(req) // writer is a http.ResponseWriter, use the returned writer in place of the original writer = txn.SetWebResponse(writer) writer.WriteHeader(500) defer txn.End()
However, a transaction started without the calls to
Transaction.SetWebRequest
andTransaction.SetWebResponse
will not have CAT enabled:// Cross application tracing not enabled txn := app.StartTransaction("transactionName") defer txn.End()
Additionally, if you're setting HTTP response codes, use the Go agent's
txn.WriteHeader
method rather than the standard library'shttp.ResponseWriter.WriteHeader
method.// old code // writer.WriteHeader(http.StatusInternalServerError) // replace with this txn := app.StartTransaction("transactionName") txn.SetWebRequest(req) writer = txn.SetWebResponse(writer) writer.WriteHeader(http.StatusInternalServerError)
- 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 tohttp://api.example.com/
that includes the outgoing CAT headers.func useNewRoundTripper(txn *newrelic.Transaction) (*http.Response, error) { client := &http.Client{} client.Transport = newrelic.NewRoundTripper(client.Transport) req, _ := http.NewRequest("GET", "http://api.example.com/", nil) req = newrelic.RequestWithTransactionContext(req, txn) return client.Do(req) }
If you have a more complex request that uses the Go standard library's
http.Request
, you'll need to use thenewrelic.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 usingnewrelic.NewRoundTripper
ornewrelic.ExternalSegment
.func noGoodForCat(txn *newrelic.Transaction, url string) (*http.Response, error) { // CAT headers not inserted defer newrelic.ExternalSegment{ StartTime: txn.StartSegmentNow(), URL: url, }.End() 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.