aptos_logger_link/
metadata.rs

1// Copyright (c) Aptos
2// SPDX-License-Identifier: Apache-2.0
3
4use serde::{Deserialize, Serialize};
5use std::{fmt, str::FromStr};
6
7/// Associated metadata with every log to identify what kind of log and where it came from
8#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
9pub struct Metadata {
10    /// The level of verbosity of the event
11    #[serde(skip_serializing)]
12    level: Level,
13
14    /// The part of the system where the event occurred
15    package: &'static str,
16
17    /// The name of the Rust module where the event occurred
18    // do not emit this field into the json logs since source.location is already more useful
19    #[serde(skip)]
20    module_path: &'static str,
21
22    /// The source code file path and line number together as 'file_path:line'
23    file: &'static str,
24}
25
26impl Metadata {
27    pub const fn new(
28        level: Level,
29        target: &'static str,
30        module_path: &'static str,
31        source_path: &'static str,
32    ) -> Self {
33        Self {
34            level,
35            package: target,
36            module_path,
37            file: source_path,
38        }
39    }
40
41    pub fn enabled(&self) -> bool {
42        crate::logger::enabled(self)
43    }
44
45    pub fn level(&self) -> Level {
46        self.level
47    }
48
49    pub fn target(&self) -> &'static str {
50        self.package
51    }
52
53    pub fn module_path(&self) -> &'static str {
54        self.module_path
55    }
56
57    pub fn source_path(&self) -> &'static str {
58        self.file
59    }
60}
61
62static LOG_LEVEL_NAMES: &[&str] = &["ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
63
64/// Logging levels, used for stratifying logs, and disabling less important ones for performance reasons
65#[repr(usize)]
66#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Serialize, Deserialize)]
67#[serde(rename_all = "UPPERCASE")]
68pub enum Level {
69    /// The "error" level.
70    ///
71    /// Designates very serious errors.
72    Error = 0,
73    /// The "warn" level.
74    ///
75    /// Designates hazardous situations.
76    Warn,
77    /// The "info" level.
78    ///
79    /// Designates useful information.
80    Info,
81    /// The "debug" level.
82    ///
83    /// Designates lower priority information.
84    Debug,
85    /// The "trace" level.
86    ///
87    /// Designates very low priority, often extremely verbose, information.
88    Trace,
89}
90
91impl Level {
92    fn from_usize(idx: usize) -> Option<Self> {
93        let lvl = match idx {
94            0 => Level::Error,
95            1 => Level::Warn,
96            2 => Level::Info,
97            3 => Level::Debug,
98            4 => Level::Trace,
99            _ => return None,
100        };
101
102        Some(lvl)
103    }
104}
105
106/// An error given when no `Level` matches the inputted string
107#[derive(Debug)]
108pub struct LevelParseError;
109
110impl FromStr for Level {
111    type Err = LevelParseError;
112    fn from_str(level: &str) -> Result<Level, Self::Err> {
113        LOG_LEVEL_NAMES
114            .iter()
115            .position(|name| name.eq_ignore_ascii_case(level))
116            .map(|idx| Level::from_usize(idx).unwrap())
117            .ok_or(LevelParseError)
118    }
119}
120
121impl fmt::Display for Level {
122    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
123        fmt.pad(LOG_LEVEL_NAMES[*self as usize])
124    }
125}