drive_abci/logging/
level.rs1use crate::logging::error::Error;
2use derive_more::Display;
3use serde::de::Visitor;
4use serde::{de, Deserialize, Deserializer, Serialize};
5use std::fmt;
6use tracing_subscriber::EnvFilter;
7
8#[derive(Serialize, Debug, Clone, Default, Display)]
10#[serde(rename_all = "camelCase")]
11pub enum LogLevel {
12 Silent,
14 Custom(String),
16 Error,
18 Warn,
20 #[default]
22 Info,
23 Debug,
25 Trace,
27 Paranoid,
29}
30
31impl From<&str> for LogLevel {
33 fn from(value: &str) -> Self {
34 match value {
35 "silent" => LogLevel::Silent,
36 "error" => LogLevel::Error,
37 "warn" => LogLevel::Warn,
38 "info" => LogLevel::Info,
39 "debug" => LogLevel::Debug,
40 "trace" => LogLevel::Trace,
41 "paranoid" => LogLevel::Paranoid,
42 configuration => LogLevel::Custom(configuration.to_string()),
43 }
44 }
45}
46
47struct LogLevelPresetVisitor;
48
49impl Visitor<'_> for LogLevelPresetVisitor {
50 type Value = LogLevel;
51
52 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
53 formatter.write_str("silent, error, warn, info, debug, trace, paranoid or custom level using RUST_LOG format")
54 }
55
56 fn visit_str<E>(self, value: &str) -> Result<LogLevel, E>
57 where
58 E: de::Error,
59 {
60 let level = LogLevel::from(value);
61
62 Ok(level)
63 }
64}
65
66impl<'de> Deserialize<'de> for LogLevel {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: Deserializer<'de>,
70 {
71 deserializer.deserialize_str(LogLevelPresetVisitor)
72 }
73}
74
75impl TryFrom<u8> for LogLevel {
77 type Error = Error;
78
79 fn try_from(value: u8) -> Result<Self, <LogLevel as TryFrom<u8>>::Error> {
80 let level = match value {
81 0 => LogLevel::Info,
82 1 => LogLevel::Debug,
83 2 => LogLevel::Trace,
84 3 => LogLevel::Paranoid,
85 verbosity => return Err(Error::InvalidVerbosityLevel(verbosity)),
86 };
87
88 Ok(level)
89 }
90}
91
92impl TryFrom<&LogLevel> for EnvFilter {
93 type Error = Error;
94
95 fn try_from(value: &LogLevel) -> Result<Self, Error> {
96 let env_filter = match value {
97 LogLevel::Silent => EnvFilter::default(),
98 LogLevel::Custom(configuration) => {
99 EnvFilter::try_new(configuration).map_err(Error::InvalidLogSpecification)?
100 }
101 LogLevel::Error => {
102 EnvFilter::try_new("error").expect("should be a valid log specification")
103 }
104 LogLevel::Warn => {
105 EnvFilter::try_new("error,tenderdash_abci=warn,drive_abci=warn,drive=warn,dpp=warn")
106 .expect("should be a valid log specification")
107 }
108 LogLevel::Info => {
109 EnvFilter::try_new("error,tenderdash_abci=info,drive_abci=info,drive=info,dpp=info")
110 .expect("should be a valid log specification")
111 }
112 LogLevel::Debug => EnvFilter::try_new(
113 "info,tenderdash_abci=debug,drive_abci=debug,drive=debug,dpp=debug,dapi_grpc=debug,tonic=debug",
114 )
115 .expect("should be a valid log specification"),
116 LogLevel::Trace => EnvFilter::try_new(
117 "debug,tenderdash_abci=trace,drive_abci=trace,drive=trace,drive_grovedb_operations=off,dpp=trace",
118 )
119 .expect("should be a valid log specification"),
120 LogLevel::Paranoid => {
121 EnvFilter::try_new("trace").expect("should be a valid log specification")
122 }
123 };
124
125 Ok(env_filter)
126 }
127}