1use std::fmt;
2
3pub use tracing::Level;
4
5#[derive(Debug, Clone, structopt::StructOpt, serde::Serialize, serde::Deserialize)]
6pub struct LoggingConfig {
7 #[structopt(long, default_value = "info")]
8 #[serde(with = "impl_serde_for_level")]
9 pub min_log_level: tracing::Level,
10
11 #[structopt(long)]
12 #[serde(default)]
13 pub log_target_filter: Vec<LogTargetConfig>,
14}
15
16#[derive(Debug, Clone)]
18pub struct LogTargetConfig {
19 pub path: Vec<String>,
20 pub level: tracing::Level,
21}
22
23impl std::str::FromStr for LogTargetConfig {
24 type Err = String;
25
26 fn from_str(s: &str) -> Result<Self, Self::Err> {
27 let (path, level) = s
28 .split_once('=')
29 .ok_or_else(|| "eq-sign missing".to_owned())?;
30 let level = level.parse::<tracing::Level>().map_err(|e| e.to_string())?;
31 let path = path.split("::").map(|s| s.to_owned()).collect();
32
33 let out = Self { path, level };
34 Ok(out)
35 }
36}
37
38impl fmt::Display for LogTargetConfig {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 format!("{}={}", self.path.join("*"), self.level).fmt(f)
41 }
42}
43
44mod impl_serde_for_log_target_config {
45 use super::*;
46 impl<'de> serde::Deserialize<'de> for LogTargetConfig {
47 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
48 where
49 D: serde::Deserializer<'de>,
50 {
51 use serde::de::Error as DeError;
52 String::deserialize(deserializer)?
53 .parse()
54 .map_err(D::Error::custom)
55 }
56 }
57
58 impl serde::Serialize for LogTargetConfig {
59 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: serde::Serializer,
62 {
63 self.to_string().serialize(serializer)
64 }
65 }
66}
67
68mod impl_serde_for_level {
69 use serde::de::Error as DeError;
70 use serde::{Deserialize, Deserializer, Serialize, Serializer};
71
72 pub(super) fn serialize<S>(value: &tracing::Level, ser: S) -> Result<S::Ok, S::Error>
73 where
74 S: Serializer,
75 {
76 value.to_string().serialize(ser)
77 }
78
79 pub(super) fn deserialize<'de, D>(deser: D) -> Result<tracing::Level, D::Error>
80 where
81 D: Deserializer<'de>,
82 {
83 String::deserialize(deser)?
84 .parse::<tracing::Level>()
85 .map_err(D::Error::custom)
86 }
87}