Rust 中的分佈式跟蹤:OpenTelemetry

在這篇文章中,我們先簡單介紹一下 OpenTelemetry,然後,再來編寫一個在 Rust 中使用 OpenTelemetry 的示例。

OpenTelemetry,也被簡稱爲 OTel,是一個開源可觀察性框架,用於檢測、生成、收集和導出測量數據,如跟蹤、度量、日誌。OTEL 爲你提供了一套獨立的 api、sdk、集成和收集器服務。如圖:

下面,讓我們來看一下 OpenTelemetry 的關鍵概念。

OpenTelemetry 介紹

核心術語

跟蹤 (Trace):

指標 (Metric):

日誌 (Logs):

上下文信息 (Baggage):

OpenTelemetry 的構成

語義約定:爲常見的遙測類型 (如應用程序名稱、HTTP 調用等) 定義標準命名約定。

OpenTelemetry 數據處理

在 Rust 中使用 OpenTelemetry

在開始檢測應用程序之前,我們需要向一個可觀察性的後端來發送遙測數據,最容易上手的就是 Jaeger。

設置 Jaeger

啓動 Jaeger 的最簡單方法是使用 Docker 鏡像:

docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 14250:14250 \
  -p 14268:14268 \
  -p 14269:14269 \
  -p 9411:9411 \
  jaegertracing/all-in-one:1.47

在這裏 16686 是前端顯示端口;4318 是接收遙測數據的 HTTP 端口,4317 是接收遙測數據的 GRPC 端口,它們都遵循 OTLP 協議。

一旦它啓動並運行,可以在瀏覽器中輸入:http://localhost:16686/ 來觀察數據。

創建項目

在這個例子中,定義一個簡單的函數生成一個隨機數並打印出來,然後在執行時返回一個結果。

使用如下命令創建一個 Rust 項目:

cargo new otlp-example

然後在 Cargo.toml 文件中,加入以下依賴項:

[dependencies]
opentelemetry = { version = "0.19.0"features = ["rt-tokio"] }
opentelemetry-otlp = { version="0.12.0",  features = ["tonic""metrics"] }
opentelemetry-semantic-conventions = { version="0.11.0" }
tokio = { version = "1.0"features = ["full"] }
rand = "0.8.5"

在 src/main.rs 中,寫入如下代碼:

use opentelemetry::trace::TraceError;
use rand::Rng;

fn gen_number() -> u32 {
    let mut rng = rand::thread_rng();
    rng.gen()
}

#[tokio::main]
async fn main() -> Result<(), TraceError> {
    let num = gen_number();
    println!("{}", num);
    Ok(())
}

創建 init_tracer 函數來初始化 OpenTelemetry 跟蹤器:

fn init_tracer() -> Result<trace::Tracer, TraceError> {
    // 初始化OTLP管道
    opentelemetry_otlp::new_pipeline()
        .tracing() // 創建OTLP跟蹤管道
        .with_exporter(
            opentelemetry_otlp::new_exporter()
                .tonic() // 創建GRPC層
                .with_endpoint("http://localhost:4317"), // GRPC OTLP Jaeger端口
        )
        // 跟蹤配置
        .with_trace_config(
            trace::config().with_resource(Resource::new(vec![KeyValue::new(
                opentelemetry_semantic_conventions::resource::SERVICE_NAME,
                "rust-otlp-basic",
            )])),
        )
        .install_batch(runtime::Tokio) // 配置一個span導出器
}

在 main 函數中使用跟蹤器:

// 創建一個常量 Key
const RANDOM: Key = Key::from_static_str("random.value");

#[tokio::main]
async fn main() -> Result<(), TraceError> {
    // 設置全局傳播器
    global::set_text_map_propagator(TraceContextPropagator::new());

    // 初始化跟蹤程序
    let tracer = init_tracer().unwrap();

   // 啓動一個新的活躍的跨度
   tracer.in_span("generating number"|cx| {
    let span = cx.span();
    let num = gen_number();
    span.add_event(
        "Generating Number".to_string(),
        vec![Key::new("number").i64(num.into())],
    );

    // 設置span屬性
    span.set_attribute(RANDOM.i64(10));


    // 開始一個新的span
    tracer.in_span("generate another number"|cx| {
            let span = cx.span();
            let num = gen_number();
            span.add_event(
                "Generating Number".to_string(),
                vec![Key::new("number").i64(num.into())],
            )
        })
    });

    // 優雅地關閉跟蹤器
    global::shutdown_tracer_provider();
    Ok(())
}

執行 cargo run 運行程序。

執行程序多次後,打開 Jaeger UI:http://localhost:16686/,選擇我們配置的服務名稱:rust-otlp-basic。如圖:

像這樣使用 OpenTelemetry 還是有些複雜,在下一篇文章中,我們將引入 Tracing crates,來簡化 OpenTelemetry 的使用。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/OW4vWSR3PQWEoe4Lk5o8qw