OpenTelemetryでGoを使う時の無難な設定
OpenTelemetryの公式のSDKにはバッチやHTTPの接続など色々な設定項目があります。
この記事ではGo用のOpenTelemetryを実装するときに使う無難な設定を紹介します。
具体例
最初に、この記事で使用する具体的な設定を紹介します。
この関数を実行すると、OpenTelemetryのデータをサーバーに送信するようになります。
※文字列部分の値は環境毎に適切なものへ変更してください
import (
"context"
"go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/propagation"
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
)
func InitTracerProvider(ctx context.Context) (func(context.Context) error, error) {
client := otlptracehttp.NewClient(
otlptracehttp.WithEndpoint("xxx.example.com"),
otlptracehttp.WithHeaders(map[string]string{
"ヘッダー名": "ヘッダーの値",
}),
otlptracehttp.WithCompression(otlptracehttp.GzipCompression),
)
exporter, err := otlptrace.New(ctx, client)
if err != nil {
return nil, err
}
resources, err := resource.New(
ctx,
resource.WithProcessPID(),
resource.WithHost(),
resource.WithAttributes(
semconv.ServiceName("サービス名"),
semconv.ServiceVersion("バージョン名"),
semconv.DeploymentEnvironment("環境の名前"),
),
)
if err != nil {
return nil, err
}
tp := trace.NewTracerProvider(
trace.WithBatcher(exp),
trace.WithResource(resources),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
return tp.Shutdown, nil
}
設定しているのは大まかに次の4箇所です。
- Exporterの設定
- Resourceの設定
- TracerProviderの設定
- グローバル設定
設定内容の説明
具体例で使った設定について詳しくみていきましょう。
1. Exporterの設定
Exporterでは、OpenTelemetryで集めたデータを送信する方法を設定をします。
具体例では、エンドポイントとヘッダー、圧縮方法を指定しています。
client := otlptracehttp.NewClient(
otlptracehttp.WithEndpoint("xxx.example.com"),
otlptracehttp.WithHeaders(map[string]string{
"ヘッダー名": "ヘッダーの値",
}),
otlptracehttp.WithCompression(otlptracehttp.GzipCompression),
)
exporter, err := otlptrace.New(ctx, client)
if err != nil {
return nil, err
}
-
WithEndpoint
は接続先のホストとポートを指定します。デフォルトではlocalhost:4318
が指定されるので、localhostにCollectorを置いている場合、指定する必要はありません。 -
WithHeaders
はヘッダーを指定します。認証に必要なトークンを渡すときに使うことが多いです。 -
WithCompression
はデータの圧縮方法を設定します。gzipを使うようにすると送信量が減るので便利なことが多いです。
2. Resourceの設定
OpenTelemetryではResourceにサービス名やバージョンを付与することでデータの発生元の情報をトレースに追加できます。
Resourceに用意されている項目は色々ありますが、サービスを運用する上では最小限「サービス名」と「バージョン」、「環境の名前」は欲しいところです。
また、プロセスIDやホスト名を付与すると、特定のサーバーでだけ起きている問題が把握できたりと便利です。
各項目は具体例のように設定できます。
resources, err := resource.New(
ctx,
resource.WithProcessPID(),
resource.WithHost(),
resource.WithAttributes(
semconv.ServiceName("サービス名"),
semconv.ServiceVersion("バージョン名"),
semconv.DeploymentEnvironment("環境の名前"),
),
)
if err != nil {
return nil, err
}
-
WithProcessPID
は実行しているプロセスIDをResourceに付与します。 -
WithHost
は実行しているホスト名を付与します。 -
WithAttributes
は任意の情報を付与することができます。具体例では以下の情報を付与しています。-
ServiceName
はサービス名 -
ServiceVersion
はバージョンの名前 (v2.0.0 や、gitのハッシュ値 など) -
DeploymentEnvironment
は環境の名前 (productionやstagingなど)
-
また、AWSやGCPを使っている場合、インスタンスやクラスタの情報を一括で登録するモジュールもあります。
3. TracerProviderの設定
TracerProviderは計装に必要な情報を持っているオブジェクトで、Spanを作るために使われます。
バッチやサンプリングなどの設定ができますが、Batch
と Resource
は必ず設定するべき項目でしょう。
tp := trace.NewTracerProvider(
trace.WithBatcher(exporter),
trace.WithResource(resources),
)
-
WithBatcher
は作成したSpanをまとめて送信する設定です。WithSyncer
を使って逐一送信することもできますが、本番で使う場合にはWithBatcher
を使う選択肢しかないでしょう。 -
WithResource
で前に作成したresourceを使うようにします。
3. グローバル設定
最後に、グローバルな設定をします。
グローバル変数などは行儀が悪い方法と捉えられがちですが、OpenTelemetryはログと同じようにどこからでも使うものなので、グローバルに状態を共有したほうが便利です。
グローバルに設定するのは次の2つです。
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
-
otel.SetTracerProvider()
はグローバルなTracerProviderを設定する関数です。設定するとotel.GetTracerProvider()
などを使ってどこからでもアクセス出来るようになります。 -
otel.SetTextMapPropagator()
はpropagation
という、サービス間で情報を共有する方法を設定します。歴史的経緯からW3CやB3などのフォーマットがあり、通信相手が使うフォーマットも理解できるように設定する必要があります。propagation.TraceContext
はW3Cフォーマットを使うようにする設定です。
終わりに
以上、OpenTelemetryでGoを使う時の無難な設定を紹介しました。
Discussion