-
Notifications
You must be signed in to change notification settings - Fork 160
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
feat: rename zenoh::try_init_log_from_env
to zenoh::init_logging
#1165
base: dev/1.0.0
Are you sure you want to change the base?
Conversation
I disagree on this PR. |
That's right, but it brings me two things in mind:
EDIT: if the user still want to a finer control on the logging than |
If you are ok with this idea, I can open a PR right now. Exposing a |
@gabrik, as you touched to the logging, do you have an opinion on the proposition above? |
I do not have a strong opinion on it, the fact that fails silently is not a real issue, as it means that the subscriber has been already initialized in the process. Regarding the Also with |
A logging rework should be done throughout the whole Zenoh ecosystem. I'll try to enumerate what I believe current issues are:
|
Exactly, even if
It's already the case with In my opinion, |
`init_logging` code is kept unused waiting for eclipse-zenoh/zenoh#1165
Tracing doesn't offer additional levels, but
I'm not sure to follow you, could you elaborate on this point? I did a quick search on Google ("RUST_LOG Python", "RUST_LOG javascript", etc.) and I didn't found any application (zenoh-python excepted) in an other language than Rust using
I agree, and that's completely the point of That's also based on this zenoh-python experience that I made the proposal for a
I was ok with that, but now I think we should go further:
|
* feat: improve logging * fix: add missing header * fix: replace `init_logging` with `try_init_log_from_env` `init_logging` code is kept unused waiting for eclipse-zenoh/zenoh#1165
In addition to my previous remarks, I think we can add the following issue:
|
I think we have two separate problems here
I think that from the API point of view the function
I think we can add Examples: init_logging().from_env().wait().; // init from RUST_LOG
init_logging().from_string("Debug").wait().; // init from string only
init_logging().from_string("Debug").from_env().wait().; // init from string then override from env, if env present
init_logging().from_env().or_from_string("Debug").wait(); // init from env and if not present, init from string |
There is no point using our current builder pattern for something not being related to asynchronous. We could use a common builder pattern, so replacing
That' why |
Tests are now using `test-log` library. See detailed `zenoh_util::init_logging` documentation.
Anyway, I've pushed a POC of my proposal, with a very detailed documentation, and some experimentation results about memory leaks. /// Initialize zenoh logging using the value of `ZENOH_LOG` environment variable.
///
/// `ZENOH_LOG` is parsed use [`LogLevel::from_str`], possible values are `"debug"`/`"INFO"`/etc.
/// If `ZENOH_LOG` is not provided, [`LogLevel::default`], i.e. `warn` is used.
///
/// See [`init_logging_with_level`] if you prefer setting the level directly in your code.
/// This function is roughly a wrapper around
/// ```ignore
/// let level = std::env::var("ZENOH_LOG")
/// .map(|var| var.parse().unwrap())
/// .unwrap_or_default();
/// init_logging_with_level(level);
/// ```
///
/// Logs are printed on stdout and are formatted like the following:
/// ```text
/// 2024-06-19T09:46:18.808602Z INFO main ThreadId(01) zenoh::net::runtime: Using ZID: 1a615ea88fe1dc531a9d8701775d5bee
/// 2024-06-19T09:46:18.814577Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::1]:58977
/// ```
///
/// # Advanced use
///
/// zenoh logging uses `tracing` crates internally; this function is just a convenient wrapper
/// around `tracing-subscriber`. If you want to control the formatting, or have a finer grain on
/// log filtering, we advise using `tracing-subscriber` directly.
///
/// However, to make migration and on the fly debugging easier, [`RUST_LOG`][1] environment variable
/// can still be used, and will override `ZENOH_LOG` configuration.
///
/// # Panics
///
/// This function may panic if the following operations fail:
/// - parsing `ZENOH_LOG`/`RUST_LOG` (see [Advanced use](#advanced-use)) environment variable
/// - register the global tracing subscriber, because another one has already been registered
///
/// These errors mostly being the result of unintended use, fast failure is assumed to be more
/// suitable than unexpected behavior, especially as logging should be initialized at program start.
///
/// # Use in tests
///
/// This function should **not** be used in tests, as it would panic as soon as there is more
/// than one test executed in the same unit, because only the first one to execute would be able to
/// register the global tracing subscriber.
///
/// Moreover, `tracing` and Rust logging in general requires special care about testing because of
/// libtest output capturing; see
/// [`SubscriberBuilder::with_test_writer`](tracing_subscriber::fmt::SubscriberBuilder::with_test_writer).
///
/// That's why we advise you to use a dedicated library like [`test-log`][3]
/// (with `"tracing"` feature enabled).
///
/// # Memory leak
///
/// [`tracing`] use a static subscriber, which is not deallocated prior to process exiting.
/// Tools such as `valgrind` will then report memory leaks in *still reachable* category.
///
/// However, when `RUST_LOG` is provided (see [Advanced use](#advanced-use)),
/// [`tracing_subscriber::EnvFilter`] is then used, and causes also *still reachable* blocks,
/// but also *possibly lost* blocks, which are [known false-positives][2].
/// Those "leaks" can be "suppressed" from `valgrind` report using the following suppression:
/// ```text
/// {
/// zenoh_init_logging
/// Memcheck:Leak
/// ...
/// fun:*zenoh*init_logging*
/// }
/// ```
///
/// [1]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives
/// [2]: https://github.com/rust-lang/regex/issues/1205
/// [3]: https://crates.io/crates/test-log By the way, as written in the documentation, |
/// # Panics | ||
/// | ||
/// This function may panic if the following operations fail: | ||
/// - parsing `RUST_LOG` (see [Advanced use](#advanced-use)) environment variable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parsing RUST_LOG
/ ZENOH_LOG
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed, ZENOH_LOG
is not parsed in init_logging_with_level
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get this, sorry. But why? Isn't it just adds more complexity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We talked about it in our last meeting: to keep things the simplest possible, I've dissociated initialization from variable and initialization from code.
It's still possible to override the provided level with RUST_LOG
environment variable for debug purpose.
I don't know what would be the use case of using init_logging_from_level
together with ZENOH_LOG
. The only thing I see is when you want to increase the logging level to debug something (without having to recompile/redeploy), but in that case, RUST_LOG
seems more appropriate to me, and it's already supported.
The approach looks good for me. The naming |
I've also tried to specify a convention for the bindings behavior, that I've written in /// Initialize zenoh logging using the provided callbacks.
///
/// This function is mainly meant to be used in zenoh bindings, to provide a bridge between Rust
/// `tracing` implementation and a native logging implementation.
///
/// To be consistent with zenoh API, bindings should parse `ZENOH_LOG` environment variable
/// to set the log level (unless it is set directly in code).
/// However, if `RUST_LOG` environment variable is provided, the callback will be skipped, and
/// [`init_logging`] called instead. I admit I'm not sure about that |
pub use zenoh_util::{init_logging, init_logging_with_level, InvalidLogLevel, LogLevel}; | ||
#[cfg(feature = "internal")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- better to use
#[zenoh_macros::internal]
- the function implementations should be under "internal" too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to use #[zenoh_macros::internal]
Indeed
the function implementations should be under "internal" too
Do you mean moving zenoh::logging::try_init_logging
to zenoh::internal::try_init_logging
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I mean the implementation of internal/unstable functions are usually under "internal"/"unstable" cfg too, not only reexports.
It would be nice to check such cases automatically - generate build error if there is some public item inside which is not publicly reexported
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, I will add the feature to zenoh-util
.
This rework however doesn't cover the first point of @Mallets:
It could be solved however with additional variants to But that's not the object of the current rework., this one should just be extendable in a backward compatible way. It should be part of the next rework regarding structured logging application. |
The to-decide list brought by the rework is:
|
@Mallets I would to ask for your feedback on the rework proposal when you will have the time. |
@milyin If I remember correctly, we already talked about doing this renaming. Here is the PR.
@Mallets