コンテンツにスキップ

OpenTelemetry Go(otelc)

OpenTelemetry Go Compile-Time Instrumentation は、otelc を使用して Go のコンパイル時に OpenTelemetry SDK の初期化とコンポーネントのインスツルメンテーションロジックを自動的に注入します。アプリケーションのビジネスコードを変更する必要はなく、従来の go buildgo tool otelc go build に置き換えるだけで、OTLP 経由でテレメトリデータを DataKit に送信し、Guance に転送できます。

この記事では、otelc v1.1.0、ホストインストールされた DataKit、および OTLP/gRPC を例に、Go HTTP サービスのトレースを接続する手順を説明します。

Go ソースコード -- go tool otelc go build --> インスツルメントされた Go バイナリ -- OTLP --> DataKit --> Guance

補足:otelc の「ゼロコード」とは、ビジネスコードで OpenTelemetry SDK を手動でインポートおよび初期化する必要がないことを意味し、再ビルドが不要というわけではありません。通常の Go バイナリに事後的にインスツルメンテーションを追加することはできません。必ず otelc で再コンパイルし、新しい成果物をデプロイしてください。

前提条件

  • Go 1.25 以降
  • プロジェクトが Go Module を使用しており、通常の go build で正常にコンパイルできること
  • DataKit がインストールされ、対象の Guance ワークスペースに接続されていること
  • Go アプリケーションから DataKit へのネットワーク到達性があること:OTLP/gRPC はデフォルトで 4317 ポート、OTLP/HTTP は DataKit HTTP ポート 9529 を使用
  • アプリケーションが使用するフレームワークまたはコンポーネントが otelc v1.1.0 でサポートされていること
  • アプリケーションが OpenTelemetry SDK を重複して初期化していないこと。SDK のライフサイクルを自前で管理する必要があるプロジェクトは、OpenTelemetry Go SDK の標準的な接続方式を利用してください。

この記事では Linux ホストと net/http サービスを例に説明し、Kubernetes デプロイメントは対象外です。

1. OpenTelemetry コレクターの有効化

DataKit の OpenTelemetry コレクターのディレクトリに移動します。設定ファイルがまだ存在しない場合は、サンプル設定をコピーします。

cd /usr/local/datakit/conf.d/opentelemetry
sudo cp opentelemetry.conf.sample opentelemetry.conf

opentelemetry.conf に最低限以下の設定が含まれていることを確認します。

[[inputs.opentelemetry]]
  # Guance のタグとして保持するカスタム属性のホワイトリスト。
  customer_tags = ["team", "project"]

  [inputs.opentelemetry.http]
    http_status_ok = 200
    trace_api = "/otel/v1/traces"
    metric_api = "/otel/v1/metrics"

  [inputs.opentelemetry.grpc]
    addr = "127.0.0.1:4317"

上記の設定は、以下の受信アドレスに対応します。

プロトコル データタイプ DataKit 受信アドレス
OTLP/gRPC トレース、メトリクス http://<DataKit-IP>:4317
OTLP/HTTP + Protobuf トレース http://<DataKit-IP>:9529/otel/v1/traces
OTLP/HTTP + Protobuf メトリクス http://<DataKit-IP>:9529/otel/v1/metrics

アプリケーションと DataKit が同一ホスト上にない場合は、gRPC の addr をアプリケーションからアクセス可能なリスニングアドレス(例:0.0.0.0:4317)に変更し、ファイアウォールやその他のネットワークアクセス制御を適宜設定してください。OTLP 受信ポートをインターネットに直接公開しないでください。

DataKit を再起動して設定を反映します。

sudo datakit service restart

DataKit および gRPC ポートを確認します。

curl http://127.0.0.1:9529/v1/ping
ss -lnt | grep 4317

2. アプリケーションの OpenTelemetry 接続

インスツルメンテーション前の確認

アプリケーションの Go Module ルートディレクトリに移動し、元のプロジェクトが正常にビルドできることを確認します。

