src/logger/level.rs

Lines

100.00 %

Functions

100.00 %

Regions

100.00 %

LineCountSource (jump to first uncovered line)
1
//
2
// File Name:    level.rs
3
// Directory:    src/logger
4
// Project Name: flogging
5
//
6
// Copyright (C) 2025 Bradley Willcott
7
//
8
// SPDX-License-Identifier: GPL-3.0-or-later
9
//
10
// This library (crate) is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
14
//
15
// This library (crate) is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
// GNU General Public License for more details.
19
//
20
// You should have received a copy of the GNU General Public License
21
// along with this library (crate).  If not, see <https://www.gnu.org/licenses/>.
22
//
23
24
//!
25
//! # Log Entry Level
26
//!
27
//! This module provides the enum containing the possible log entry levels.
28
//! The order in which they are listed within the enum, enables logging at that level
29
//! and at all higher levels.
30
//!
31
//! The levels in descending order are:
32
//!
33
//! - SEVERE (highest level)
34
//! - WARNING
35
//! - INFO
36
//! - CONFIG
37
//! - FINE
38
//! - FINER
39
//! - FINEST (lowest level)
40
//!
41
//! In addition there is a level **OFF** that can be used to turn off logging.
42
43
use std::{fmt, str::FromStr};
44
use strum::{EnumIter, IntoEnumIterator};
45
46
///
47
/// Log entry level setting.
48
///
49
/// Default level: INFO.
50
///
51
// #[allow(unused)]
52
#[derive(Debug, Clone, Default, PartialEq, PartialOrd, EnumIter, Copy)]
53
pub enum Level {
54
    ///
55
    /// ALL is a special level that can be used to turn on logging
56
    /// for all levels.
57
    ///
58
    ALL,
59
60
    ///
61
    /// FINEST indicates a highly detailed tracing message.
62
    ///
63
    FINEST,
64
65
    ///
66
    /// FINER indicates a fairly detailed tracing message.
67
    /// Suggest logging calls for entering, returning,
68
    /// or `Error`s, such as returned via `Result`, are traced at
69
    /// this level.
70
    ///
71
    FINER,
72
73
    ///
74
    /// FINE is a message level providing tracing information.
75
    ///
76
    /// All of FINE, FINER, and FINEST are intended for relatively
77
    /// detailed tracing. The exact meaning of the three levels will
78
    /// vary between subsystems, but in general, FINEST should be
79
    /// used for the most voluminous detailed output, FINER for somewhat
80
    /// less detailed output, and FINE for the lowest volume (and most
81
    /// important) messages.
82
    ///
83
    /// In general the FINE level should be used for information that
84
    /// will be broadly interesting to developers who do not have a
85
    /// specialized interest in the specific subsystem.
86
    ///
87
    /// FINE messages might include things like minor (recoverable)
88
    /// failures. Issues indicating potential performance problems are
89
    /// also worth logging as FINE.
90
    ///
91
    FINE,
92
93
    ///
94
    /// CONFIG is a message level for static configuration messages.
95
    ///
96
    /// CONFIG messages are intended to provide a variety of static
97
    /// configuration information, to assist in debugging problems
98
    /// that may be associated with particular configurations.
99
    ///
100
    /// For example, a CONFIG message might include the CPU type, the
101
    /// graphics depth, the GUI look-and-feel, etc.
102
    ///
103
    CONFIG,
104
105
    ///
106
    /// INFO is a message level for informational messages.
107
    ///
108
    /// Typically INFO messages will be written to the console or its
109
    /// equivalent. So the INFO level should only be used for reasonably
110
    /// significant messages that will make sense to end users and system
111
    /// administrators.
112
    ///
113
    /// \[default level]
114
    ///
115
    #[default]
116
    INFO,
117
118
    ///
119
    /// WARNING is a message level indicating a potential problem.
120
    ///
121
    /// In general WARNING messages should describe events that will be
122
    /// of interest to end users or system managers, or which indicate
123
    /// potential problems.
124
    ///
125
    WARNING,
126
127
    ///
128
    /// SEVERE is a message level indicating a serious failure.
129
    ///
130
    /// In general SEVERE messages should describe events that are of
131
    /// considerable importance and which will prevent normal program
132
    /// execution. They should be reasonably intelligible to end users
133
    /// and to system administrators.
134
    ///
135
    SEVERE,
136
137
    ///
138
    /// OFF is a special level that can be used to turn off logging.
139
    ///
140
    OFF,
141
}
142
143
impl Level {
144
    ///
145
    /// Converts a level to its string version.
146
    ///
147168
    pub const fn as_str(&self) -> &'static str {
148168
        match self {
1491
            Level::ALL => "ALL",
1507
            Level::FINEST => "FINEST",
15133
            Level::FINER => "FINER",
15213
            Level::FINE => "FINE",
15324
            Level::CONFIG => "CONFIG",
15444
            Level::INFO => "INFO",
15535
            Level::WARNING => "WARNING",
15610
            Level::SEVERE => "SEVERE",
1571
            Level::OFF => "OFF",
158
        }
159168
    }
160
}
161
162
impl fmt::Display for Level {
1635
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1645
        self.as_str().fmt(f)
1655
    }
166
}
167
168
#[allow(dead_code)]
169
#[derive(Debug)]
170
pub struct LevelError {
171
    msg: String,
172
}
173
174
impl FromStr for Level {
175
    type Err = LevelError;
176
17710
    fn from_str(s: &str) -> Result<Self, Self::Err> {
17810
        match s {
1791
            "ALL" => Ok(Level::ALL),
1801
            "FINEST" => Ok(Level::FINEST),
1811
            "FINER" => Ok(Level::FINER),
1821
            "FINE" => Ok(Level::FINE),
1831
            "CONFIG" => Ok(Level::CONFIG),
1841
            "INFO" => Ok(Level::INFO),
1851
            "WARNING" => Ok(Level::WARNING),
1861
            "SEVERE" => Ok(Level::SEVERE),
1871
            "OFF" => Ok(Level::OFF),
1881
            _ => Err(LevelError {
1891
                msg: format!("Unknown Level: {s}"),
1901
            }),
191
        }
19210
    }
193
}
194
195
#[cfg(test)]
196
mod tests {
197
    use super::*;
198
199
    #[test]
2001
    fn compare_levels() {
2011
        let log_level = Level::default();
2021
        let b = Level::FINE;
203
2041
        println!("\n|{log_level}|\n");
205
2061
        assert!(b < log_level);
2071
    }
208
209
    #[test]
2101
    fn check_conversions() {
2111
        for level in Level::iter() {
2129
            let lstr = level.as_str();
2139
            let l = Level::from_str(lstr).unwrap();
2149
            assert_eq!(level, l);
215
        }
216
2171
        assert!(Level::from_str("DEBUG").is_err());
2181
    }
219
}