はじめに
こんにちは、rendaman0215です。
弊社では、ログ保管やAPM・メトリクスの収集先としてNewRelicを採用しています。
私は認証チームとして、Go言語のサービスにNewRelicを導入したため、その方法を紹介できればと思います。
本記事は、その取り組みの中で行なった、APMの取得に関する記事になります。
実施環境
言語:Go言語
フレームワーク:go-chi
実行環境:ECS on Fargate
導入
初期化
NewRelicのAPM計測用Goエージェントを初期化する。
まずは、アプリケーションに github.com/newrelic/go-agent/v3/newrelic
パッケージをインポート
import github.com/newrelic/go-agent/v3/newrelic
次にmain関数、またはinitブロックに以下を追加することで、Goエージェントを初期化
app, err := newrelic.NewApplication(
newrelic.ConfigAppName("アプリケーション名"),
newrelic.ConfigLicense("ライセンスキー"),
)
実装によっては、main関数で初期化しつつ他パッケージから呼び出したいため、以下のようにnewrelic
パッケージを作成しグローバル変数としてappを保持する。
var App *newrelic.Application
// NewTracer ...
func InitializeApp() {
app, err := newrelic.NewApplication(
newrelic.ConfigEnabled(true),
newrelic.ConfigDistributedTracerEnabled(true),
newrelic.ConfigAppName(config.Get().NewRelic.AppName),
newrelic.ConfigLicense(config.Get().NewRelic.LicenseKey),
newrelic.ConfigAppLogForwardingEnabled(true),
)
if err != nil {
clog.L.Fatal(err)
}
App = app
}
トランザクション
NewRelicのAPMでは、1リクエストに対して1トランザクション紐づく。
トランザクションを開始する方法は、以下の二通りある
- NewRelicが用意したラッパーを利用する
公式推奨の簡単な方法。HandleFuncをラップすることでWebトランザクションを計測しはじめられる。
http.HandleFunc(newrelic.WrapHandleFunc(app, "/users", usersHandler))
- 任意のタイミングでトランザクションを開始する
go-chiを使っている場合など上記の方法をとれない場合、手動でトランザクションを開始できる。
txn := nr.App.StartTransaction(r.URL.RequestURI())
defer txn.End() // リクエスト処理終了時、クローズが必要
txn.SetWebRequestHTTP(r) // Webトランザクションとする。(設定なしだと非Webトランザクション扱いされる)
ctx = newrelic.NewContext(ctx, txn) // リクエストのコンテキストに埋め込むことができ、これにより他パッケージからでも簡単に呼び出せる
セグメント
1トランザクションは、複数のセグメントから構成される。
各エンドポイントの処理の頭に以下のように記述し、セグメントの計測を行える。
// NewRelic データストアのセグメントを定義
txn := newrelic.FromContext(r.Context())
s1 := txn.StartSegment("MySegment")
defer s1.End()
もしくは、DB関連の処理をセグメントで囲むこともある。
// NewRelic データストアのセグメントを定義
seg := newrelic.DatastoreSegment{
Product: newrelic.DatastoreOracle,
Collection: "テーブル名",
Operation: "SELECT",
ParameterizedQuery: query,
}
seg.StartTime = txn.StartSegmentNow()
// この行でDML実行
seg.End()
まとめ
今回はGoのWebアプリケーションへNewRelicのAPMを導入する手順を紹介しました。
NewRelicは公式のドキュメントが充実しているのでシンプルに導入できますが、トランザクションやセグメントなどの前提知識がないと少し混乱していますかもしれませんね。
参考記事