---
title: Cross application tracing with Go
source: https://docs.newrelic.com/docs/apm/agents/go-agent/features/cross-application-tracing-go
---

The Go agent supports [cross application tracing (CAT)](https://docs.newrelic.com/docs/apm/transactions/cross-application-traces/introduction-cross-application-traces). Cross application tracing links transactions between APM-monitored app, which is vital for applications implementing a service-oriented or microservices architecture.

> #### ⚠️ IMPORTANT
>
> Cross application tracing has been deprecated in favor of [Distributed tracing](https://docs.newrelic.com/docs/agents/go-agent/features/distributed-tracing-go) and will be removed in a future agent version.

## Enable cross application tracing with Go [#enable]

You can enable or disable cross application tracing in the Go agent by using the [`CrossApplicationTracer.Enabled`](https://docs.newrelic.com/docs/agents/go-agent/instrumentation/go-agent-configuration#cross-tracer-enabled) configuration flag.

## Transaction and HTTP request guidelines with Go [#guidelines]

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](https://docs.newrelic.com/docs/agents/go-agent/get-started/instrument-go-transactions).

**Creating transactions via http.ServeMux**

If you're using Go's [`http.ServeMux`](https://golang.org/pkg/net/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](https://docs.newrelic.com/docs/apm/transactions/cross-application-traces/introduction-cross-application-traces#security). Your code should look similar to the following:

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

You can read more about these wrappers in [Instrument Go transactions](/docs/agents/go-agent/get-started/instrument-go-transactions#http-handler-txns).

````

**Creating web transactions manually**

When creating your own transactions with `app.StartTransaction`, ensure that you also call `Transaction.SetWebRequest` and `Transaction.SetWebResponse`. For example, a transaction started with the following code will have CAT enabled:

````go
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` and `Transaction.SetWebResponse` <DNT>**will not**</DNT> have CAT enabled:

```go
// 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's [`http.ResponseWriter.WriteHeader`](https://golang.org/pkg/net/http/#ResponseWriter) method.

```go
// 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](https://docs.newrelic.com/docs/agents/go-agent/get-started/instrument-go-segments#go-external-segments).

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 `http://api.example.com/` that includes the outgoing CAT headers.

````go
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 the `newrelic.StartExternalSegment` method to ensure your outbound request is eligible for CAT.

```go
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 <DNT>**will not**</DNT> be eligible for CAT. Because of this, New Relic recommends using [`newrelic.NewRoundTripper` or `newrelic.ExternalSegment`](/docs/agents/go-agent/get-started/instrument-go-segments#go-external-segments).

```go
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 [#distributed-tracing]

New Relic also offers [distributed tracing](https://docs.newrelic.com/docs/apm/distributed-tracing/getting-started/introduction-distributed-tracing). Distributed tracing is an improvement on cross application tracing and is recommended for large, distributed systems.