go version
go build ./...

カレントディレクトリに go.mod がまだない場合は、最初に Module を初期化します。

go mod init example.com/my-service

プロジェクトが OpenTelemetry SDK または Contrib インスツルメンテーションライブラリに直接依存していないか確認します。

go list -m all | grep 'go.opentelemetry.io'

otelc は SDK の初期化ロジックを注入します。プロジェクト内に別の SDK 初期化や重複した HTTP インスツルメンテーションが存在する場合、スパンの重複、Provider の上書き、依存関係のバージョン競合が発生する可能性があります。この記事では、ビジネスコードでは SDK に直接接続しないことを推奨します。

otelc のインストール

Go の tool ディレクティブを使用して otelc v1.1.0 をインストールし、固定します。

go get -tool go.opentelemetry.io/otelc/tool/cmd/otelc@v1.1.0
go mod tidy

ツールのバージョンを確認します。

go tool otelc version

期待される出力:

otelc version v1.1.0

本番ビルドでは、go.modgo.sum でバージョンを固定し、@latest のような未固定のバージョンを使用しないでください。

otelc を使用したコンパイル

既存のビルドパラメータはそのまま維持し、go build の前に go tool otelc を追加するだけです。

go tool otelc go build -o my-service .

一般的なビルドパラメータを含む例:

mkdir -p ./bin
go tool otelc go build \
  -trimpath \
  -ldflags="-s -w" \
  -o ./bin/my-service \
  ./cmd/my-service

otelc go は現在、go buildgo installgo test をサポートしています。初回のインスツルメンテーションビルドでは OpenTelemetry の依存関係をダウンロードしてコンパイルするため、通常の go build よりも明らかに時間がかかります。ターミナルにコマンドプロンプトが再表示されるまでお待ちください。

ビルドが完了すると、.otelc-build/matched.json にマッチしたルールが記録されます。HTTP サーバーサイドのフックを確認します。

jq -e '[.. | objects | .name?] | index("server_hook") != null' \
  .otelc-build/matched.json >/dev/null

注意:リリースプロセスでは、go tool otelc go build で生成されたバイナリをデプロイする必要があります。その後に通常の go build で成果物を上書きすると、実行時に自動インスツルメンテーションが含まれなくなります。

OTLP/gRPC の設定と起動

以下の設定では、net/http トレースのみを有効にし、OTLP/gRPC 経由でローカルの DataKit に送信します。

export OTEL_SERVICE_NAME="my-service"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=prod,service.version=1.0.0,team=backend"

export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"

export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4317"
export OTEL_EXPORTER_OTLP_INSECURE="true"

export OTEL_GO_ENABLED_INSTRUMENTATIONS="nethttp"

./my-service

実行パラメータは、コンパイルホストだけでなく、インスツルメントされたバイナリが実際に実行される環境で設定する必要があります。アプリケーションの起動後、サポート対象のコンポーネントで処理されるエンドポイントにリクエストを送信し、検証可能なスパンを生成します。

本番環境では TLS エンドポイントを使用し、証明書や認証ヘッダーは Secret で管理してください。http://127.0.0.1:4317 は同一ホストからの接続にのみ適しています。

OTLP/HTTP の使用

OTLP/HTTP + Protobuf に切り替える場合は、プロトコルとエンドポイントを変更します。

export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
export OTEL_EXPORTER_OTLP_INSECURE="true"

Exporter はデータタイプに応じて /v1/traces または /v1/metrics を自動的に追加します。トレースエンドポイントのみを設定する場合は、直接以下も使用できます。

export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://127.0.0.1:9529/otel/v1/traces"

3. データ送信パラメータ

リソースと Exporter のパラメータ

