#tracing-subscriber #logging-tracing #json-log #tracing #json #subscriber #logging

json-subscriber

用于在JSON中记录日志的自定义层和订阅者,适用于 tracing

3个版本

0.1.2 2024年6月16日
0.1.1 2024年6月14日
0.1.0 2024年6月13日

#283调试

MIT 许可证

135KB
2K SLoC

json-subscriber

json-subscriber 是 (主要) tracing_subscriber::fmt::json 的替代品。

它提供了一些辅助工具,以尽可能与 tracing_subscriber 兼容,同时也允许对格式进行简单的扩展,以便在日志行中包含自定义数据。

最终目标是让每个用户都能根据自己的意愿定义JSON日志行的结构。目前,该库只允许包含 tracing-subscriber 以及 OpenTelemetry 跟踪和跨度 ID。

兼容性

无论您如何创建 FmtSubscriberfmt::Layer,在这个包中都应该能实现相同的效果。

例如,在 Tracing 的 README.md 中,您可以看到一个 yak-shaving 示例,其中只需将 tracing_subscriber 更改为 json_subscriber,一切都将按预期工作,只是日志将采用 JSON 格式。

use tracing::info;
use json_subscriber;

fn main() {
    // install global collector configured based on RUST_LOG env var.
    json_subscriber::fmt::init();

    let number_of_yaks = 3;
    // this creates a new event, outside of any spans.
    info!(number_of_yaks, "preparing to shave yaks");

    let number_shaved = yak_shave::shave_all(number_of_yaks);
    info!(
        all_yaks_shaved = number_shaved == number_of_yaks,
        "yak shaving completed."
    );
}

tracing_subscriber::fmt 下的大多数配置都应等效。例如,可以创建一个类似这样的层

json_subscriber::fmt()
    // .json()
    .with_max_level(tracing::Level::TRACE)
    .with_current_span(false)
    .init();

调用 .json 是不必要的,该方法不做任何操作,并已被标记为已弃用。但是,它保留下来是为了简化从 tracing-subscriber 的迁移。

尝试调用 .pretty.compact 将导致错误。 json-tracing 不支持除 JSON 之外的其他输出。

扩展

OpenTelemetry

要在日志行中包含来自OpenTelemetry的跟踪ID和span ID,只需调用with_opentelemetry_ids。如果没有配置tracing-opentelemetry层,则此调用将无任何效果。

let tracer = todo!();
let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer);
let json = json_subscriber::layer()
    .with_current_span(false)
    .with_span_list(false)
    .with_opentelemetry_ids(true);

tracing_subscriber::registry()
    .with(opentelemetry)
    .with(json)
    .init();

这将生成如下的日志行(不包括格式化)

{
  "fields": {
    "message": "shaving yaks"
  },
  "level": "INFO",
  "openTelemetry": {
    "spanId": "35249d86bfbcf774",
    "traceId": "fb4b6ae1fa52d4aaf56fa9bda541095f"
  },
  "target": "readme_opentelemetry::yak_shave",
  "timestamp": "2024-06-06T23:09:07.620167Z"
}

请参阅readme-opentelemetry示例以获取完整的代码。

自定义

您还可以指定要添加到每个日志行中的自定义静态字段,或者序列化由其他Layer提供的扩展

#[derive(Serialize)]
struct Foo(String);

impl<S: Subscriber + for<'lookup> LookupSpan<'lookup>> Layer<S> for FooLayer {
    fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
        let span = ctx.span(id).unwrap();
        let mut extensions = span.extensions_mut();
        let foo = Foo("hello".to_owned());
        extensions.insert(foo);
    }
}

fn main() {
  let foo_layer = FooLayer;

  let mut layer = json_subscriber::JsonLayer::stdout();
  layer.serialize_extension::<Foo>("foo");

  registry().with(foo_layer).with(layer);
}

基准测试

此crate努力比tracing_subscriber更快。请参阅基准测试

支持的Rust版本

json-subscriber基于最新的稳定版构建。最低支持版本是1.65。当前版本不保证在低于最低支持版本的Rust版本上构建。

json-subscriber遵循与Tokio项目相同的编译器支持策略。当前稳定Rust编译器和之前三个小版本的编译器将始终得到支持。例如,如果当前稳定编译器版本是1.69,则最低支持版本不会增加到1.66以下,即三个小版本之前。只要这样做符合此策略,增加最低支持编译器版本不被视为semver破坏性变更。

许可证

本项目使用MIT许可证

贡献

除非您明确声明,否则您提交给json-subscriber的任何贡献将被许可为MIT,不附加任何额外条款或条件。

依赖项

~1.8–4MB
~72K SLoC