OpenTelemetry Go(otelc)¶
OpenTelemetry Go Compile-Time Instrumentation は、otelc を使用して Go のコンパイル時に OpenTelemetry SDK の初期化とコンポーネントのインスツルメンテーションロジックを自動的に注入します。アプリケーションのビジネスコードを変更する必要はなく、従来の go build を go tool otelc go build に置き換えるだけで、OTLP 経由でテレメトリデータを DataKit に送信し、Guance に転送できます。
この記事では、otelc v1.1.0、ホストインストールされた DataKit、および OTLP/gRPC を例に、Go HTTP サービスのトレースを接続する手順を説明します。
補足:
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 コレクターのディレクトリに移動します。設定ファイルがまだ存在しない場合は、サンプル設定をコピーします。
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 を再起動して設定を反映します。
DataKit および gRPC ポートを確認します。
2. アプリケーションの OpenTelemetry 接続¶
インスツルメンテーション前の確認¶
アプリケーションの Go Module ルートディレクトリに移動し、元のプロジェクトが正常にビルドできることを確認します。
カレントディレクトリに go.mod がまだない場合は、最初に Module を初期化します。
プロジェクトが OpenTelemetry SDK または Contrib インスツルメンテーションライブラリに直接依存していないか確認します。
otelc は SDK の初期化ロジックを注入します。プロジェクト内に別の SDK 初期化や重複した HTTP インスツルメンテーションが存在する場合、スパンの重複、Provider の上書き、依存関係のバージョン競合が発生する可能性があります。この記事では、ビジネスコードでは SDK に直接接続しないことを推奨します。
otelc のインストール¶
Go の tool ディレクティブを使用して otelc v1.1.0 をインストールし、固定します。
ツールのバージョンを確認します。
期待される出力:
本番ビルドでは、go.mod と go.sum でバージョンを固定し、@latest のような未固定のバージョンを使用しないでください。
otelc を使用したコンパイル¶
既存のビルドパラメータはそのまま維持し、go build の前に go tool otelc を追加するだけです。
一般的なビルドパラメータを含む例:
mkdir -p ./bin
go tool otelc go build \
-trimpath \
-ldflags="-s -w" \
-o ./bin/my-service \
./cmd/my-service
otelc go は現在、go build、go install、go 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 を自動的に追加します。トレースエンドポイントのみを設定する場合は、直接以下も使用できます。
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.10、parentbased_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_INSTRUMENTATIONS と OTEL_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 |
| ログ連携 | 標準ライブラリ log、log/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.conf で customer_tags を設定してください。ユーザーID、注文番号などの高カーディナリティ値をまとめてタグに昇格させないでください。また、パスワード、トークン、完全なデータベース接続文字列などの機密情報を送信しないでください。
接続の確認¶
- ツールのバージョンとインスツルメンテーションビルドが成功したことを確認します。
- アプリケーションを起動し、ログに以下の内容が含まれ、OTLP エクスポートエラーがないことを確認します。
trace provider initialized with auto-export
OpenTelemetry initialized
HTTP server instrumentation initialized
- アプリケーションのエンドポイントにリクエストを送信し、トレースを生成します。
- ビルドルールに
server_hookが含まれていることを確認します。
- OTLP/gRPC を使用している場合、DataKit ホストで受信カウントが増加していることを確認できます。
curl -fsS http://127.0.0.1:9529/metrics \
| grep 'opentelemetry.proto.collector.trace.v1.TraceService/Export'
- Guance の「アプリケーションパフォーマンスモニタリング(APM)>トレース」に移動し、
service:my-serviceで検索して、先ほどリクエストしたトレースが表示されることを確認します。
よくある質問¶
go.mod file not found¶
go get -tool は Go Module 内で実行する必要があります。プロジェクトのルートディレクトリに移動するか、最初に以下を実行してください。
コンパイルが WORK=/tmp/go-build... で停止する¶
初回のインスツルメンテーションビルドでは、多くの依存関係のコンパイルが行われます。go tool otelc go build プロセスがまだ実行中であれば、そのままお待ちください。ターミナルにコマンドプロンプトが再表示されてからビルド完了です。コンパイル中にアプリケーションバイナリを事前に実行しないでください。
リクエストポートへの接続が失敗する¶
まずコンパイルが終了し、インスツルメントされたバイナリを起動したことを確認してから、リスニングポートを確認してください。
アプリケーションは正常だが、Guance にトレースが表示されない¶
以下の順に確認してください。
- デプロイされたバイナリが
go tool otelc go buildで生成されたものであること OTEL_SERVICE_NAME、Exporter、プロトコル、エンドポイントが実際の実行プロセスで設定されていること.otelc-build/matched.jsonに期待されるルールが含まれていることOTEL_GO_ENABLED_INSTRUMENTATIONSに対象のコンポーネントが含まれていること- DataKit の OpenTelemetry コレクターが有効になり、再起動されて反映されていること
- アプリケーションから DataKit へのネットワーク、および
4317または9529ポートへの到達性があること
ビルドの問題については、一時的に詳細ログを有効にできます。
詳細ログは .otelc-build/debug.log に出力されます。トラブルシューティングが終了したらデバッグを無効にし、ログの増加を防いでください。
初回の Ctrl+C でアプリケーションが終了しない¶
otelc v1.1.0 が注入するランタイムは SIGINT と SIGTERM をリッスンします。最初のシグナルはテレメトリデータのフラッシュに使用されますが、アプリケーション自身の終了処理はアプリケーション側で行う必要があります。グレースフルシャットダウンを実装していない単純なアプリケーションでは、再度シグナルを送信する必要がある場合があります。本番サービスでは、Go の標準ライブラリを使用して HTTP サーバーのグレースフルシャットダウンを実装し、テレメトリのフラッシュ時間を確保してください。