はじめに
OpenTelemetryではログ出力は既存のログライブラリに乗っかるという方針で、ログ出力ライブラリ用のブリッジがcontribリポジトリにあります。slogでもログを出力することができます。
OpenTelemetryでログを出力することの何が良いかというと、Traceと関連付けてログを出力できることです。一般的なバックエンド(Datadogなど)であれば特定のTraceを表示すると関連付けられたログだけを表示することができます。
GoのLogのステータスはBetaです。まあOpenTelemetryを使っているような人はBetaでも気にせず使う気がします。
設定
otel側の設定
// resourceはどこかで定義されているものとする
resource := getResource()
// 面倒なのでautoexportを使います
// go.opentelemetry.io/contrib/exporters/autoexport
logExporter, err := autoexport.NewLogExporter(ctx)
if err != nil {
return nil, err
}
// ログレベルをminsevで指定
// go.opentelemetry.io/contrib/processors/minsev
severity = minsev.SeverityDebug
// sdklog "go.opentelemetry.io/otel/sdk/log"
lp := sdklog.NewLoggerProvider(
sdklog.WithResource(resource),
sdklog.WithProcessor(
minsev.NewLogProcessor(
sdklog.NewBatchProcessor(logExporter),
severity,
),
),
)
// go.opentelemetry.io/otel/log/global
global.SetLoggerProvider(lp)
設定時にminsevを使わないとログ出力レベルが変更できません。slogのログ出力レベルは無視されます。
slog側の設定
logLevel := slog.LevelDebug
logger = slog.New(
// stdoutにも出てほしいのでslog-multiを使う
// slogmulti "github.com/samber/slog-multi
slogmulti.Fanout(
// go.opentelemetry.io/contrib/bridges/otelslog
otelslog.NewHandler("slog-test"),
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: logLevel
}),
),
)
slog.SetDefault(logger)
ログ出力
slog.InfoContext(ctx, "hoge")
注意点として、Contextに関連付けられたTraceが終了しているとログが出力されません。
これでTraceとLogが関連付けられた状態でDatadogなどで表示することができます。ローカルだとAspire Dashboardかotel-tuiが確認しやすいです。