Cloud LoggingのログにOpenTelemetryのspan情報を埋め込む方法の確認
経緯
前回、TracerAgentによってCloud Loggingに送信していたログにSpan情報が付与されなくなった話をしました。せっかくなので、OpenTelemetryとCloud Loggingが連携する仕組みを詳しく確認してみましょう。
結論
OpenTelemetryでトレースを取得している場合、Cloud Loggingとの連携に特別な設定は必要ありません。
ログを書き込む際にSpanが開始されていれば、必要なトレース情報が自動的にメタデータに追加される仕組みになっています。
もうちょっと詳しく
Cloud Loggingの基本的な使い方
まず、Cloud Loggingでログを送信する基本的な方法を確認します。
import {Logging} from '@google-cloud/logging-min'
const logging = new Logging();
const log = logging.log('my-test');
const metadata = {
resource: {type: 'global'},
severity: 'INFO',
};
const entry = log.entry(metadata, 'message');
log.write(entry);
entry
を用意して write
するだけのシンプルな構造です。
トレース情報を手動で付与する方法
Cloud Loggingでトレース情報を認識させるには、以下のプロパティをメタデータに追加します:
-
trace
: トレースID -
spanId
: スパンID -
trace_sampled
: サンプリングフラグ
これらはLogEntry型のプロパティとして定義されています。
具体的には以下のように書くことで、トレースが付与されていると認識されます。
const entry = log.entry({
...metadata,
trace: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
spanId: 'aaaaaaaaaaaaaaaa',
trace_sampled: false,
}, 'message');
OpenTelemetryコンテキストからの自動取得
OpenTelemetryのSpanコンテキストからCloud Loggingのプロパティへの変換処理は、ライブラリ内部で実装されています。
この実装はgetContextFromOtelContext
関数で確認できます。
メタデータ付与のタイミング
Cloud Loggingライブラリは、Entry#toStructuredJSON
や Entry#toSJON
でログエントリをJSON形式に変換する際に、OpenTelemetryのコンテキストから自動的にトレース情報を取得して付与します。
Entry#extractTraceContext
Entry#toStructuredJSON
Entry#toJSON
これらのメソッドは以下のタイミングで呼び出されます:
logSync.write
ではtoStructuredJSON
が直接呼び出されます。
log.write
ではdecorateEntries
経由でよびだされます。
動作確認コード
以下は実際にOpenTelemetryとCloud Loggingを連携させて、自動的にトレース情報が付与されることを確認するコードです:
import { Logging } from '@google-cloud/logging-min'
import { NodeTracerProvider, SimpleSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node'
import { trace } from '@opentelemetry/api';
// OpenTelemetryの設定
const tracerProvider = new NodeTracerProvider({
spanProcessors: [
new SimpleSpanProcessor(new ConsoleSpanExporter()),
]
});
tracerProvider.register();
// Cloud Loggingの設定
const logging = new Logging({ projectId: 'my-dev'});
const log = logging.log('my-test'); // logging.logSyncとすると標準出力でも確認できます
const metadata = {
resource: {type: 'global'},
severity: 'INFO',
};
const tracer = trace.getTracer('sample-app');
// Spanを開始してログを出力
await tracer.startActiveSpan('first', async (span) => {
const entry = log.entry(metadata, {
message: 'entry',
});
// ログを出力(自動的にトレース情報が付与される)
log.write(entry);
// エントリの内容を確認(トレース情報が含まれているか確認)
console.log('Entry JSON:', entry.toJSON({}, 'my-dev'));
span.end();
});
await tracerProvider.shutdown();
このコードを実行すると、entry.toJSON()
の出力にトレース情報が自動的に含まれていることが確認できます。
まとめ
OpenTelemetryとCloud Loggingは特別な設定なしに連携することが分かりました。
前回の記事の環境ではOpenTelemetryの設定は行われているため、トレースが付与されていなかった原因は、middlewareが削除されたことでスパンを計測していない範囲になったという仮説が立てられそうです。
Discussion