### 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<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(())
}
```