7 个版本 (破坏性更新)

0.8.0 2023年8月2日
0.7.0 2023年5月27日
0.6.0 2023年3月11日
0.5.0 2023年1月9日
0.2.0 2022年7月3日

#163 in 调试

Download history 81/week @ 2024-04-14 73/week @ 2024-04-21 43/week @ 2024-04-28 51/week @ 2024-05-05 35/week @ 2024-05-12 121/week @ 2024-05-19 64/week @ 2024-05-26 62/week @ 2024-06-02 86/week @ 2024-06-09 157/week @ 2024-06-16 67/week @ 2024-06-23 121/week @ 2024-06-30 62/week @ 2024-07-07 62/week @ 2024-07-14 71/week @ 2024-07-21 79/week @ 2024-07-28

每月 289 次下载

Apache-2.0

145KB
2.5K SLoC

Apache SkyWalking Rust Agent

Sky Walking logo

Twitter Follow

Crates CI

SkyWalking Rust Agent 为 Rust 应用和库提供可观察性功能,包括跟踪、指标、分布式系统的拓扑图和警报。它使用 SkyWalking 原生格式和核心概念,以保持最佳兼容性和性能。

概念

所有概念均来自官方 SkyWalking 定义。

跟踪

Span

Span 是分布式跟踪系统中的一个重要且常见概念。从 Google Dapper 论文中学习 Span。为了更好的性能,我们将 span 扩展为 3 种类型。

  1. EntrySpan EntrySpan 代表服务提供者,也是服务器端端点。作为一个 APM 系统,我们针对的是应用服务器。所以几乎所有的服务和 MQ 消费者都是 EntrySpan。
  2. LocalSpan LocalSpan 代表一个普通的 Java 方法,它不与远程服务相关,也不是 MQ 生产者/消费者或服务(例如 HTTP 服务)提供者/消费者。
  3. ExitSpan ExitSpan 代表服务或 MQ 生产者的客户端,早期 SkyWalking 中称为 LeafSpan。例如,通过 JDBC 访问数据库、读取 Redis/Memcached 被归类为 ExitSpan。

标签和日志是 span 的类似属性。

  • 标签是一个键值对,用于指示具有字符串值的属性。
  • 日志比标签更复杂,包含一个时间戳和多个键值对。日志表示一个事件,通常是错误发生。

跟踪上下文

跟踪上下文是跟踪过程的上下文。Span 应该仅通过上下文创建,并在 span 完成后存档到上下文。

日志记录

LogRecord

LogRecord 是 LogData 的简单构建器,它是 Skywalking 的日志格式。

指标

Meter

  • Counter API 代表一个单调递增的单个计数器,它自动收集数据并向后端报告。
  • Gauge API 代表一个单个数值。
  • 直方图 API 表示带有自定义桶的样本观察结果的摘要。

管理

报告实例的额外信息。

报告实例属性

方法 insert_os_infoskywalking::management::instance::Properties 中用于插入预定义的操作系统信息。此外,您还可以使用 insertupdateremove 来自定义实例信息。

预定义的操作系统信息

hostname 操作系统的主机名。
ipv4(可能多个) 网络的 ipv4 地址。
语言 rust
操作系统名称 Linux / Windows / Mac OS X
进程号 进程的 ID。

保持存活

在后台分析中保持实例存活。仅当不需要报告跟踪和指标时才建议单独进行 keepAlive 报告。否则,它将是重复的。

示例

use skywalking::{
    logging::{logger::Logger, record::{LogRecord, RecordType}},
    reporter::grpc::GrpcReporter,
    trace::tracer::Tracer,
    metrics::{meter::Counter, metricer::Metricer},
};
use std::error::Error;
use tokio::signal;

async fn handle_request(tracer: Tracer, logger: Logger) {
    let mut ctx = tracer.create_trace_context();

    {
        // Generate an Entry Span when a request is received.
        // An Entry Span is generated only once per context.
        // Assign a variable name to guard the span not to be dropped immediately.
        let _span = ctx.create_entry_span("op1");

        // Something...

        {
            // Generates an Exit Span when executing an RPC.
            let span2 = ctx.create_exit_span("op2", "remote_peer");

            // Something...

            // Do logging.
            logger.log(
                LogRecord::new()
                    .add_tag("level", "INFO")
                    .with_tracing_context(&ctx)
                    .with_span(&span2)
                    .record_type(RecordType::Text)
                    .content("Something...")
            );

            // Auto close span2 when dropped.
        }

        // Auto close span when dropped.
    }

    // Auto report ctx when dropped.
}

