🚴

OpenTelemetryでGoを使う時の無難な設定

2023/09/05に公開

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箇所です。

  1. Exporterの設定
  2. Resourceの設定
  3. TracerProviderの設定
  4. グローバル設定

設定内容の説明

具体例で使った設定について詳しくみていきましょう。

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を使っている場合、インスタンスやクラスタの情報を一括で登録するモジュールもあります。
https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/detectors

3. TracerProviderの設定

TracerProviderは計装に必要な情報を持っているオブジェクトで、Spanを作るために使われます。
バッチやサンプリングなどの設定ができますが、BatchResource は必ず設定するべき項目でしょう。

  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を使う時の無難な設定を紹介しました。

Vaxila

Discussion