OpenTelemetry Go SDKの初期化処理について、Splunk Distroを例に見ていきたいと思います!
ということで見ていきましょう!この記事は OpenTelemetry Advent Calendar 2024 および Splunk Advent Calendar 2024 の12/13の記事です。
OpenTelemetry SDKをセットアップすると、アプリケーションの挙動を表現する分散トレースやメトリクスなどをOpenTelemetry Collectorや分析バックエンドに送れるようになります。SDKのセットアップは言語によって多少の違いがあり、たとえばJava SDKでは起動オプションを追加するだけで、ライブラリ計装を含めたSDKが動作することになり、とても手軽に始められます。一方で、Go SDKは、Goの「書いた通りに動く」という特性上(そうですよね??)、SDKの初期化コードもまたある程度書く必要があります。
公式ドキュメントの Getting Started では、初期化コード例として、以下のような100行程度のコードを紹介しています。この中ではプロパゲーターの初期化や各データ型のプロバイダーを初期化していて、基本的なテレメトリーの送信が始められるようになっています。
しかし、実用的な初期化処理としては、もう少しおすすめしたいものはあったりします。OpenTelemetryでは、公式リポジトリでSDKやCollectorを公開している一方で、オブザーバビリティやIaaSなどの組織が公開しているディストリビーションがあり、その中では、各社の事情に合わせた推奨設定やエクスポートの設定が簡単に出来るようになっています(OpenTelemetry版を「Upstream Distro」と呼ぶこともあります)。オブザーバビリティベンダーであるSplunkもCollectorやいくつかの言語SDKの独自ディストリビューションを公開して、公式に技術サポート対象として扱っています。
ということで、OpenTelemetry Go SDKのSplunk Distro の初期化コードを読んで、何が起こっているかを見ていきましょう。
初期化コード
Go SDKのSplunk Distroでは、ドキュメントによると、以下のコードで計装が有効化することになっています。
package main
import (
"context"
"github.com/signalfx/splunk-otel-go/distro"
)
func main() {
sdk, err := distro.Run()
if err != nil {
panic(err)
}
// Flush all spans before the application exits
defer func() {
if err := sdk.Shutdown(context.Background()); err != nil {
panic(err)
}
}()
// ...
エージェントの起動は distro.Run()
に集約されており、Upstream Distroと比較するとシンプルです。では、 Run()
で何が起こっているか、otel.go の中身を見ていきましょう。
func Run(opts ...Option) (SDK, error) {
...(中略)
res, err := newResource(ctx)
...(中略)
shutdownFn, err := runTraces(c, res)
...(中略)
shutdownFn, err = runMetrics(c, res)
}
Run()
の主だった操作はこの3つです。それぞれ見ていきましょう。
newResource(ctx)
まず、newResouce()
を見てみます。これはおそらく、リソース属性をまとめている関数でしょう。
リソース属性 とは、そのテレメトリを生成するエンティティを表すものであり、たとえば、ホスト名やポッド名などの動作している環境に関する情報や、起動コマンドなどのプロセスに関する情報です。
func newResource(ctx context.Context) (*resource.Resource, error) {
// SDK's default resource.
res := resource.Default()
// Add process, Go runtime, and container information.
procRes, err := resource.New(ctx,
resource.WithProcess(),
resource.WithContainer(),
)
if err != nil {
return nil, err
}
res, err = resource.Merge(res, procRes)
if err != nil {
return nil, err
}
// Add Splunk-specific attributes.
splunkRes := resource.NewSchemaless(attribute.String(distroVerAttr, Version()))
res, err = resource.Merge(res, splunkRes)
if err != nil {
return nil, err
}
return res, nil
}
最初にデフォルトリソースを取得した後、プロセスの属性とコンテナの属性をマージし、さらにSplunk Distroを示す属性をマージして返しています。これにより、どんなプロセスで動いているか、どんなコンテナで動いているかが足されることになる・・・でしょう。resource
が持つ関数は https://pkg.go.dev/go.opentelemetry.io/otel/sdk/resource にまとまっています。
このリソースを使って、トレースとメトリクスのプロバイダーを初期化している・・・はずです。
runTraces(c, res)
次に、トレース関連の初期化を見てみましょう。やはりというか、先ほど作成した res
をパラメーターとして渡しています。
func runTraces(c *config, res *resource.Resource) (shutdownFunc, error) {
...(中略)
o := []trace.TracerProviderOption{
trace.WithResource(res),
trace.WithRawSpanLimits(*c.SpanLimits),
trace.WithSpanProcessor(trace.NewBatchSpanProcessor(exp)),
trace.WithIDGenerator(c.IDGenerator),
}
if _, ok := os.LookupEnv(tracesSamplerKey); !ok {
o = append(o, trace.WithSampler(trace.AlwaysSample()))
}
traceProvider := trace.NewTracerProvider(o...)
otel.SetTracerProvider(traceProvider)
return traceProvider.Shutdown, nil
}
プロバイダーのオプションとして、先ほど作成したリソース、スパンのリミット、バッチプロセッサーなどを設定しています。さらに追加として、サンプリングに関する情報を取得しています。それらのオプションをつかって traceProvider
を作成し、セットしているのがこのコードです。
runMetrics(c, res)
では次に、メトリクスの初期化を見てみましょう。
func runMetrics(c *config, res *resource.Resource) (shutdownFunc, error) {
...(中略)
o := []metric.Option{
metric.WithResource(res),
metric.WithReader(metric.NewPeriodicReader(exp)),
}
provider := metric.NewMeterProvider(o...)
otel.SetMeterProvider(provider)
// Add runtime metrics instrumentation.
if err := runtime.Start(); err != nil {
return nil, err
}
return provider.Shutdown, nil
}
トレースと同様に、こちらもリソースのオプションと、NewPeriodicReader
で作ったものを渡しています。これは、定義した間隔でメトリクスを収集してエクスポートするやつです。
まとめ
いかがでしたか?
内容はかなり省略しましたが、他にも独自に設定可能にしているものがあったりするので、Upstream版を使うとしても参考になるのではないでしょうか。OpenTelemetryのさまざまな機能は、オプションを与えなくても、デフォルトでそれなりに動作するようには作っていますが、なにか気になることがあれば調整できるようにしていきましょう。
この記事は OpenTelemetry Advent Calendar 2024 および Splunk Advent Calendar 2024 の12/13の記事でした。
Happy o11y!!
Discussion