async fn handle_metric(mut metricer: Metricer) {
    let counter = metricer.register(
        Counter::new("instance_trace_count")
            .add_label("region", "us-west")
            .add_label("az", "az-1"),
    );

    metricer.boot().await;

    counter.increment(10.);
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // Connect to skywalking oap server.
    let reporter = GrpcReporter::connect("http://0.0.0.0:11800").await?;
    // Optional authentication, based on backend setting.
    let reporter = reporter.with_authentication("<TOKEN>");

    // Spawn the reporting in background, with listening the graceful shutdown signal.
    let handle = reporter
        .reporting()
        .await
        .with_graceful_shutdown(async move {
            signal::ctrl_c().await.expect("failed to listen for event");
        })
        .spawn();

    let tracer = Tracer::new("service", "instance", reporter.clone());
    let logger = Logger::new("service", "instance", reporter.clone());
    let metricer = Metricer::new("service", "instance", reporter);

    handle_metric(metricer).await;

    handle_request(tracer, logger).await;

    handle.await?;

    Ok(())
}

高级 API

异步 Span API

Span::prepare_for_async 设计用于异步用例。当需要将 Span 的标签、日志和属性(包括结束时间)设置在另一个线程或协程中时。

TracingContext::wait 等待所有 AsyncSpan 完成。

use skywalking::{
    trace::tracer::Tracer,
    trace::span::HandleSpanObject,
};

async fn handle(tracer: Tracer) {
    let mut ctx = tracer.create_trace_context();

    {
        let span = ctx.create_entry_span("op1");

        // Create AsyncSpan and drop span.
        // Internally, span will occupy the position of finalized span stack.
        let mut async_span = span.prepare_for_async();

        // Start async route, catch async_span with `move` keyword.
        tokio::spawn(async move {

            async_span.add_tag("foo", "bar");

            // Something...

            // async_span will drop here, submit modifications to finalized spans stack.
        });
    }

    // Wait for all `AsyncSpan` finished.
    ctx.wait();
}

高级报告器

高级报告提供了一种将代理收集的数据提交到后端的替代方法。

kafka 报告器

Kafka 报告器插件支持将跟踪、指标、日志、实例属性报告到 Kafka 集群。

确保已启用功能 kafka-reporter

#[cfg(feature = "kafka-reporter")]
mod example {
    use skywalking::reporter::Report;
    use skywalking::reporter::kafka::{KafkaReportBuilder, KafkaReporter, RDKafkaClientConfig};

    async fn do_something(reporter: &impl Report) {
        // ....
    }

    async fn foo() {
        let mut client_config = RDKafkaClientConfig::new();
        client_config
            .set("bootstrap.servers", "broker:9092")
            .set("message.timeout.ms", "6000");

        let (reporter, reporting) = KafkaReportBuilder::new(client_config).build().await.unwrap();
        let handle = reporting.spawn();

        do_something(&reporter);

        handle.await.unwrap();
    }
}

如何编译?

如果您有 skywalking-(VERSION).crate,您可以使用以下方式解包

tar -xvzf skywalking-(VERSION).crate

使用 cargo build 生成库。如果您想验证行为,我们建议使用 cargo run --example simple_trace_report 生成可执行文件,然后运行它。

注意

此 crate 会自动生成 protobuf 相关代码,需要在编译前安装 protoc

请选择以下方式之一来安装 protoc

  1. 使用您的操作系统包管理器。

    对于基于 Debian 的系统

    sudo apt install protobuf-compiler
    

    对于 MacOS

    brew install protobuf
    
  2. 在 crate 构建脚本中自动编译 protoc,只需在 Cargo.toml 中添加功能 vendored 即可。

    cargo add skywalking --features vendored
    
  3. 构建。如果 protc 没有安装到 $PATH 中,则应设置环境变量 PROTOC

    PROTOC=/the/path/of/protoc
    

有关详细信息,请参阅 prost-build:sourcing-protoc

发布

SkyWalking 提交者(包括 PMC)可以遵循 此文档 发布官方版本。

许可证

Apache 2.0

依赖关系

~9–20MB
~249K SLoC