OpenTelemetry Rust SDK¶
このドキュメントでは SDK インストルメンテーションを採用しています。アプリケーションコード内で SDK を初期化し、Span を作成して Exporter を構成し、DataKit 経由でトレースを Guance に送信します。これはゼロコードインジェクションではありません。依存関係をインストールしたり環境変数を設定したりしても、すべてのフレームワーク呼び出しが自動的に収集されるわけではありません。このドキュメントでは Trace のみを有効にし、Kubernetes には対応しません。
前提条件¶
- Rust の stable ツールチェーンと Cargo をインストールしてください。以下では OpenTelemetry
0.31.0を固定して使用します。現在の安定ツールチェーンを使用し、Cargo.lockをアプリケーションのバージョン管理に含めることを推奨します。 - サンプルは同期
main、ブロッキング HTTP クライアント、バックグラウンドのバッチエクスポートスレッドを使用しているため、Tokio は不要です。 - DataKit がインストール済みで、対象ワークスペースのインストールコマンドを使用してデータ送信先とトークンを設定していることを前提とします。アプリケーションは DataKit の HTTP ポート
9529にアクセスできる必要があります。
一、OpenTelemetry コレクターを有効にする¶
DataKit ホストで設定ディレクトリに移動します。設定ファイルが存在しない場合のみサンプルをコピーし、既存ファイルがある場合は直接調整してください:
opentelemetry.conf に以下の設定が含まれていることを確認してください。カスタムタグは customer_tags で保持されます:
[[inputs.opentelemetry]]
customer_tags = ["team", "app.operation"]
[inputs.opentelemetry.http]
http_status_ok = 200
trace_api = "/otel/v1/traces"
metric_api = "/otel/v1/metrics"
logs_api = "/otel/v1/logs"
同一ホストからの接続には 127.0.0.1:9529 を使用します。別ホストから接続する場合は、DataKit のメイン設定 datakit.conf の [http_api].listen でアプリケーションがアクセスできるリッスンアドレスを設定し、ネットワークアクセス範囲を制限してください。HTTP リッスンアドレスはコレクターの設定ファイルでは設定しません。
DataKit を再起動して確認します:
/v1/ping は HTTP サービスへの到達可能性のみを確認するもので、トレースが取り込まれたことを示すものではありません。詳細は OpenTelemetry コレクター を参照してください。DataKit がワークスペースの認証を担当するため、サンプルアプリケーションでワークスペーストークンを直接設定する必要はありません。
二、アプリケーションへの OpenTelemetry 導入¶
依存関係のインストール¶
空のディレクトリにサンプルプロジェクトを作成し、Cargo.toml を以下の内容に設定します。既存のプロジェクトの場合は依存関係をマージし、元の設定を上書きしないでください:
[package]
name = "otel-rust-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
opentelemetry = { version = "=0.31.0", default-features = false, features = ["trace"] }
opentelemetry_sdk = { version = "=0.31.0", default-features = false, features = ["trace"] }
opentelemetry-otlp = { version = "=0.31.0", default-features = false, features = ["trace", "http-proto", "reqwest-blocking-client"] }
SDK を初期化して Span を作成する¶
以下を src/main.rs として保存します。SDK は起動時に一度だけ初期化され、checkout の下に子 Span db.lookup を作成し、終了前にバッチエクスポートを待機します:
use opentelemetry::{
global,
trace::{TraceContextExt, Tracer},
KeyValue,
};
use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig};
use opentelemetry_sdk::{
propagation::TraceContextPropagator,
trace::{Sampler, SdkTracerProvider},
Resource,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let exporter = SpanExporter::builder()
.with_http()
.with_protocol(Protocol::HttpBinary)
.build()?;
let provider = SdkTracerProvider::builder()
.with_batch_exporter(exporter)
.with_resource(Resource::builder().build())
.with_sampler(Sampler::ParentBased(Box::new(
Sampler::TraceIdRatioBased(1.0),
)))
.build();
global::set_text_map_propagator(TraceContextPropagator::new());
global::set_tracer_provider(provider.clone());
let tracer = global::tracer("otel-rust-demo");
tracer.in_span("checkout", |_cx| {
tracer.in_span("db.lookup", |cx| {
cx.span().set_attribute(KeyValue::new("app.operation", "lookup"));
});
});
provider.shutdown()?;
Ok(())
}
ビルドと実行¶
アプリケーションを起動する同じターミナルで以下のパラメータを設定します。別ホストから接続する場合は 127.0.0.1 を実際の DataKit アドレスに置き換えてください:
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=prod,service.version=1.0.0,team=backend"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://127.0.0.1:9529/otel/v1/traces"
cargo run
初回実行時は依存関係のダウンロードとコンパイルが行われます。それ以降は cargo build --release を実行して本番用バイナリをビルドできます。長時間稼働するサービスでは Provider を保持し、リクエストの受信を停止して処理中の Span を終了させた後に shutdown() を呼び出してください。
三、データ送信パラメータ¶
| パラメータまたは設定 | 説明 |
|---|---|
OTEL_SERVICE_NAME |
service.name。サンプルでは order-service を使用していますが、安定したサービス名に設定してください。 |
OTEL_RESOURCE_ATTRIBUTES |
カンマ区切りのリソース属性。サンプルでは環境、バージョン、team を設定しています。カスタムフィールドは DataKit の customer_tags に追加してください。 |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
Trace 専用の完全なアドレス: http://127.0.0.1:9529/otel/v1/traces。汎用のベースアドレスよりも優先されます。 |
OTEL_EXPORTER_OTLP_ENDPOINT |
任意のベースアドレス: http://127.0.0.1:9529/otel。Trace 専用アドレスが設定されていない場合、Exporter が /v1/traces を追加します。 |
OTEL_EXPORTER_OTLP_HEADERS |
任意の OTLP リクエストヘッダー。形式は key=value,key2=value2 です。受信側またはプロキシが認証を要求する場合にのみ設定します。 |
この例では、コード内で .with_http() と Protocol::HttpBinary を使用して HTTP/Protobuf を選択しています。OTEL_EXPORTER_OTLP_PROTOCOL を変更しても、このサンプルが自動的に gRPC に切り替わることはありません。gRPC に変更するには、grpc-tonic を有効にし、.with_tonic() に切り替えて、適切な Tokio ランタイムを提供する必要があります。
サンプリングはコード内で ParentBased + ルートトレースの比率 1.0 として構成されており、親 Span のサンプリング決定に従います。本番環境では、サンプルの比率を 0.1 に変更すると、ルートトレースの約 10% がサンプリングされます。この例ではサンプラーを明示的に設定しているため、OTEL_TRACES_SAMPLER や OTEL_TRACES_SAMPLER_ARG には依存しません。
この例では Trace エクスポートパイプラインを明示的に作成しているため、OTEL_TRACES_EXPORTER がその選択や終了を行うことはありません。Metric や Log の Provider は作成されていないため、OTEL_METRICS_EXPORTER や OTEL_LOGS_EXPORTER を設定しても対応するシグナルは有効になりません。ログについては、DataKit の ログファイル収集 を別途使用できます。
コンテキスト伝播とアプリケーションへの組み込み¶
この例では W3C TraceContext プロパゲーターを登録していますが、ネットワークリクエストを自動的にインターセプトすることはありません。HTTP/RPC に組み込む場合は、サーバー側で Extractor を使用して上流のコンテキストを抽出し、新しい Span の親として設定し、クライアント側で Injector を使用して traceparent と tracestate を注入します。同期サンプルの in_span を .await をまたいで直接使用しないでください。非同期タスクでは FutureExt::with_context などを使用してコンテキストを伝播してください。tracing を使用するアプリケーションでは、互換性のあるバージョンの tracing-opentelemetry Layer も設定する必要があります。
検証とトラブルシューティング¶
- サンプルを実行した後、Guance のアプリケーションパフォーマンスモニタリング(APM)で
order-serviceを指定してトレースを検索し、checkoutとその子 Spandb.lookupが存在することを確認します。 - データがない場合は、コレクターが有効になっているか、アプリケーションの環境変数が有効か、HTTP パスに
/otel/v1/tracesが含まれているか、DataKit とアプリケーションのエクスポートエラーを確認してください。 - Span が終了し、Provider が終了前にフラッシュを完了していることを確認してください。強制終了したり、ルートトレースの比率を
0に設定すると、期待したデータが表示されない可能性があります。ネットワークが到達可能であることは、エクスポートが成功したことを意味しません。