#tracing #logging-tracing #logging #google-cloud #tracing-subscriber #google #gcp

tracing-stackdriver

兼容 Stackdriver 的跟踪层和事件格式化工具

15 个版本 (破坏性)

0.10.0 2024 年 3 月 11 日
0.9.0 2023 年 12 月 18 日
0.8.0 2023 年 9 月 26 日
0.7.2 2023 年 5 月 24 日
0.1.0 2020 年 4 月 13 日

#5 in #google-cloud

Download history 12246/week @ 2024-04-14 11260/week @ 2024-04-21 10429/week @ 2024-04-28 10573/week @ 2024-05-05 9712/week @ 2024-05-12 10172/week @ 2024-05-19 8605/week @ 2024-05-26 8374/week @ 2024-06-02 13988/week @ 2024-06-09 12229/week @ 2024-06-16 12663/week @ 2024-06-23 11681/week @ 2024-06-30 12456/week @ 2024-07-07 10762/week @ 2024-07-14 11541/week @ 2024-07-21 3697/week @ 2024-07-28

39,218 每月下载量
8 个crate中(5个直接使用) 使用

MIT 许可证

44KB
708

tracing-stackdriver

Pre-release Checks Crates.io

tracing 是一个基于异步 await 点之间可能嵌套的 Span 的上下文,发出 Event 的范围结构和诊断系统。这些属性使 tracing 非常适合与 Google Cloud Operations Suite 结构化日志(以前称为 Stackdriver)一起使用。

