-
Notifications
You must be signed in to change notification settings - Fork 24
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
Implement tracing support with associated type on LogLevel trait #124
Conversation
Pull Request Test Coverage Report for Build 11864002921Details
💛 - Coveralls |
What seems logical to me for commits
|
b137911
to
dddcca0
Compare
Sounds reasonable. I started with the premise that it wasn't necessary as a wrapper on u8, but as an enum instead that maps onto LevelFilter it's pretty neat. Ooh, idea. If instead of trying to convert from LevelFilter to Option I just add conversions from VerbosityFilter, then this is actually possible to acheive without that log PR. |
I'm fine with it being an
Not quite sure what you are referring to with this idea |
I wanted to move clap-verbosity-flag/src/log.rs Lines 6 to 13 in dddcca0
log::LevelFilter to Option<log::Level> and tracing_core::LevelFilter to Option<tracing_core::Level> , tracing implements a conversion trait, but log doesn't. The log PR I mentioned above addresses that, but it's not actually necessary. Instead I can add a type bound that converts from VerbosityFilter to Option<L::Level> , and implement that for the two crates. This would mean that the code in log.rs/tracing.rs is just simple conversion methods and log level implementations.
|
6fd4d22
to
3e04897
Compare
This makes the calculated log level filter more explicit by introducing a new `Filter` type that can be converted directly to and from the log Level and LevelFilter types.
- Add log feature flag - Move log specific code to log module - Add Level and LevelFilter associated types on LogLevel trait - Duplicate Verbosity struct with cfg flags as there's no easy way to have an optional default for an associated type BREAKING CHANGE: The log crate is now an optional dependency, enabled by default. The `LogLevel` trait now has associated types for `Level` and `LevelFilter` instead of these being the log crate types. The `log::Level` and `log::LevelFilter` types are now re-exported from the log module rather than the top-level module. This is a breaking change that will affect users who have implemented the `LogLevel` trait or imported the `Level` and `LevelFilter` types from the top-level module.
Add a new `tracing` feature flag and tracing module to support the `tracing` crate. Fixes: clap-rs#121
Previously the example code was using the `tracing-log` crate to integrate with the `tracing` ecosystem. This crate is no longer necessary as `tracing` now provides implementations of the `LogLevel` trait that expose the `tracing` log levels instead of the `log` log levels.
Reduces repetition and makes it easy to implement other levels
3e04897
to
1b1eb91
Compare
I re-implemented this with smaller clean logical commits and a few changes to naming etc. |
8fd3009
to
684cd21
Compare
I don't grok why this error is showing up. If the default features are disabled, then the log and tracing modules should not be imported, and hence should not have any doc tests run. I'm guessing there's some weird edge-case for this that I'm missing the rationale for right now. Any ideas?
|
684cd21
to
8caa1b8
Compare
ACK on the doc tests. Will take a look at these tomorrow / in a couple of days. |
src/lib.rs
Outdated
} | ||
} | ||
|
||
impl fmt::Display for Filter { |
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.
Why do we have a Display
impl?
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.
Verbosity
had a Display
impl, which previously displayed the int value. In the associated type approach, Filter
needed to be pub
, so this kinda made sense, but in the crate specific methods approach it can be an implementation detail instead and so just making Verbosity's Display impl is the right approach.
src/lib.rs
Outdated
pub trait LogLevel { | ||
type Level; | ||
type LevelFilter; |
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 associated types used
With Filter
, we shouldn't need any of this
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.
It was either use associated types, or create crate specific methods (e.g. log_level
, tracing_level
). I think the specific methods are a much simpler approach.
- Change from using associated types and type constraints to a simpler approach using crate specific methods that return log and tracing types.
7d80f10
to
6c0fef9
Compare
This PR subsumes #123 as it's simpler to just do that with the macroed impl. I'm guessing that you probably would prefer the commits reordered to go straight to the multiple methods approach here? |
Conditionally present trait methods on a non-sealed trait is an improper use of features because a feature can be enabled in another crate while I implement only the part of the trait I use. It could be argued that this crate isn't expected to be used in that way because this is for end-applications. However, a workspace could have a mixture of applications and a I had been under the assumption that the trait would return our custom filter type, making it independent of any of the logging interfaces, and not needing macros. I would also prefer to handle these concerns in separate APis rather than merging them. |
Makes sense. I'll change that so that
The macros aren't necessary, they just reduce the need for duplicate code to be written.
Can you clarify this - I'm not sure if by "separate APIs" you're agreeing with what I wrote above about having methods on |
- Expose the `Filter` type and use that instead of crate specific names. - Make Verbosity::filter() public, which allows just using `verbosity.filter().into()` in places that that makes sense
Sorry, I meant "separate PRs". |
Also, please cleanup the commit history for how you'd like it reviewed and merged. I know each maintainer on this is different but I find it difficult to review a PR when the commits go in different directions. |
Moves the crate specific `impl Verbosity` blocks to the module rather than feature flagging each method Simplifies the tests so that the tests for which Filter is returned is in lib.rs rather than repeated, while the crate specific modules just check that the right conversion happens. Adds a derived Default impl to each of the LogLevel impls so that `Verbosity::default()` usefully compiles
Yep - will do. Are you happy for me to do that once we've worked out the exact direction this ends up in? |
fn default() -> Option<Level> { | ||
Some(Level::Error) | ||
} | ||
macro_rules! def_log_levels { |
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.
This saves about 40 lines of repetitive code. It's not strictly necessary, but I think that's a reasonable thing.
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.
My bar for the use of Macros is high and I don't think this meets it.
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.
My threshold for this is a bit lower than yours. IMO, if a macro save a reasonable amount of code that I'll have to read / maintain without adding too much complexity then it's worth including. This is because they make things that look similar actually be similar. Usually that's somewhere around 5 repetitions of 3 things (e.g. struct definition, associated derives, implementing a trait hits my threshold pretty niicely).
I'm happy to go with your threshold here, though I'd suggest giving some future thought about whether that could do with a slight adjustment. If not, no big deal :)
The other PR is pretty close to being merged, let's finish that up. |
Rationale: #121 (comment)