Skip to content

Commit f289050

Browse files
committed
chore: improve Level and update changelog
1 parent deaa359 commit f289050

File tree

2 files changed

+92
-4
lines changed

2 files changed

+92
-4
lines changed

metrics/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [Unreleased] - ReleaseDate
1010

11+
### Added
12+
13+
- Added a section to the crate-level documentation about `Metadata` and how it's used.
14+
- Derived `Copy`, `PartialOrd` and `Ord` for `Metadata` to allow for cheap copies and the ability to compare levels for
15+
filtering purposes.
16+
- Added `TryFrom<&str>` for `Level` to allow parsing levels from strings.
17+
- Updated the documentation for `Metadata` to better explain how it's used.
18+
1119
## [0.24.0] - 2024-10-12
1220

1321
### Added

metrics/src/metadata.rs

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
/// Describes the level of verbosity of a metric event.
2-
#[derive(Debug, Clone, PartialEq, Eq)]
1+
/// Verbosity of a metric.
2+
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)]
33
pub struct Level(LevelInner);
44

55
impl Level {
@@ -19,7 +19,22 @@ impl Level {
1919
pub const ERROR: Self = Self(LevelInner::Error);
2020
}
2121

22-
#[derive(Debug, Clone, PartialEq, Eq)]
22+
impl std::convert::TryFrom<&str> for Level {
23+
type Error = String;
24+
25+
fn try_from(value: &str) -> Result<Self, Self::Error> {
26+
match value.trim() {
27+
"trace" | "TRACE" => Ok(Level::TRACE),
28+
"debug" | "DEBUG" => Ok(Level::DEBUG),
29+
"info" | "INFO" => Ok(Level::INFO),
30+
"warn" | "WARN" => Ok(Level::WARN),
31+
"error" | "ERROR" => Ok(Level::ERROR),
32+
unknown => Err(format!("unknown log level: {} (expected one of 'trace', 'debug', 'info', 'warn', or 'error')", unknown)),
33+
}
34+
}
35+
}
36+
37+
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
2338
enum LevelInner {
2439
Trace = 0,
2540
Debug = 1,
@@ -44,7 +59,7 @@ enum LevelInner {
4459
///
4560
/// Metadata usage is exporter-specific, and may be ignored entirely. See the documentation of the specific exporter
4661
/// being used for more information.
47-
#[derive(Debug, Clone, PartialEq, Eq)]
62+
#[derive(Clone, Debug, Eq, PartialEq)]
4863
pub struct Metadata<'a> {
4964
target: &'a str,
5065
level: Level,
@@ -77,3 +92,68 @@ impl<'a> Metadata<'a> {
7792
self.module_path
7893
}
7994
}
95+
96+
#[cfg(test)]
97+
mod tests {
98+
use std::convert::TryFrom as _;
99+
100+
use super::*;
101+
102+
#[test]
103+
fn level_try_from_valid() {
104+
let cases = &[
105+
("trace", Level::TRACE), ("TRACE", Level::TRACE),
106+
("debug", Level::DEBUG), ("DEBUG", Level::DEBUG),
107+
("info", Level::INFO), ("INFO", Level::INFO),
108+
("warn", Level::WARN), ("WARN", Level::WARN),
109+
("error", Level::ERROR), ("ERROR", Level::ERROR),
110+
];
111+
112+
for (input, expected) in cases {
113+
assert_eq!(Level::try_from(*input).unwrap(), *expected);
114+
115+
// Now try with some whitespace on either end.
116+
let input_whitespace = format!(" {} ", input);
117+
assert_eq!(Level::try_from(&*input_whitespace).unwrap(), *expected);
118+
}
119+
}
120+
121+
#[test]
122+
fn level_try_from_invalid() {
123+
let cases = &["", "foo", "bar", "baz", "qux", "quux"];
124+
125+
for input in cases {
126+
assert!(Level::try_from(*input).is_err());
127+
}
128+
}
129+
130+
#[test]
131+
fn level_ordering() {
132+
// A few manual comparisons because it makes me feel better:
133+
assert!(Level::TRACE < Level::DEBUG);
134+
assert!(Level::DEBUG < Level::INFO);
135+
assert!(Level::ERROR > Level::DEBUG);
136+
assert!(Level::WARN == Level::WARN);
137+
138+
// Now check each level programmatically.
139+
let levels = &[
140+
Level::TRACE, Level::DEBUG, Level::INFO, Level::WARN, Level::ERROR,
141+
];
142+
143+
for i in 0..levels.len() {
144+
let current_level = levels[i];
145+
let lower_levels = &levels[..i];
146+
let higher_levels = &levels[i + 1..];
147+
148+
for lower_level in lower_levels {
149+
assert!(current_level > *lower_level);
150+
assert!(*lower_level < current_level);
151+
}
152+
153+
for higher_level in higher_levels {
154+
assert!(current_level < *higher_level);
155+
assert!(*higher_level > current_level);
156+
}
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)