---
title: Go agent code-level metrics instrumentation
source: https://docs.newrelic.com/docs/apm/agents/go-agent/instrumentation/go-agent-code-level-metrics-instrument
---

After you've turned on code-level metrics using the steps in [Go agent code-level metrics configuration](https://docs.newrelic.com/docs/apm/agents/go-agent/configuration/go-agent-code-level-metrics-config), you can fine-tune how your metrics are collected by using additional instrumentation.

## Instrumenting transactions [#instrument-transactions-clm]

With code-level metrics enabled, the Go agent will add source code context information to any transaction started by a call to the `StartTransaction` method of the application. Without changing any of your existing instrumentation code, this means that the source code location will be added based on the function which called `StartTransaction`. This is true even if `StartTransaction` is called for you by an instrumentation package.

However, if you wish to exert some manual control over how code-level metrics are collected for a particular transaction, you may add a number of `newrelic.TraceOption` functions as described below:

### Suppressing code-level metrics for a single transaction [#instrument-transactions-suppress-clm]

If you don't want code-level metrics for a particular transaction (say, to avoid the overhead of collecting the information when you know you won't need that data), add a `WithoutCodeLevelMetrics` function to the end of the `StartTransaction` call:

```go
txn := app.StartTransaction("nothing-here-to-see", newrelic.WithoutCodeLevelMetrics())
defer txn.End()
```

### Adjusting the file path prefix [#instrument-transactions-path-prefix-clm]

