this post was submitted on 12 Jul 2023
6 points (100.0% liked)

Rust Lang

3 readers
1 users here now

Rules [Developing]

Observe our code of conduct

Constructive criticism only

No endless relitigation

No low-effort content

No memes or image macros

No NSFW Content

founded 1 year ago
MODERATORS
 

I need some help here trying to add a second logging subscriber for a specific target to the Lemmy server Rust code.

Here is the default logging in the app: https://github.com/LemmyNet/lemmy/blob/main/src/lib.rs

Step 1 ==============
I know I have to add another library to log to a file.
cargo add tracing-appender

Step 2 ===============
I know I have to specify how I want the files to work, I found this pile of code:

  let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
  let formatting_layer = fmt::layer().pretty().with_writer(std::io::stderr);
  let log_file_name = Local::now().format("%Y-%m-%d").to_string() + "-apub.log";
  let file_appender = rolling::daily("/home/lemmy/logs", log_file_name);
  let (non_blocking_appender, _guard) = non_blocking(file_appender);
  let file_layer = fmt::layer()
      .with_ansi(false)
      .with_writer(non_blocking_appender);

  Registry::default()
      .with(env_filter)
      .with(ErrorLayer::default())
      .with(formatting_layer)
      .with(file_layer)
      .init();

Now this isn't right, because it registers itself as "default", and I want it to be a Target - and I still want the normal Lemmy logging behavior to exist.

I want the macros to work like:

warn!("this is how normal Lemmy server log entries are created in the current code");  
warn!(target: "apubfile", "this logging entry only goes to the apub file logging using tracing-appender);

Can someone work this out? How to have two subscribers, not just the single default, and how to specify the target: string on the subscriber?

Thank you.

EDIT: ok, I found an example of how to have two logs at the same time, one to file and one to console: https://stackoverflow.com/questions/76042603/how-to-unify-the-time-in-the-console-and-the-file-when-using-tracing-appender -- I still need to figure out how to get this into Lemmy's structure and attach to a "target".

top 1 comments
sorted by: hot top controversial new old
[–] MoSal@lemmyrs.org 1 points 1 year ago

I think tracing-appender is not directly relevant here.

Never touched tracing layers before. But I think this may help you:

EnvFilter implements both the Layer and Filter traits, so it may be used for both global filtering and per-layer filtering, respectively. See the documentation on filtering with Layers for details.

https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html

So adding a filter with <custom-target>=<log-level> to your custom layer should work.

Example:

use tracing_subscriber::{fmt, EnvFilter, prelude::*};

fn main() {
    let custom_layer = fmt::layer()
        .with_writer(|| std::io::stderr())
        // EnvFilter as a Filter
        .with_filter(EnvFilter::try_new("custom_target=info").unwrap());

    tracing_subscriber::registry()
        // EnvFilter as a Layer
        .with(EnvFilter::try_new("info").unwrap())
        .with(fmt::layer()) // default
        .with(custom_layer) // custom
        .init();

    tracing::info!("default target");
    tracing::info!(target:"custom_target", "custom target");
}

Here the default layer is using the default writer to stdout, while the custom one is writing to stderr.