More Fine-Grained Verbosity Settings #229

Closed
opened 2017-09-29 14:19:05 -05:00 by cramertj · 20 comments
cramertj commented 2017-09-29 14:19:05 -05:00 (Migrated from github.com)

Currently, log levels are represented by a LogLevel enum:

pub enum LogLevel {
    Error,
    Warn,
    Info,
    Debug,
    Trace,
}

In my experience, five log levels is enough for most use cases. However, I don't see a reason why log should limit the user to this finite set. Consider adding a custom-verbosity variant that includes an integer specifying the log level:

pub enum LogLevel {
    Error,
    Warn,
    Info,
    Debug,
    Trace,
    CustomVerbosity(u8), // bikeshed away on the name :)
}

Apologies if I missed an existing issue or conversation around this!

Currently, log levels are represented by a `LogLevel` enum: ```rust pub enum LogLevel { Error, Warn, Info, Debug, Trace, } ``` In my experience, five log levels is enough for most use cases. However, I don't see a reason why `log` should limit the user to this finite set. Consider adding a custom-verbosity variant that includes an integer specifying the log level: ```rust pub enum LogLevel { Error, Warn, Info, Debug, Trace, CustomVerbosity(u8), // bikeshed away on the name :) } ``` Apologies if I missed an existing issue or conversation around this!
sfackler commented 2017-09-29 14:28:17 -05:00 (Migrated from github.com)

What would CustomVerbosity(4) mean, and how would it compare to, say Info?

What would `CustomVerbosity(4)` mean, and how would it compare to, say `Info`?
cramertj commented 2017-09-29 15:01:01 -05:00 (Migrated from github.com)

I'm not quite sure of the best semantics. It seems like CustomVerbosity is really just a more fine-grained Info. Perhaps rank them something like this: Trace > Debug > Info > CustomInfo(255) > CustomInfo(0) > Warn > Error.

I'm not quite sure of the best semantics. It seems like `CustomVerbosity` is really just a more fine-grained `Info`. Perhaps rank them something like this: Trace > Debug > Info > CustomInfo(255) > CustomInfo(0) > Warn > Error.
sfackler commented 2017-09-30 23:11:23 -05:00 (Migrated from github.com)

That ordering doesn't seem super obvious to me at least. Do any other logging frameworks in other languages do this kind of thing? I'm not familiar with any that do personally.

Filtering is traditionally done based off of the modules you care about, not turning on log levels 57 and up. Trying to maintain a reasonable ordering of log verbosity/priority with 261 levels seems like it would be pretty hard in a large codebase.

That ordering doesn't seem super obvious to me at least. Do any other logging frameworks in other languages do this kind of thing? I'm not familiar with any that do personally. Filtering is traditionally done based off of the modules you care about, not turning on log levels 57 and up. Trying to maintain a reasonable ordering of log verbosity/priority with 261 levels seems like it would be pretty hard in a large codebase.
cramertj commented 2017-10-01 12:04:26 -05:00 (Migrated from github.com)

Google glog lets you set a custom level using V (for verbosity).

Google [glog](https://github.com/golang/glog) lets you set a custom level using `V` (for verbosity).
cramertj commented 2017-10-01 12:05:59 -05:00 (Migrated from github.com)

In practice, it's usually less that you have 57 levels, and more that you have three or four different levels of "Info"-type logs.

In practice, it's usually less that you have 57 levels, and more that you have three or four different levels of "Info"-type logs.
sfackler commented 2017-10-01 14:24:51 -05:00 (Migrated from github.com)

Glog's setup seems a bit different than this, though. The verbosity seems orthogonal to the level there, right?

Glog's setup seems a bit different than this, though. The verbosity seems orthogonal to the level there, right?
sfackler commented 2017-10-01 14:30:44 -05:00 (Migrated from github.com)

Oh nevermind, I misread that.

Oh nevermind, I misread that.
sfackler commented 2017-10-01 14:34:15 -05:00 (Migrated from github.com)

In glog's case, there are no verbosity levels above INFO, which is where the V stuff comes in. Here, we have Debug and Trace. If anything, it seems like the V equivalent in this library would be even more verbose than trace, right?

In glog's case, there are no verbosity levels above INFO, which is where the V stuff comes in. Here, we have Debug and Trace. If anything, it seems like the V equivalent in this library would be even more verbose than trace, right?
cramertj commented 2017-10-01 15:47:42 -05:00 (Migrated from github.com)

Yeah, I suppose you could also organize it that way.

Yeah, I suppose you could also organize it that way.
sfackler commented 2017-10-01 16:25:18 -05:00 (Migrated from github.com)

The way this would work is probably something like this:

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Level(u8);

impl Level {
    pub const ERROR: Level = Level(1);
    pub const WARN: Level = Level(2);
    pub const INFO: Level = Level(3);
    pub const DEBUG: Level = Level(4);
    pub const TRACE: Level = Level(5);

    pub fn custom(level: u8) -> Level {
        assert!(level > 5);
        Level(level)
    }
}

I'm not totally sold that this is a good idea, though. Logging libraries need to decide how they want to display and consume custom levels. Library authors now need to go from figuring out which of 5 levels is appropriate for an individual message to which of 255 is appropriate.

The way this would work is probably something like this: ```rust #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Level(u8); impl Level { pub const ERROR: Level = Level(1); pub const WARN: Level = Level(2); pub const INFO: Level = Level(3); pub const DEBUG: Level = Level(4); pub const TRACE: Level = Level(5); pub fn custom(level: u8) -> Level { assert!(level > 5); Level(level) } } ``` I'm not totally sold that this is a good idea, though. Logging libraries need to decide how they want to display and consume custom levels. Library authors now need to go from figuring out which of 5 levels is appropriate for an individual message to which of 255 is appropriate.
cramertj commented 2017-10-01 19:09:33 -05:00 (Migrated from github.com)

My expectation would be that library authors would create their own level constants, which they could use to give more specific semantic meaning to the levels.

My expectation would be that library authors would create their own level constants, which they could use to give more specific semantic meaning to the levels.
sfackler commented 2017-10-01 19:32:05 -05:00 (Migrated from github.com)

But how many new levels will people actually need in practice? It's already super uncommon in my experience to ever turn on trace-level logging, and that only needs to happen when something really weird is going on. For example, Hyper's trace logging helped diagnose a protocol bug since it dumped a ton of information about its state and the data coming in off the wire.

Do you have an example of a library that needs even more levels of verbosity than what trace would give you?

But how many new levels will people actually need in practice? It's already super uncommon in my experience to ever turn on trace-level logging, and that only needs to happen when something really weird is going on. For example, Hyper's trace logging helped diagnose a protocol bug since it dumped a ton of information about its state and the data coming in off the wire. Do you have an example of a library that needs even more levels of verbosity than what trace would give you?
cramertj commented 2017-10-05 14:32:19 -05:00 (Migrated from github.com)

@sfackler Not that I can recall, no.

@sfackler Not that I can recall, no.
sfackler commented 2017-10-12 22:27:55 -05:00 (Migrated from github.com)

In the absence of a more concrete use case, I think we'll keep things as-is for the 0.4 release.

In the absence of a more concrete use case, I think we'll keep things as-is for the 0.4 release.
cramertj commented 2017-10-13 01:12:04 -05:00 (Migrated from github.com)

Okay! That seems fine to me. I still think it would be interesting to explore a design like the one you suggested above, since it seems more extensible to me, and I don't see any real downsides. However, I agree with you that it does seem like a bit of a solution in need of a problem. 😄

Okay! That seems fine to me. I still think it would be interesting to explore a design like the one [you suggested above](https://github.com/rust-lang-nursery/log/issues/229#issuecomment-333407924), since it seems more extensible to me, and I don't see any real downsides. However, I agree with you that it does seem like a bit of a solution in need of a problem. :smile:
sfackler commented 2017-10-13 12:31:18 -05:00 (Migrated from github.com)

There is a real downside for that approach - you can no longer exhaustively match on the level.

There is a real downside for that approach - you can no longer exhaustively match on the level.
cramertj commented 2017-10-13 13:56:39 -05:00 (Migrated from github.com)

@sfackler Yeah, that seems good to me-- it seems like what you'd usually want is to work with things above or below a certain level, not implement specific behaviors for each individual level. I could be wrong, though.

@sfackler Yeah, that seems good to me-- it seems like what you'd usually want is to work with things above or below a certain level, not implement specific behaviors for each individual level. I could be wrong, though.
sfackler commented 2017-10-13 14:41:47 -05:00 (Migrated from github.com)

You need specific behavior if you e.g. want to translate a log level to a name.

You need specific behavior if you e.g. want to translate a log level to a name.
cramertj commented 2017-10-13 15:41:22 -05:00 (Migrated from github.com)

Sure, but you could just match on the cases that you know, and set the rest to "CUSTOM" or similar.

Sure, but you could just match on the cases that you know, and set the rest to "CUSTOM" or similar.
cramertj commented 2017-10-13 15:42:20 -05:00 (Migrated from github.com)

It might even be worthwhile to let crates specify their own translators for a given target, so that their custom levels show up correctly.

It might even be worthwhile to let crates specify their own translators for a given target, so that their custom levels show up correctly.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-rust-lang/log#229
No description provided.