Instrument Go segments

With New Relic Go monitoring, you can create segments to get more detail about the time taken by specific functions or code blocks in a transaction.

For general information about New Relic's Go monitoring, see New Relic for Go.

What is a segment?

Segments are optional instrumentations used to get more information about specific parts of a transaction. Segments measure the time taken by functions and code blocks, such as external calls, datastore calls, and background tasks.

Here's one example of how you might use segments:

You have a transaction associated with a checkout process, which processes both shipping information and credit card information. You could use segments to break that transaction up into two pieces: one segment for shipping and one segment for payment.

Create a segment for a block of code

Once you instrument a transaction, you are ready to instrument one or more segments in that transaction.

To instrument an arbitrary block of code as a segment, use the following pattern:

segment := newrelic.Segment{}
segment.Name = "mySegmentName"
segment.StartTime = newrelic.StartSegmentNow(txn)
// ... code you want to time here ...
segment.End()

txn is the variable name set for the transaction, as described in Instrument Go transactions.

StartSegment is a convenient helper. It creates a segment and starts it:

segment := newrelic.StartSegment(txn, "mySegmentName")
// ... code you want to time here ...
segment.End()

Create a segment for a function

Creating a segment for a function is essentially the same as creating a segment for an arbitrary block of code. The main difference is that, because a function has a discrete ending, you can use Go's defer statement.

To create a segment for a function, add the following code at the start of the function:

defer newrelic.StartSegment(txn, "mySegmentName").End()

txn is the variable name set for the transaction, as described in Instrument Go transactions.

Nest segments

Segments can be nested. The segment being ended must be the most recently started segment.

Here's an example of a segment starting and ending inside another segment:

s1 := newrelic.StartSegment(txn, "outerSegment")
s2 := newrelic.StartSegment(txn, "innerSegment")
// s2 must end before s1
s2.End()
s1.End()

A zero value segment may safely be ended. Therefore, the following code is safe even if the conditional fails:

var s newrelic.Segment
if txn, ok := w.(newrelic.Transaction); ok {
    s.StartTime = newrelic.StartSegmentNow(txn),
}
// ... code you wish to time here ...
s.End()

Create a datastore segment

You can instrument Go application datastore calls. Datastore segments appear in the Breakdown table and Databases tab of the Transactions page in the New Relic UI.

Just like basic segments, datastore segments begin when the StartTime field is populated and finish when the End method is called. To instrument a datastore segment, place the following at the beginning of the function you want to monitor:

s := newrelic.DatastoreSegment{
    Product: newrelic.DatastoreMySQL,
    Collection: "users",
    Operation: "INSERT",
    ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)",
    QueryParameters: map[string]interface{}{
        "name": "Dracula",
        "age": 439,
    },
    Host: "mysql-server-1",
    PortPathOrID: "3306",
    DatabaseName: "my_database",
}
s.StartTime = newrelic.StartSegmentNow(txn)
// ... make the datastore call
s.End()

For more on how to assign the Product, Collection, Operation, and other parameter values, see the New Relic datastore segment documentation on GitHub.

When instrumenting a datastore call that spans an entire function call, you can use the defer statement to simplify instrumentation:

defer newrelic.DatastoreSegment{
    Product: newrelic.DatastoreMySQL,
    Collection: "users",
    Operation: "INSERT",
    ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)",
    QueryParameters: map[string]interface{}{
        "name": "Dracula",
        "age": 439,
    },
    Host: "mysql-server-1",
    PortPathOrID: "3306",
    DatabaseName: "my_database",
}.End()

Create an external segment

You can instrument Go application calls to external services, such as web services, resources in the cloud, and any other network calls. External segments appear in the Breakdown table and the External services page of the New Relic UI.

There are two ways to instrument external segments:

Recommended: Use StartExternalSegment()

New Relic recommends using the StartExternalSegment helper, since New Relic will use it in the future to trace activity between your New Relic applications using headers.

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
}
Use ExternalSegment()

Use ExternalSegment and populate either the URL or Request field of the external segment parameter to indicate the endpoint:

func external(txn newrelic.Transaction, url string) (*http.Response, error) {
    defer newrelic.ExternalSegment{
        Start: newrelic.StartSegmentNow(txn),
        URL:   url,
    }.End()

    return http.Get(url)
}

New Relic reocmmends using the Request and Response fields because they provide more information about the external call.

NewRoundTripper is an optional helper built on top of PrepareRequest and EndRequest. It accesses the Go RoundTripper interface, which allows special control over HTTP request execution. It must be used in the same goroutine as the transaction.

Here is an example of NewRoundTripper instrumentation:

client := &http.Client{}
client.Transport = newrelic.NewRoundTripper(txn, nil)
resp, err := client.Get("http://example.com/")

For more help

Additional documentation resources include:

Join the discussion about Go monitoring in the New Relic Online Technical Community! The Technical Community is a public platform to discuss and troubleshoot your New Relic toolset.

If you need additional help, get support at support.newrelic.com.