環境変数 説明 推奨値または例
OTEL_SERVICE_NAME Guance で APM サービスを識別するための必須フィールド my-service、明示的に設定する必要があります
OTEL_RESOURCE_ATTRIBUTES リソース属性、複数の key=value はカンマ区切り deployment.environment.name=prod,service.version=1.0.0
OTEL_TRACES_EXPORTER トレース Exporter DataKit に送信する場合は otlp に設定
OTEL_METRICS_EXPORTER メトリクス Exporter 収集しない場合は none に設定
OTEL_LOGS_EXPORTER ログ Exporter OTLP でアプリケーションログを収集しない場合は none に設定
OTEL_EXPORTER_OTLP_PROTOCOL 共通 OTLP プロトコル grpc または http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT 全 OTLP シグナルで共通のエンドポイント gRPC:http://datakit-host:4317
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT トレース専用のエンドポイント、共通設定より優先 HTTP:http://datakit-host:9529/otel/v1/traces
OTEL_EXPORTER_OTLP_INSECURE TLS を使用しない接続にするかどうか ローカル平文接続の場合は true に設定
OTEL_EXPORTER_OTLP_HEADERS OTLP リクエストの認証ヘッダー Secret 経由で注入し、コードやイメージに書き込まない

インスツルメンテーション、サンプリング、デバッグのパラメータ

環境変数 説明 推奨値または例
OTEL_GO_ENABLED_INSTRUMENTATIONS 実行時インスツルメンテーションのホワイトリスト HTTP サービスでは nethttp
OTEL_GO_DISABLED_INSTRUMENTATIONS 実行時インスツルメンテーションのブラックリスト 必要に応じて無効化、例:redis
OTEL_TRACES_SAMPLER トレースサンプラー 接続確認では parentbased_always_on
OTEL_TRACES_SAMPLER_ARG 比率サンプリングのパラメータ 例:0.10parentbased_traceidratio と組み合わせる
OTEL_PROPAGATORS トレースコンテキストの伝搬形式 tracecontext,baggage
OTEL_LOG_LEVEL otelc 注入時の実行時ログレベル デフォルトは info、トラブルシューティング時は debug
OTEL_GO_SIMPLE_SPAN_PROCESSOR スパンを即座に1件ずつエクスポートするかどうか ローカルのトラブルシューティング時のみ true に設定
OTEL_SDK_DISABLED 注入された SDK を無効にするかどうか true にすると収集と送信が停止
OTELC_DEBUG 詳細なビルドログを記録するかどうか トラブルシューティング時は 1 に設定

OTEL_GO_ENABLED_INSTRUMENTATIONSOTEL_GO_DISABLED_INSTRUMENTATIONS は、すでにバイナリにコンパイルされたインスツルメンテーションのみを制御します。両方の変数が存在する場合、ホワイトリストが適用された後、ブラックリストの内容が除外されます。

本番環境では、トラフィックとデータ予算に応じてサンプリングレートを設定してください。アプリケーション側と DataKit 側の両方でサンプリングを有効にすると、最終的な保持率は相乗的に低下します。サンプリングの場所は統一して計画してください。

サポート対象コンポーネント

otelc v1.1.0 の組み込みルールは、以下のよく使われるコンポーネントをカバーします。

タイプ コンポーネント
HTTP net/http クライアントとサーバー、Gin
RPC gRPC クライアントとサーバー
データベース database/sql、Redis v9、MongoDB
メッセージキュー Kafka Go
クラウドとインフラ Kubernetes client-go、AWS SDK for Go v2、Linode Go v2
GenAI OpenAI Go v1/v2/v3、Anthropic Go SDK
ログ連携 標準ライブラリ loglog/slog、Logrus

実際のサポート範囲は、コンポーネントのバージョンやビルド方法によって影響を受ける可能性があります。アプリケーションの依存関係や otelc をアップグレードした後は、.otelc-build/matched.json を再確認し、トレースのリグレッションテストを実行してください。

フィールドマッピング

DataKit OpenTelemetry コレクターは、一般的な OpenTelemetry スパン属性を Guance のトレースフィールドに変換します。

