### OpenTelemetry
#### 主要功能组件的现状如下
|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 后端搜索时更容易过滤。
- 没有内置的完整性检查来确保行李物品是您的,因此在使用行李时要小心。

#### 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<sdktrace::Tracer, TraceError> {
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<BasicController> {
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<dyn Error + Send + Sync + 'static>> {
// 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(())
}
```