Skip to content

budougumi0617/nrseg

Repository files navigation

nrseg

Go Reference MIT License test reviewdog

Background

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.

Description

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)
}

Features

  • 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()
  • 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

Synopsis

$ nrseg -i testuitl ./

Options

$ 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

Limitation

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),
	)

Installation

$ go install github.com/budougumi0617/nrseg/cmd/nrseg

Built binaries are available on github releases. https://github.com/budougumi0617/nrseg/releases

MacOS

If you want to install on MacOS, you can use Homebrew.

brew install budougumi0617/tap/nrseg

Contribution

  1. Fork (https://github.com/budougumi0617/nrseg/fork)
  2. Create a feature branch
  3. Commit your changes
  4. Rebase your local changes against the master branch
  5. Run test suite with the go test ./... command and confirm that it passes
  6. Run gofmt -s
  7. Create new Pull Request

License

MIT

Author

budougumi0617