https://docs.newrelic.com/docs/agents/go-agent/instrumentation/instrument-go-segments
NewRelic is excellent o11y service, but if we use Newrelic in Go app, we need to insert segment
into every function/method to measure the time taken by functions and code blocks.
For example, we can use with newrelic.FromContext
and defer
statement.
func SampleFunc(ctx context.Context) {
defer newrelic.FromContext(ctx).StartSegment("sample_func").End()
// do anything...
}
If there is your application in production already, you must add a segment into any function/method. It is a very time-consuming and tedious task.
nrseg
is cli tool for insert segment into all function/method in specified directory.
Before code is below,
package input
import (
"context"
"fmt"
"net/http"
)
type FooBar struct{}
func (f *FooBar) SampleMethod(ctx context.Context) {
fmt.Println("Hello, playground")
fmt.Println("end function")
}
func SampleFunc(ctx context.Context) {
fmt.Println("Hello, playground")
fmt.Println("end function")
}
func SampleHandler(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Hello, %q", req.URL.Path)
}
// nrseg:ignore you can be ignored if you want to not insert segment.
func IgnoreHandler(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Hello, %q", req.URL.Path)
}
After execute nrseg
, modified code is below.
package input
import (
"context"
"fmt"
"net/http"
"github.com/newrelic/go-agent/v3/newrelic"
)
type FooBar struct{}
func (f *FooBar) SampleMethod(ctx context.Context) {
defer newrelic.FromContext(ctx).StartSegment("foo_bar_sample_method").End()
fmt.Println("Hello, playground")
fmt.Println("end function")
}
func SampleFunc(ctx context.Context) {
defer newrelic.FromContext(ctx).StartSegment("sample_func").End()
fmt.Println("Hello, playground")
fmt.Println("end function")
}
func SampleHandler(w http.ResponseWriter, req *http.Request) {
defer newrelic.FromContext(req.Context()).StartSegment("sample_handler").End()
fmt.Fprintf(w, "Hello, %q", req.URL.Path)
}
// nrseg:ignore you can be ignored if you want to not insert segment.
func IgnoreHandler(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Hello, %q", req.URL.Path)
}
- Insert
Function segments
into the function with following arguments.- The function/method signature has
context.Context
.defer newrelic.FromContext(ctx).StartSegment("func_name").End()
- The function/method signature has
*http.Request
.defer newrelic.FromContext(req.Context()).StartSegment("func_name").End()
- The function/method signature has
- Support any variable name of
context.Context
/*http.Request
. - Support import alias of
"context"
/"net/http"
. - Use function/method name to segment name.
- This processing is recursively repeated.
- Able to ignore function/method by
nrseg:ignore
comment. - Ignore specified directories with cli option
-i
/-ignore
. - Remove all
Function segments
- Add:
dry-run
option - Validate: Show a function that doesn't call the segment.
- Support anonymous function
$ nrseg -i testuitl ./
$ nrseg -h
Insert function segments into any function/method for Newrelic APM.
Usage of nrseg:
-i string
ignore directory names. ex: foo,bar,baz
(testdata directory is always ignored.)
-ignore string
ignore directory names. ex: foo,bar,baz
(testdata directory is always ignored.)
-v print version information and quit.
-version
print version information and quit.
exit status 1
nrseg inserts only function segments
, so we need the initialize of Newrelic manually.
If we want to adopt Newrelic to our application, , we write initialize, and newrelic.WrapHandleFunc manually before execute this tool.
app, err := newrelic.NewApplication(
newrelic.ConfigAppName("my_application"),
newrelic.ConfigLicense(newrelicLicenseKey),
newrelic.ConfigDistributedTracerEnabled(true),
)
$ go install github.com/budougumi0617/nrseg/cmd/nrseg
Built binaries are available on github releases. https://github.com/budougumi0617/nrseg/releases
If you want to install on MacOS, you can use Homebrew.
brew install budougumi0617/tap/nrseg
- Fork (https://github.com/budougumi0617/nrseg/fork)
- Create a feature branch
- Commit your changes
- Rebase your local changes against the master branch
- Run test suite with the
go test ./...
command and confirm that it passes - Run
gofmt -s
- Create new Pull Request