OpenTelemetry 属性 DataKit フィールド
http.request.method http_method
http.response.status_code http_status_code
network.protocol.name net_protocol_name
network.protocol.version net_protocol_version
db.system.name db_system
db.operation.name db_operation
db.query.text db_statement
rpc.system.name rpc_system
rpc.method rpc_method

その他の属性を Guance のタグとして保持する必要がある場合は、DataKit の opentelemetry.confcustomer_tags を設定してください。ユーザーID、注文番号などの高カーディナリティ値をまとめてタグに昇格させないでください。また、パスワード、トークン、完全なデータベース接続文字列などの機密情報を送信しないでください。

接続の確認

  1. ツールのバージョンとインスツルメンテーションビルドが成功したことを確認します。
go tool otelc version
test -x ./my-service
  1. アプリケーションを起動し、ログに以下の内容が含まれ、OTLP エクスポートエラーがないことを確認します。
trace provider initialized with auto-export
OpenTelemetry initialized
HTTP server instrumentation initialized
  1. アプリケーションのエンドポイントにリクエストを送信し、トレースを生成します。
curl http://127.0.0.1:18080/ping
  1. ビルドルールに server_hook が含まれていることを確認します。
jq -e '[.. | objects | .name?] | index("server_hook") != null' \
  .otelc-build/matched.json
  1. OTLP/gRPC を使用している場合、DataKit ホストで受信カウントが増加していることを確認できます。
curl -fsS http://127.0.0.1:9529/metrics \
  | grep 'opentelemetry.proto.collector.trace.v1.TraceService/Export'
  1. Guance の「アプリケーションパフォーマンスモニタリング(APM)>トレース」に移動し、service:my-service で検索して、先ほどリクエストしたトレースが表示されることを確認します。

よくある質問

go.mod file not found

go get -tool は Go Module 内で実行する必要があります。プロジェクトのルートディレクトリに移動するか、最初に以下を実行してください。

go mod init example.com/my-service

コンパイルが WORK=/tmp/go-build... で停止する

初回のインスツルメンテーションビルドでは、多くの依存関係のコンパイルが行われます。go tool otelc go build プロセスがまだ実行中であれば、そのままお待ちください。ターミナルにコマンドプロンプトが再表示されてからビルド完了です。コンパイル中にアプリケーションバイナリを事前に実行しないでください。

リクエストポートへの接続が失敗する

まずコンパイルが終了し、インスツルメントされたバイナリを起動したことを確認してから、リスニングポートを確認してください。

ss -lntp | grep 18080

アプリケーションは正常だが、Guance にトレースが表示されない

以下の順に確認してください。

  • デプロイされたバイナリが go tool otelc go build で生成されたものであること
  • OTEL_SERVICE_NAME、Exporter、プロトコル、エンドポイントが実際の実行プロセスで設定されていること
  • .otelc-build/matched.json に期待されるルールが含まれていること
  • OTEL_GO_ENABLED_INSTRUMENTATIONS に対象のコンポーネントが含まれていること
  • DataKit の OpenTelemetry コレクターが有効になり、再起動されて反映されていること
  • アプリケーションから DataKit へのネットワーク、および 4317 または 9529 ポートへの到達性があること

ビルドの問題については、一時的に詳細ログを有効にできます。

OTELC_DEBUG=1 go tool otelc go build -o my-service .

詳細ログは .otelc-build/debug.log に出力されます。トラブルシューティングが終了したらデバッグを無効にし、ログの増加を防いでください。

初回の Ctrl+C でアプリケーションが終了しない

otelc v1.1.0 が注入するランタイムは SIGINTSIGTERM をリッスンします。最初のシグナルはテレメトリデータのフラッシュに使用されますが、アプリケーション自身の終了処理はアプリケーション側で行う必要があります。グレースフルシャットダウンを実装していない単純なアプリケーションでは、再度シグナルを送信する必要がある場合があります。本番サービスでは、Go の標準ライブラリを使用して HTTP サーバーのグレースフルシャットダウンを実装し、テレメトリのフラッシュ時間を確保してください。

参考

フィードバック

このページは役に立ちましたか?