Go で PostgreSQL に pgx と OpenTelemetry を使ってクエリをトレースする
はじめに
Go で PostgreSQL に pgx と OpenTelemetry を使ってクエリをトレースする方法を紹介します。
目標
最終的にこのようなトレースを取得できることを目標とします。
成果物
以下のリポジトリにサンプルコードを置いています。
利用ライブラリ
主に利用しているライブラリは以下の通りです。
コード
Tracer provider に渡すオプションの準備
まずは以下のように tracer provider に渡すオプションを準備します。
検証用なので sdktrace.AlwaysSample()
を利用して常時サンプリングするようにしています。
sdktrace.WithResource()
でリソースを指定しています。
import (
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)
opts := []sdktrace.TracerProviderOption{
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithResource(
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String("pgx-otel"),
semconv.ServiceVersion("v0.0.0"),
),
),
}
Exporter に関してはローカルでの検証用と Grafana Cloud を利用する場合の 2 つを用意しています。
ローカルでの検証用の場合は stdouttrace
を利用して標準出力に出力します。
import (
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint())
if err != nil {
panic(err)
}
opts = append(opts, sdktrace.WithBatcher(exporter))
Grafana Cloud を利用する場合は以下のように設定します。
Grafana Cloud へのトレース情報の送信は現時点では HTTP のみ対応しているため otlptracehttp
を利用します。
また、次の環境変数を Grafana Cloud の設定画面から取得して設定します。
OTEL_EXPORTER_OTLP_ENDPOINT
OTEL_EXPORTER_OTLP_PROTOCOL
OTEL_EXPORTER_OTLP_HEADERS
import (
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
otelClient := otlptracehttp.NewClient()
exporter, err := otlptrace.New(ctx, otelClient)
if err != nil {
panic(err)
}
opts = append(opts, sdktrace.WithBatcher(exporter))
Tracer provider の生成
準備したオプションを利用して Tracer provider を生成します。
ここでは batcher を利用しているため、最後に ForceFlush()
と Shutdown()
を呼び出して終了時にリソースを解放します。
import (
"go.opentelemetry.io/otel"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
tp := sdktrace.NewTracerProvider(opts...)
otel.SetTracerProvider(tp)
defer func() {
if err := tp.ForceFlush(ctx); err != nil {
panic(err)
}
if err := tp.Shutdown(ctx); err != nil {
panic(err)
}
}()
pgx の設定
ここではローカルの PostgreSQL に接続する場合の設定例を示します。
pgxpool でプールの設定を初期化した後、 otelpgx.NewTracer()
を利用して Tracer を設定します。
このコンフィグを用いて、 pgxpool を生成します。
import (
"github.com/exaring/otelpgx"
"github.com/jackc/pgx/v5/pgxpool"
)
url := "postgres://usr:pw@localhost:5432/db?sslmode=disable"
cfg, err := pgxpool.ParseConfig(url)
if err != nil {
return err
}
cfg.ConnConfig.Tracer = otelpgx.NewTracer(otelpgx.WithTracerProvider(tp))
conn, err := pgxpool.NewWithConfig(ctx, cfg)
if err != nil {
return err
}
defer conn.Close()
クエリの実行
あとは通常通りクエリを実行します。
row, err := conn.Query(ctx, "SELECT 1")
if err != nil {
return err
}
defer row.Close()
これでクエリをトレースできます。
設定したトレースバックエンドでトレース情報を確認してみてください。
Discussion