Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: meta logging in logger? #645

Open
tisonkun opened this issue Nov 14, 2024 · 4 comments
Open

Question: meta logging in logger? #645

tisonkun opened this issue Nov 14, 2024 · 4 comments

Comments

@tisonkun
Copy link
Contributor

Some log implementations support logger pipeline. For example, in logforth you can write:

use log::LevelFilter;
use logforth::append;

logforth::builder()
    .dispatch(|d| {
        d.filter(LevelFilter::Error)
            .append(append::Stderr::default())
    })
    .dispatch(|d| {
        d.filter(LevelFilter::Info)
            .append(append::Stdout::default())
    })
    .apply();

log::error!("Hello error!");
log::warn!("Hello warn!");
log::info!("Hello info!");
log::debug!("Hello debug!");
log::trace!("Hello trace!");

When I'm trying to add some complex appenders, for example, Kafka appender, it's natural to use a Kafka client lib. However, such a client lib may log inside also, which can result in an infinite recursive logging if such an appender is installed globally.

I did some investigation and how a possible solution, but would like to open this issue for discussion:

  1. Filter certain target in specific appender:
impl log::Log KafkaAppender {
  fn log(&self, record: &Record) {
    if record.target().start_with("rdkafka") { return; }
  }
}

This is, however, both brittle and may filter logs from user code. I don't know how targets are defined and if we can reliably depend on that matches.

@KodrAus
Copy link
Contributor

KodrAus commented Nov 28, 2024

This is a tricky topic, and one that any log framework will encounter at some point. Since log itself doesn't give you many tools to work with, one option that logforth could use is to set a thread-local at the start of its entrypoint Log::log implementation and use that to discard or re-route logs produced while that local is set. It would mean that you'd need some control over whether code plugged in to the appender created any background threads, but it limits the potential for infinite log looping.

@tisonkun
Copy link
Contributor Author

tisonkun commented Jan 25, 2025

@KodrAus I'm considering a related topic: whether it's reasonable to add an optional logger field for all log macros.

The idea comes from spdlog-rs (cc @SpriteOvO) where they have:

/// # Examples
///
/// ```
/// use spdlog::debug;
///
/// # struct Position { x: f32, y: f32 }
/// # let app_events = spdlog::default_logger();
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// // Using the global default logger
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
///
/// // Or using the specified logger
/// debug!(logger: app_events, "New position: x: {}, y: {}", pos.x, pos.y);
/// ```
#[macro_export]
macro_rules! debug {
    (logger: $logger:expr, $($arg:tt)+) => (
        $crate::log!(logger: $logger, $crate::Level::Debug, $($arg)+)
    );
    ($($arg:tt)+) => (
        $crate::log!($crate::Level::Debug, $($arg)+)
    )
}

and "Named optional parameters"

Name Type Description
logger Arc<Logger> or Logger If specified, the given logger will be used instead of the global default logger.

@tisonkun
Copy link
Contributor Author

This can possibly work around the meta logging issue because one can configure different logger for different use case, the same as log4j can apply different config for different logger (https://logging.apache.org/log4j/2.x/manual/configuration.html#logger-attributes-name)

@KodrAus
Copy link
Contributor

KodrAus commented Jan 26, 2025

Adding a logger parameter to the macros would be a worthwhile enhancement I think 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants