### OpenTelemetry #### 主要功能组件的现状如下 |Traces|Metrics|Logs| |-|-|-| |Stable|Alpha|Not yet implemented| #### [Tracer](https://opentelemetry.io/docs/concepts/signals/traces/) - Spans - 一个Span代表一个工作或操作单元包含如下字段: - Name - Parent span ID (empty for root spans) - Start and End Timestamps - Span Context - Attributes - Span Events - Span Links - Span Status #### [Metrics](https://opentelemetry.io/docs/concepts/signals/metrics/) - 三种度量 - counter: 一个随时间相加的值——你可以把它想象成汽车上的里程表;它只会上升。 - measure: 随时间聚合的值。这更类似于汽车上的行程里程表,它代表某个定义范围内的值。 - observer: 在特定时间点捕获一组当前值,例如车辆中的燃油表 - 遥测后端支持的常见聚合(例如 sum、count、last value 和 histograms)。 #### [Baggage](https://opentelemetry.io/docs/concepts/signals/baggage/) - Baggage 应该用来做什么? - Baggage 应该用于您可以向第三方公开的非敏感数据。 - 常见用例包括只能在堆栈中进一步访问的信息。例如,这可能包括帐户标识、用户 ID、产品 ID 和源 IP 等内容。将这些向下传递到您的堆栈后,您可以将它们添加到下游服务中的 Spans 中,以便在您在 Observability 后端搜索时更容易过滤。 - 没有内置的完整性检查来确保行李物品是您的,因此在使用行李时要小心。 ![示例](https://opentelemetry.io/img/otel_baggage-2.png) #### demo ``` use opentelemetry::global::shutdown_tracer_provider; use opentelemetry::runtime; use opentelemetry::sdk::export::metrics::aggregation::cumulative_temporality_selector; use opentelemetry::sdk::metrics::controllers::BasicController; use opentelemetry::sdk::metrics::selectors; use opentelemetry::sdk::Resource; use opentelemetry::trace::TraceError; use opentelemetry::{global, sdk::trace as sdktrace}; use opentelemetry::{ metrics, trace::{TraceContextExt, Tracer}, Context, Key, KeyValue, }; use opentelemetry_otlp::{ExportConfig, WithExportConfig}; use std::error::Error; use std::time::Duration; fn init_tracer() -> Result { opentelemetry_otlp::new_pipeline() .tracing() .with_exporter( opentelemetry_otlp::new_exporter() .tonic() .with_endpoint("http://localhost:4317"), ) .with_trace_config( sdktrace::config().with_resource(Resource::new(vec![KeyValue::new( opentelemetry_semantic_conventions::resource::SERVICE_NAME, "trace-demo", )])), ) .install_batch(opentelemetry::runtime::Tokio) } fn init_metrics() -> metrics::Result { let export_config = ExportConfig { endpoint: "http://localhost:4317".to_string(), ..ExportConfig::default() }; opentelemetry_otlp::new_pipeline() .metrics( selectors::simple::inexpensive(), cumulative_temporality_selector(), runtime::Tokio, ) .with_exporter( opentelemetry_otlp::new_exporter() .tonic() .with_export_config(export_config), ) .build() } 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> { // By binding the result to an unused variable, the lifetime of the variable // matches the containing block, reporting traces and metrics during the whole // execution. let _ = init_tracer()?; let metrics_controller = init_metrics()?; let cx = Context::new(); let tracer = global::tracer("ex.com/basic"); let meter = global::meter("ex.com/basic"); let gauge = meter .f64_observable_gauge("ex.com.one") .with_description("A gauge set to 1.0") .init(); meter.register_callback(move |cx| gauge.observe(cx, 1.0, COMMON_ATTRIBUTES.as_ref()))?; let histogram = meter.f64_histogram("ex.com.two").init(); histogram.record(&cx, 5.5, COMMON_ATTRIBUTES.as_ref()); 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", vec![]); histogram.record(&cx, 1.3, &[]); }); }); // wait for 1 minutes so that we could see metrics being pushed via OTLP every 10 seconds. tokio::time::sleep(Duration::from_secs(60)).await; shutdown_tracer_provider(); metrics_controller.stop(&cx)?; Ok(()) } ```