本文介紹通過OpenTelemetry Rust SDK將Rust應用的Trace資料接入到Log Service的操作步驟。
前提條件
- 已建立Trace執行個體。更多資訊,請參見建立Trace執行個體。
已安裝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.namespace}
服務歸屬的命名空間。
order
${host}
主機名稱。
localhost
${endpoint}
Log ServiceProject的接入地址,格式為${project}.${region-endpoint}:Port,其中:
${project}:Log ServiceProject名稱。
${region-endpoint}:Log ServiceProject所在地區的訪問網域名稱,支援公網和阿里雲內網(傳統網路、VPC)。更多資訊,請參見服務入口。
Port:網路連接埠,固定為10010。
test-project.cn-hangzhou.log.aliyuncs.com:10010
${project}
Log ServiceProject名稱。
test-project
${instance}
Trace服務執行個體ID。更多資訊,請參見建立Trace執行個體。
test-traces
${access-key-id}
阿里雲帳號AccessKey ID。
建議您使用只具備Log ServiceProject寫入許可權的RAM使用者的AccessKey(包括AccessKey ID和AccessKey Secret)。授予RAM使用者向指定Project寫入資料許可權的具體操作,請參見授權。如何擷取AccessKey的具體操作,請參見存取金鑰。
無
${access-key-secret}
阿里雲帳號AccessKey Secret。
建議您使用只具備Log ServiceProject寫入許可權的RAM使用者的AccessKey。
無