BASE BANKでエンジニアをしている @budougumi0617 です。
先日行われたNew Relic User Group Vol.0でGoでNew Relic APMを活用するためのOSSを紹介するLT発表をさせていただきました。
New Relic User Group Vol.0
New Relic User Group(NRUG)はNew Relicを活用するユーザーの集いです。NRUGはヌルグと読むとのことです。
コロナ禍後初開催となるVol.0は2021年9月15日にオンライン形式で次のコンテンツが行われました。
- New Relic One 最新機能紹介
- Nerd Life Talk (LT)
- ネットワーキング
関連ハッシュタグは#NRUG
です。
BASE BANKを含めBASEグループでも2020年9月よりNew Relic Oneを利用した開発・運用体制を敷いており、今回LT発表の機会をいただくことができました。
発表資料
私の当日の発表資料は次のスライドになります。
私の発表では、BASE BANKのGoアプリケーションでNew Relic Oneを活用するために私が開発し、OSSとして公開している3つのツールについて紹介しました。
当日紹介したOSS
スライド中で紹介したOSSは次の3点です。
- https://github.com/budougumi0617/nrseg
- https://github.com/marketplace/actions/action-newrelic-segment-lint
- https://github.com/budougumi0617/nrzap
github.com/budougumi0617/nrseg
nrseg
コマンドはGoアプリケーションの関数・メソッドにNew Relic APMでSpanを生成するためのNew Relicライブラリの呼び出しを自動挿入するツールです。
GoアプリケーションへNew Relic APMを導入する際、Goでは実行時間を計測したい関数・メソッド全てで次のようなライブラリの呼び出しをする必要があります。
defer txn.StartSegment("mySegmentName").End()
nrseg
コマンドは指定ディレクトリ配下の全てのGoのコードに含まれる関数やメソッド1にスパンを生成するために必要なコードを自動挿入します。
import ( "context" "fmt" "net/http" + + "github.com/newrelic/go-agent/v3/newrelic" ) func (f *FooBar) SampleMethod(ctx context.Context) { + defer newrelic.FromContext(ctx).StartSegment("foo_bar_sample_method").End() fmt.Println("end function") } func SampleFunc(ctx context.Context) { + defer newrelic.FromContext(ctx).StartSegment("sample_func").End() 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 ignoreコメントをしておけば無視します。 func IgnoreHandler(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "Hello, %q", req.URL.Path) }
既存アプリケーションの関数やメソッド全てに上記のような呼び出しを手動で挿入するのは手間なのでこちらを利用しております。
内部実装的にはASTから関数名を取得したり関数の位置を読み取って先頭行にコードを挿入したりと楽しい静的解析になっております。
action-newrelic-segment-lint actions
action-newrelic-segment-lint
はNew RelicのSpan対応漏れがある関数・メソッドがPull Request(PR)に含まれていたときに警告コメントをするGitHub Actionsです。
既存コードに対してはnrseg
コマンドでNew Relicの対応ができます。
しかし、我々のGoアプリケーションは機能追加が活発に行われており、毎日関数やメソッドが追加されています。
新しく追加された関数やメソッドがNew Relicの対応をしていなかった時警告コメントをしてくれます。
github.com/budougumi0617/nrzap
nrzap
はNew RelicのTrace ID
やSpan ID
をuber-go/zap
のログに埋め込むためのヘルパーです。
New Relicには分散トレースとログを紐付けるLogs in contextという機能があります。
しかし、New Relicの公式Goライブラリはlogrus
というロガーパッケージしか現在はLogs in contextに対応していません。
弊社のGoアプリケーションで利用しているロガーパッケージはuber-go/zap
です。
Logs in contextに必要なNew RelicのTrace ID
やSpan ID
をuber-go/zap
のログに埋め込むためのヘルパーがnrzap
です。GetNrMetadataFields
関数を使うとcontext.Context
オブジェクトにNew Relic関連情報が含まれていればuber-go/zap
のログに適切なJSONキーでNew RelicのTrace ID
などの情報を含めることができます。
func ExampleHandler(w http.ResponseWriter, r *http.Request) {
logger, _ := zap.NewProduction()
defer logger.Sync()
// nrgorillaなどでcontextから*newrelic.Transactionが取れる前提
+ nrfs := nrzap.GetNrMetadataFields(r.Context())
logger.Info("failed to fetch URL", nrfs...)
}
会に参加して
会ではNew Relicのコンサルタントの皆様よりPixieなどのNew Relic Oneの最新機能を紹介していただきました。
また、他社の皆様には開発組織へのNew Relic導入活動のコツを教えていただいたり、本番ダッシュボードを実際に拝見させていただけました。
懇親会では紹介したOSSを実際に利用してくださっている方と話しかけていただき、とてもモチベーションが高まりました。
どのOSSもまだまだバギーなところがあるので時間を見つけて改善を重ねておこうと思います。
終わりに
NRUGの次回開催は12月を予定されているようです。今回とても有意義な時間だったのでぜひまた参加する予定です。
New Relicの最新機能、現場の生の声を聞ける貴重な会なので現在活用中の方、導入を検討されている方とも12月にお会いできればと思います。
-
正確には引数に
context.Context
オブジェクトまたは*http.Request
オブジェクトを持つ関数/メソッドです。↩