此crate提供了一个用于与 tracing Registry 一起使用的 Layer,该层将 tracing Span 和事件格式化为适合通过 jsonPayload 字段由 Google Operations Logging 消耗的适当结构的 JSON。这包括以下行为和增强:

  1. 所有事件的 rfc3339 格式的时间戳
  2. tracing Level 导出的 severity(在 LogSeverity 格式)
  3. 从事件 target 导出的 target
  4. span 键下包含 Span 名称和自定义字段
  5. 自动嵌套以 http_request. 为前缀的事件字段
  6. 自动嵌套以 labels. 为前缀的事件字段,重写为 特殊字段
  7. 自动将 insert_id 重写为 特殊字段
  8. 自动将所有字段键转换为驼峰命名法(例如 field_name -> fieldName,或 field.name -> fieldName
  9. 支持 valuable,包括一个 HttpRequest 辅助 struct
  10. 支持由 OpenTelemetry Span 和 跟踪 IDs 衍生的 Cloud Trace

示例

基本设置

use tracing_subscriber::{layer::SubscriberExt, Registry};

fn main() {
    let stackdriver = tracing_stackdriver::layer(); // writes to std::io::Stdout
    let subscriber = Registry::default().with(stackdriver);

    tracing::subscriber::set_global_default(subscriber).expect("Could not set up global logger");
}

自定义写入位置

use tracing_subscriber::{layer::SubscriberExt, Registry};

fn main() {
    let make_writer = || std::io::Stderr;
    let stackdriver = tracing_stackdriver::layer().with_writer(make_writer); // writes to std::io::Stderr
    let subscriber = Registry::default().with(stackdriver);

    tracing::subscriber::set_global_default(subscriber).expect("Could not set up global logger");
}

带有 httpRequest 字段

查看所有可用字段 这里

// requires working global setup (see above examples)

use hyper::Request;

fn handle_request(request: Request) {
    let method = &request.method();
    let uri = &request.uri();

    tracing::info!(
      http_request.request_method = %method,
      http_request.request_url = %uri,
      "Request received"
    );

    // jsonPayload formatted as:
    // {
    //   "time": "some-timestamp"
    //   "severity": "INFO",
    //   "httpRequest": {
    //     "requestMethod": "GET",
    //     "requestUrl": "/some/url/from/request"
    //    },
    //   "message": "Request received"
    // }
}

带有 labels 字段

将字符串化的标签映射到 logging.googleapis.com/labels 特殊字段 的键/值映射。有关 labels 的更多信息,请参阅 这里

// requires working global setup (see above examples)

fn main() {
    tracing::info!(
      labels.thread_count = 3,
      labels.is_production = true,
      labels.note = "A short note",
      "Application starting"
    );

    // jsonPayload formatted as:
    // {
    //   "time": "some-timestamp"
    //   "message": "Application starting",
    //   "logging.googleapis.com/labels": {
    //     "threadCount": "3",
    //     "isProduction": "true",
    //     "note": "A short note",
    //   }
    // }
}

带有 insert_id 字段

将字符串化的 insert_id 映射到 logging.googleapis.com/insertId 特殊字段。有关 insertId 的更多信息,请参阅 这里。这是一个可选字段,因为如果省略了 insert_id,日志 API 会为该字段分配其自己的唯一标识符。

// requires working global setup (see above examples)

fn main() {
    tracing::info!(
      insert_id = 1234,
      "Application starting"
    );

    // jsonPayload formatted as:
    // {
    //   "time": "some-timestamp"
    //   "message": "Application starting",
    //   "logging.googleapis.com/insertId": "1234"
    // }
}

带有更具体的 LogSeverity 级别

Google 支持的严重性级别略不同于 tracing。将 tracing 级别自动映射到 LogSeverity 级别,但您可以通过使用提供的 LogSeverity 级别和 severity 键来自定义级别,超出了 tracing 级别和 LogSeverity 级别的交集。

use tracing_stackdriver::LogSeverity;

fn main() {
    // requires working global setup (see above examples)

    tracing::info!(severity = %LogSeverity::Notice, "Application starting");

    // jsonPayload formatted as:
    // {
    //   "time": "some-timestamp"
    //   "severity": "NOTICE",
    //   "message": "Application starting"
    // }
}

带有 valuable 支持

tracing_stackdriver 通过 tracing不稳定的 valuable 支持 支持深层嵌套的结构化日志。此外,可以使用从库中导出的 HttpRequest 辅助结构体生成 httpRequest 字段,以更好地进行字段编译时检查。

要启用 valuable 支持,请使用 valuable 功能标志,并使用以下命令编译您的项目:RUSTFLAGS="--cfg tracing_unstable"


// requires working global setup (see above examples)

use hyper::Request;
use tracing_stackdriver::HttpRequest;
use valuable::Valuable;

#[derive(Valuable)]
struct StructuredLog {
    service: &'static str,
    handler: &'static str
}

fn handle_request(request: Request) {
    let http_request = HttpRequest {
        request_method: request.method().into(),
        request_url: request.uri().into(),
        ..Default::default()
    };

    let structured_log = StructuredLog {
        service: "request_handlers",
        handler: "handle_request",
    };

    tracing::info!(
      http_request = http_request.as_value(),
      structured_log = structured_log.as_value(),
      "Request received"
    );

    // jsonPayload formatted as:
    // {
    //   "time": "some-timestamp"
    //   "severity": "INFO",
    //   "httpRequest": {
    //     "requestMethod": "GET",
    //     "requestUrl": "/some/url/from/request"
    //    },
    //   "structuredLog": {
    //      "service": "request_handlers",
    //      "handler": "handle_request"
    //    },
    //   "message": "Request received"
    // }
}

带有 Cloud Trace 支持

tracing_stackdriver 支持通过 tracing_opentelemetryCloud TraceOpenTelemetry 集成,并输出 特殊的 Cloud Trace LogEntry 字段 以进行跟踪采样和日志关联。

要启用云跟踪支持,您需要启用 opentelemetry 功能标志,并将 CloudTraceConfiguration 提供给层的 with_cloud_trace 方法。

use tracing_stackdriver::CloudTraceConfiguration;

fn main() {
    // You may want to configure the `tracing_opentelemetry` layer to suit your needs,
    // including the use of an additional tracer or exporter.
    // See `tracing_opentelemetry`'s doc for details.
    let opentelemetry = tracing_opentelemetry::layer();

    let stackdriver = tracing_stackdriver::layer()
        .with_cloud_trace(CloudTraceConfiguration { project_id: "my-project-id" });

    let subscriber = tracing_subscriber::Registry::default()
        .with(opentelemetry)
        .with(stackdriver);

    // set up the root span to trigger Span/Trace ID generation
    let root = tracing::info_span!("root");
    let _root = root.enter();
    tracing::info!("Application starting");

    // jsonPayload formatted as:
    // {
    //   "time": "some-timestamp"
    //   "severity": "INFO",
    //   "message": "Application starting",
    //   "logging.googleapis.com/spanId": "0000000000000000",
    //   "logging.googleapis.com/trace":"projects/my-project-id/traces/0679686673a"
    // }
}

包含源位置

默认情况下,tracing_stackdriver 在发出的 LogEntry 上的特殊 SourceLocation 组合字段 中包含 tracing 事件的源位置。此行为可以通过层的 with_source_location 方法进行配置。

fn main() {
    // Source Locations are enabled by default, so they must be disabled by setting the configuration
    // to "false" using with_source_location()
    let stackdriver = tracing_stackdriver::layer().with_source_location(false);
    let subscriber = tracing_subscriber::Registry::default().with(stackdriver);
    tracing::subscriber::set_global_default(subscriber).expect("Could not set up global logger");

    // tracing events from this point on will have their source location omitted
}

依赖关系

~2.6-5MB
~97K SLoC