By default, the Go agent will report full (absolute) file pathnames for the source files referenced by code-level metrics. The [configuration guide](https://docs.newrelic.com/docs/apm/agents/go-agent/configuration/go-agent-code-level-metrics-config) has information about how you can truncate file pathnames globally to start at your choice of directory name via the `ConfigCodeLevelMetricsPathPrefixes` setting, but you may need to specify a different file pathname prefix for individual transactions. If so, just add a `WithPathPrefixes` option to the transaction:

```go
txn := app.StartTransaction("mytransaction", newrelic.WithPathPrefixes("otherproject/lib/src"))
defer txn.End()
```

This means that, for this transaction only, a source file pathname of, for example, `"/usr/src/otherproject/lib/src/main.go"` is shortened to `"otherproject/lib/src/main.go"`.

If you have multiple path prefixes you wish to use, simply pass them as additional parameters to `WithPathPrefixes`:

```go
txn := app.StartTransaction("mytransaction", newrelic.WithPathPrefixes("otherproject/lib/src", "myproject/src"))
defer txn.End()
```

### Adjusting the function recognition heuristic's ignore prefix [#instrument-transactions-ignore-prefix-clm]

By default, the Go agent contains logic to skip over functions in the call stack which are internal to the agent itself, in order to arrive at the one you are instrumenting. The [configuration guide](https://docs.newrelic.com/docs/apm/agents/go-agent/configuration/go-agent-code-level-metrics-config)
has information about how you can globally change this heuristic via the `ConfigCodeLevelMetricsIgnoredPrefixes` setting, but you may wish to provide a custom namespace ignore prefix for a single transaction. You can do so by adding a `WithIgnoredPrefixes` option to the transaction:

```go
txn := app.StartTransaction("mytransaction", newrelic.WithIgnoredPrefixes("github.com/ignore/this/"))
defer txn.End()
```

You can specify multiple string arguments to `WithIgnoredPrefixes` if there are multiple packages whose functions should be ignored:

```go
txn := app.StartTransaction("mytransaction", newrelic.WithIgnoredPrefixes("github.com/ignore/this/", "github.com/ignore/that/"))
defer txn.End()
```

With this change, any functions from a package whose name begins with `github.com/ignore/this/` (or `github.com/ignore/that/` in the second example) will be skipped over to find the function being instrumented.

### Explicitly mark the code location [#instrument-transactions-this-location-clm]

To make it easier to identify the point of interest to be reported, add `WithThisCodeLocation` to the end of the `StartTransaction` call (for example, if the transaction is actually started inside another framework). This will force the code-level metrics to report the location in the source code where `WithThisCodeLocation` was invoked.

```go
txn := app.StartTransaction("mytransaction", newrelic.WithThisCodeLocation())
defer txn.End()
```

### Explicitly mark any code location [#instrument-transactions-any-location-clm]

You can also fully control the location in your source code to be associated with a transaction. In essence you can mark any location by calling `ThisCodeLocation` to get a "marker" for that location. Then, use that saved marker with the `WithCodeLocation` option to a `StartTransaction` call:

```go
here := newrelic.ThisCodeLocation()
.
.
.
txn := app.StartTransaction("mytransaction", newrelic.WithCodeLocation(here))
defer txn.End()
```

If needed, you can tell `ThisCodeLocation` to skip a number of calling functions so that the reported location is farther up the call stack. For example, to skip 1 caller, so that `here` refers to the caller of the function that calls `ThisCodeLocation`, change the above example to:

```go
here := newrelic.ThisCodeLocation(1)
.
.
.
txn := app.StartTransaction("mytransaction", newrelic.WithCodeLocation(here))
defer txn.End()
```

### Explicitly mark the code location based on a function value [#instrument-transactions-by-function-clm]

If the code you wish to instrument is available to you as a `func` type value, such as the name of a function or a function literal value, you can specify that as the location for code-level metrics reporting by adding a `WithFunctionLocation` option to `StartTransaction`, passing the `func` value as a parameter:

```go
func myfunction() { ... }
.
.
.
txn := app.StartTransaction("myfunction", newrelic.WithFunctionLocation(myfunction))
```

or

```go
someFunction := func() {...}
.
.
.
txn := app.StartTransaction("myfunction", newrelic.WithFunctionLocation(someFunction))
```

You may also obtain a `CodeLocation` value from a `func` value for later use with the `WithCodeLocation` option. Compare this to [the usage shown above](#instrument-transactions-any-location-clm) to save a code location with `ThisCodeLocation` for later reference with `WithCodeLocation`. This time we do the same thing but with a `func` value instead:

```go
func myFunc() {...}
.
.
.
locationOfMyFunc, err := newrelic.FunctionLocation(myFunc)
if err != nil {
    // handle the case that the location could not be determined
    // from the value passed to FunctionLocation.
}
.
.
.
txn := app.StartTransaction("mytransaction", newrelic.WithCodeLocation(locationOfMyFunc))
```

Note that `FunctionLocation` returns an error if the value passed to it was not a valid function, or the source code location could not be obtained from it. By contrast, the `WithFunctionLocation` option sets the code-level metrics based on the value passed if possible, but silently does nothing if an error occurs.

## Adding custom options to wrapped handlers [#instrument-transactions-custom-wrappers-clm]

The same options described above which may be added to the end of `StartTransaction` may also be added to `WrapHandle` and `WrapHandleFunc` to adjust the code-level metrics collection associated with transactions started by them, if desired (although in most cases the `WrapHandle` and `WrapHandleFunc` functions will correctly identify the location of the code being instrumented). For example:

```go
http.HandleFunc(newrelic.WrapHandleFunc(app, "/endpoint", endpointFunction, newrelic.WithThisCodeLocation()))
```

## Changing trace options after a transaction has started [#instrument-transactions-set-options-clm]

Sometimes you don't have the luxury of knowing the code location until after the transaction has already been started (perhaps by a framework or integration function on your behalf). You may change the transaction options on an existing transaction by calling its `SetOption` method. The parameters are a set of `TraceOption` functions just as described above. For example:

```go
txn := newrelic.FromContext(r.context)
txn.SetOption(newrelic.WithThisCodeLocation())
```

## Improving performance with cached code-level metrics functions [#instrument-transactions-cached-clm]

Often the most convenient way to instrument a transaction with code-level metrics is to call `newrelic.WithThisCodeLocation()` (or similar function as described above) inside the instrumented function. However, if that function is going to be called many times throughout the runtime of your application, it would be preferable to avoid the overhead of repeatedly computing the source code location. This is especially true if the transaction code will be run concurrently in many goroutines.

To mitigate this, the Go agent provides _caching_ versions of several of these functions. They operate the same as their uncached counterparts do, except that they only do the work of figuring out the source code location the _first_ time they are called, and then simply reuse that value every subsequent time.

In order to make use of this feature, you need to create a cache storage variable by calling `NewCachedCodeLocation()` and put it where it will persist between executions of the instrumented transaction.
This variable will hold the cached value for that code location. Then simply use the methods `FunctionLocation(functionValue)` or
`ThisCodeLocation()` just as you would use the stand-alone functions of the same names, but in this case they are methods of your `CachedCodeLocation` variable.
These methods are thread-safe, so you may use them in concurrent goroutines without adding any additional concurrency controls to them.

For example, in this code we set up a cache variable which is used in the closure assigned to the `myFunc` variable.

```go
cache := newrelic.NewCachedCodeLocation()

myFunc := func() {
	txn := app.StartTransaction("mytransaction", cache.WithThisCodeLocation())
	defer txn.End()
	// go on to perform the transaction
}
```

(This example assumes that `app` is the agent's `Application` value created when the agent was started, and is visible to this code snippet.)

Now we can call the `myFunc` function many times. Each (possibly concurrent) invocation of `myFunc` has a reference to the `cache` variable. The first invocation
to execute `cache.WithThisCodeLocation()` will compute the source code location at that point, and store it in the `cache` variable. Subsequent executions of `myFunc` will reuse the value previously stored in `cache`.

Note that you must use a different cache variable for each code location you want to use, since the point is to only evaluate that location once and then
use the cached value from there. The cache variable is not intended to be copied or used other than as documented here and in the module package documentation.

Please refer to the full Go [module package documentation](https://pkg.go.dev/github.com/newrelic/go-agent/v3/newrelic) for more details about all of the cached code-level metrics functions and methods you may employ.
