Exercise: Logger Trait
Let’s design a simple logging utility, using a trait Logger with a log method. Code which might log its progress can then take an &impl Logger. In testing, this might put messages in the test logfile, while in a production build it would send messages to a log server.
However, the StdoutLogger given below logs all messages, regardless of verbosity. Your task is to write a VerbosityFilter type that will ignore messages above a maximum verbosity.
This is a common pattern: a struct wrapping a trait implementation and implementing that same trait, adding behavior in the process. What other kinds of wrappers might be useful in a logging utility?
1. ```
pub trait Logger {
```
2. ```
/// Log a message at the given verbosity level.
```
3. ```
fn log(&self, verbosity: u8, message: &str);
```
4. ```
}
```
6. ```
struct StdoutLogger;
```
8. ```
impl Logger for StdoutLogger {
```
9. ```
fn log(&self, verbosity: u8, message: &str) {
```
10. ```
println!("verbosity={verbosity}: {message}");
```
11. ```
}
```
12. ```
}
```
14. ```
// TODO: Define and implement `VerbosityFilter`.
```
16. ```
fn main() {
```
17. ```
let logger = VerbosityFilter { max_verbosity: 3, inner: StdoutLogger };
```
18. ```
logger.log(5, "FYI");
```
19. ```
logger.log(2, "Uhoh");
```
20. ```
}
```
