【Go】これが俺なりのnrslog【New Relic APM】
TL;DR
-
nrslog
ではAPM Agent単体でslog.Attr
を転送できない - なので俺なりのnrslogを作りました
nrslogとは
New Relic公式が公開しているgo-agentのサブモジュールで
log/slog
でLogs in Context[1]を実現するためのパッケージです
NRHandler
をslog.Logger
のハンドラに設定することで簡単に計装することができます
詳しくはexample参照
slog.Attr
が転送されないのか
なぜその理由はNRHandlerの実装にあります
Go Agentを利用したログ転送はあくまでTransaction.RecordLog
を通じてNew Relicに送信されるEventの一種で、io.Writerの出力をそのままローテーションしているわけではない
というのが筆者の認識です
上記実装ではログレベル、タイムスタンプ、メッセージのみをTransaction.RecordLog
に渡しているため、後続の処理でシリアライズされるslog.Attr
もとい...args
は含まれていません
(2024/03/01 追記)
ただしこれは後述するキー項目を確実に含ませる意図があっての実装だと思われます
参考にnewrelic/go-agent/v3/integrations/logcontext-v2/nrzap
の実装ですが
nrslog同様に構造化データを含んでいません
上記についてはイシューが挙がっていますが、メンテナーからは前向きな回答がありました
slog.Attr
を転送するには
肝心のslog.Attr
はslog.commonHandler.handle
内で
- マーシャリング
-
slog.Record.Message
とマージ
の後に[]byte
としてio.Writer.Write
に渡されています
Write
メソッド内でTransaction.RecordLog
を呼び出すio.Writer
実装をslog.commonHandler
に設定するしかなさげです
その他 Logs in Contextを実現する上での留意点
ログデータ(ログイベント)にはキーとなるいくつかの項目を含む必要があります
今回そちらの説明は割愛しますが、参考にしたリンクを貼っておきます
作ったもの
実際に作ったライブラリです
現状用意しているハンドラはTransactionalHandler
の一種のみです
TransactionalHandler
を使用する上ではTransaction単位でslog.Logger
を生成して持ちまわす必要があります
なので、HTTPリクエストごとに
-
slog.Logger
の生成 -
context.Context
への格納
を行うカスタムミドルウェアを作って貰うのが一番使いやすいかなと思ってます
蛇足な気もしつつ、context.Context
からの出し入れ用の関数だけ用意しました
具体的な使い方はREADMEもしくは、pkg.go.devのExamplesセクションを参照してください
以下が実際にaltnrslogで転送されたログです
実行環境はECS on Fargate
それでは、よきオブザーバビリティを
Discussion