このトピックでは、OpenTelemetry SDK for Rustを使用してRustアプリケーションからSimple Log Serviceにトレースデータをインポートする方法について説明します。
前提条件
トレースインスタンスが作成されます。 詳細については、「トレースインスタンスの作成」をご参照ください。
Rust開発環境が設定されています。 Rustバージョンは1.46以降です。
手順
依存関係を追加します。
[package] name = "test" version = "0.1.0" authors = [""] edition = "2018" # See more keys and their definitions at The Manifest Format. [dependencies] futures = "0.3" lazy_static = "1.4" opentelemetry = { version = "0.16.0", features = ["tokio-support", "metrics", "serialize"] } opentelemetry-otlp = { version = "0.9.0", features = ["tonic", "metrics", "tls", "tls-roots"] } serde_json = "1.0" tokio = { version = "1.0", features = ["full"] } tonic="0.4.0" url = "2.2.0"
コードを実行します。
次のコードの変数を実際の値に置き換えます。 変数の詳細については、「変数」をご参照ください。
use opentelemetry::global::shutdown_tracer_provider; use opentelemetry::sdk::Resource; use opentelemetry::trace::TraceError; use opentelemetry::{ baggage::BaggageExt, trace::{TraceContextExt, Tracer}, Context, Key, KeyValue, }; use opentelemetry::{global, sdk::trace as sdktrace}; use opentelemetry_otlp::WithExportConfig; use std::error::Error; use std::time::Duration; use tonic::metadata::MetadataMap; use tonic::transport::ClientTlsConfig; use url::Url; static ENDPOINT: &str = "https://${endpoint}"; static PROJECT: &str = "${project}"; static INSTANCE_ID: &str = "${instance}"; static AK_ID: &str = "${access-key-id}"; static AK_SECRET: &str = "${access-key-secret}"; static SERVICE_VERSION: &str = "${version}"; static SERVICE_NAME: &str = "${service}"; static SERVICE_NAMESPACE: &str = "${service.namespace}"; static HOST_NAME: &str = "${host}"; static SLS_PROJECT_HEADER: &str = "x-sls-otel-project"; static SLS_INSTANCE_ID_HEADER: &str = "x-sls-otel-instance-id"; static SLS_AK_ID_HEADER: &str = "x-sls-otel-ak-id"; static SLS_AK_SECRET_HEADER: &str = "x-sls-otel-ak-secret"; static SLS_SERVICE_VERSION: &str = "service.version"; static SLS_SERVICE_NAME: &str = "service.name"; static SLS_SERVICE_NAMESPACE: &str = "service.namespace"; static SLS_HOST_NAME: &str = "host.name"; fn init_tracer() -> Result<sdktrace::Tracer, TraceError> { let mut metadata_map = MetadataMap::with_capacity(4); metadata_map.insert(SLS_PROJECT_HEADER, PROJECT.parse().unwrap()); metadata_map.insert(SLS_INSTANCE_ID_HEADER, INSTANCE_ID.parse().unwrap()); metadata_map.insert(SLS_AK_ID_HEADER, AK_ID.parse().unwrap()); metadata_map.insert(SLS_AK_SECRET_HEADER, AK_SECRET.parse().unwrap()); let endpoint = ENDPOINT; let endpoint = Url::parse(&endpoint).expect("endpoint is not a valid url"); let resource = vec![ KeyValue::new(SLS_SERVICE_VERSION, SERVICE_VERSION), KeyValue::new(SLS_HOST_NAME, HOST_NAME), KeyValue::new(SLS_SERVICE_NAMESPACE, SERVICE_NAMESPACE), KeyValue::new(SLS_SERVICE_NAME, SERVICE_NAME), ]; opentelemetry_otlp::new_pipeline() .tracing() .with_exporter( opentelemetry_otlp::new_exporter() .tonic() .with_endpoint(endpoint.as_str()) .with_metadata(dbg!(metadata_map)) .with_tls_config( ClientTlsConfig::new().domain_name( endpoint .host_str() .expect("the specified endpoint should have a valid host"), ), ), ) .with_trace_config(sdktrace::config().with_resource(Resource::new(resource))) .install_batch(opentelemetry::runtime::Tokio) } const FOO_KEY: Key = Key::from_static_str("ex.com/foo"); const BAR_KEY: Key = Key::from_static_str("ex.com/bar"); const LEMONS_KEY: Key = Key::from_static_str("lemons"); const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another"); lazy_static::lazy_static! { static ref COMMON_ATTRIBUTES: [KeyValue; 4] = [ LEMONS_KEY.i64(10), KeyValue::new("A", "1"), KeyValue::new("B", "2"), KeyValue::new("C", "3"), ]; } #[tokio::main] async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> { let _ = init_tracer()?; let tracer = global::tracer("ex.com/basic"); let _baggage = Context::current_with_baggage(vec![FOO_KEY.string("foo1"), BAR_KEY.string("bar1")]) .attach(); tracer.in_span("operation", cx { let span = cx.span(); span.add_event( "Nice operation!".to_string(), vec![Key::new("bogons").i64(100)], ); span.set_attribute(ANOTHER_KEY.string("yes")); tracer.in_span("Sub operation...", cx { let span = cx.span(); span.set_attribute(LEMONS_KEY.string("five")); span.add_event("Sub span event".to_string(), vec![]); }); }); tokio::time::sleep(Duration::from_secs(60)).await; shutdown_tracer_provider(); Ok(()) }
表 1. 変数
変数
説明
例
${service}
サービスの名前です。 ビジネスシナリオに基づいて値を指定します。
payment
${version}
サービスのバージョンです。 va.b.c形式でバージョンを指定することを推奨します。
v0.1.2
${service.nameスペース}
サービスが属する名前空間。
order
${host}
ホスト名。
localhost
${endpoint}
Simple Log Serviceプロジェクトのエンドポイント。 形式: ${project}.${region-endpoint}: ポート
${project}: Simple Log Serviceプロジェクトの名前。
${region-endpoint}: プロジェクトが存在するリージョンのSimple Log Serviceエンドポイント。 Simple Log Serviceには、内部エンドポイントまたはパブリックエンドポイントを使用してアクセスできます。 内部エンドポイントは、クラシックネットワークまたは仮想プライベートクラウド (VPC) 経由でアクセスできます。 インターネット経由でパブリックエンドポイントにアクセスできます。 詳細については、「エンドポイント」をご参照ください。
Port: ポート番号。 値は10010のように固定されます。
test-project.cn-hangzhou.log.aliyuncs.com:10010
${project}
Simple Log Serviceプロジェクトの名前。
test-project
${instance}
トレースインスタンスのID。 詳細については、「トレースインスタンスの作成」をご参照ください。
テストトレース
${access-key-id}
Alibaba CloudアカウントのAccessKey ID。
Simple Log Serviceプロジェクトに対する書き込み権限のみを持つRAMユーザーのAccessKeyペアを使用することを推奨します。 AccessKey ペアは、AccessKey ID と AccessKey Secret で構成されます。 指定したプロジェクトの書き込み権限をRAMユーザーに付与する方法の詳細については、「カスタムポリシーを使用してRAMユーザーに権限を付与する」をご参照ください。 AccessKeyペアを取得する方法の詳細については、「AccessKeyペア」をご参照ください。
なし
${access-key-secret}
Alibaba CloudアカウントのAccessKeyシークレット。
Simple Log Serviceプロジェクトに対する書き込み権限のみを持つRAMユーザーのAccessKeyペアを使用することを推奨します。
なし