How do I get json logging from the tracing lib?

Apologies if this comes across as a bit of an RTFM question, but I've tried my best to read the docs here and I am still completely clueless.

I am writing a library on top of the AWS SDK libraries and I wanted to be as consistent as possible with them when writing logs, so I've added the tracing - Rust as a dependency of my project and I'm using their event! macro in place of where I would normally use a println! with some fields for context.

For end users, it seems they need a runtime to subscribe to the events and spans that are being created by tracing. The AWS docs don't go into any great detail Enable logging of AWS SDK for Rust code - AWS SDK for Rust and just recommend initializing the default thing

tracing_subscriber::fmt::init();

which means having the dependency tracing_subscriber - Rust which I've done for my own tests with

[dev-dependencies]
tracing-subscriber = { version = "0.3.19", features = ["json"] }

but this doesn't seem to be causing Json in tracing_subscriber::fmt::format - Rust to be used. I'm still getting regular ansi-colored output in my tests, which is no good because downstream users will almost certainly want me to document for them how to get JSON output from the logs in my library.

The AWS docs also reference tracing_subscriber::fmt - Rust for more information but I can't see anything here showing me how to enable JSON. Ideally I'd like it to be enabled with just an envvar but if end-users need to use code configuration I guess that's ok.

ok, by basically guessing, I was able to get json output by using

    tracing_subscriber::fmt().json().init();

but is there a way to do this with just envvars?

That turns a simple

    event!(Level::INFO, "hello world");

into

{"timestamp":"2024-12-09T11:35:43.357112Z","level":"INFO","fields":{"message":"hello world"},"target":"workers"}

if you want to turn on/off or set certain levels, you can use EnvFilter:

// from_default_env() uses `RUST_LOG` environment variable
fmt().json().with_env_filter(EnvFilter::from_default_env()).init();
// you can also specify a custom variable name:
fmt().json().with_env_filter(EnvFilter::from_env("MY_LOG")).init();

however, if you want to switch between json and simple formats, then you'll have to implement your own Subscriber, the fmt subscriber doesn't support this feature.

2 Likes