Rust logger package?

I am looking for a production level logger package to use. (Main use: logging of production services, for future debugging purposes.)

On crates.io, the highest seems to be https://crates.io/crates/env_logger at 41M downloads.

Any other crates worth look into?

We’ve been using slog with the syslog backend as our go-to logger. Develpment seems to have stalled lately but that’s not much of a problem as it is fairly feature complete already.

I'm not a massive fan of the printf-style logging you get with the log crate and prefer to use structured logging when I can. It really pays off for logging in production services because you can wire it up to something like Datadog or the Elastic stack to get rich dashboards.

I used to use slog for this, but over the last year or so I've started moving towards the tracing crate and the JSON output generated by the tracing_subscriber logger.

For example, I have a Discord bot which logs every command that gets executed. This is the code I use to log the incoming message:

tracing::debug!(
    command,
    author.nick = author,
    author.id = msg.author.id,
    message,
    link,
    guild,
    attachments = msg.attachments,
    "Executing a command"
);

It will log this output (indented for readability) when you ask it to run the about command:

{
    "timestamp": "2022-02-11T02:49:34.485522Z",
    "level": "DEBUG",
    "fields": {
        "message": "@Bot#3189 about",
        "command": "about",
        "author.nick": "Michael",
        "author.id": "419204234060234766",
        "link": "https://discord.com/channels/860564021496905788/860564021496905792/941526345861709824",
        "guild": "Michael's Test Server",
        "attachments": "[]"
    },
    "target": "halp::discord::hooks"
}

Besides the structured logging, tracing has this concept of "spans" representing a section of code with a start and end. For example, you might enter a new span when you start handling a HTTP request and attach fields like the endpoint and request ID, you would then do the normal handling process, emitting logs or entering nested spans as you go, before you finally exit the span.

Depending on the logger implementation, you could log when spans are entered/exited or even use it to record timing metrics. The tokio console uses spans under the hood to help you debug async code and reason about futures as they are being executed.

9 Likes

Thanks for sharing this detailed post. I too find that I am not a fan of printf-style logging + grep style searching, but it was not obvious to me how to do anything better. Thanks for sharing this detailed post.

1 Like

Do you have a setup that can be run locally without Datadog / ElasticSearch ? I am currently setting this up and trying to figure out the right local tools to visualize the json logs.

I think you can run the elastic stack locally using Docker, although the last time I did that was for a personal project several years ago.

Normally when I'm just developing locally I'll just look at the logs manually. Visualising your logs gets more important when you're deploying across multiple nodes and have a service up for longer periods of time, so that's where I'll use the infrastructure we've set up for staging/production logs.