Your data. Anywhere you go.

New Relic for iOS or Android


Download on the App Store    Android App on Google play


New Relic Insights App for iOS


Download on the App Store


Learn more

Close icon

Backwards compatibility break in Go agent 2.0 (released May 15)

golang
go-agent

#1

Update

As expected, we released version 2.0 today to https://github.com/newrelic/go-agent with the changes described below.

Please reply here or contact support if you have any issues.

Original post

As part of our commitment to continually refine and improve our Go agent, we’re going to be releasing a breaking change to the Go agent API in version 2.0, which we intend to release next Tuesday, May 15. The change is minor, and we expect most users to either not be impacted or only be impacted very minimally, but as this is the first time we’ve incremented the major version number to make a breaking change, we want to be very transparent about what we’re doing and how we’re doing it.

What’s changing

We’re changing the End() function on the Segment, DatastoreSegment, and ExternalSegment types to receive a pointer, rather than the value. As such, a simple go get -u github.com/newrelic/go-agent may result in build failures starting on May 15 for code written against the Go agent 1.x segment API.

You will need to change your code if you’ve implemented code that uses this pattern to both define the segment literal and defer a call to End() at the same time:

defer newrelic.Segment{
  StartTime: newrelic.StartSegmentNow(txn),
  Name: "foo",
}.End()

The Go compiler is unable to automatically transform a struct literal into a pointer for the call to End(). Instead, you will need to use a temporary variable like so:

s := newrelic.Segment{
  StartTime: newrelic.StartSegmentNow(txn),
  Name: "foo",
}
defer s.End()

Why we’re changing it

When we implemented Cross Application Tracing support late last year, we discovered an issue with a pattern we’d previously recommended for creating segments:

es := newrelic.ExternalSegment{
  StartTime: newrelic.StartSegmentNow(txn),
  Request: req,
}
defer es.End()
// ...
es.Response = resp

As we’d defined the End() function to receive the ExternalSegment structure by value, when the call to End() was deferred, the value of the structure at the point of the defer statement would be used. As a result, the subsequent assignment to the Response field would not be visible to End().

To fix this, we’re changing the End() function on the Segment, DatastoreSegment, and ExternalSegment types to receive a pointer, rather than the value.

How we’re rolling out version 2.0

The Go agent, like most Go packages, has its master branch track the most recent released version. As noted above, this means that a straight go get -u github.com/newrelic/go-agent within a project written to use the Go agent 1.x API may result in build failures from May 15.

We strongly recommend either explicitly vendoring dependencies, including the Go agent, or using a package management tool to manage and pin your dependencies.

If you wish to pin your application to a specific version of the Go agent, you can use the tags in our repository to do so. Our tag naming scheme is also generally compatible with package management tools in use, including dep and vgo.

How to migrate immediately

If you would like to get a head start on your migration, we’ve pushed the new API to the v2 branch in the Go agent repository. We expect this will be the code that makes up the 2.0.0 release on May 15.

If you find any issues, please either reply here or contact support.


#2