1use std::{fmt::Display, path::PathBuf};
2
3use serde::{Deserialize, Deserializer, Serialize};
4use tracing_subscriber::{fmt::writer::BoxMakeWriter, EnvFilter};
5
6#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
8#[serde(rename_all = "kebab-case")]
9pub struct Log {
10 #[serde(default)]
13 pub level: LogLevel,
14 #[serde(default)]
15 pub outputs: Vec<LogOutput>,
16 #[serde(default)]
17 pub format: LogFormat,
18}
19
20#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq)]
22#[serde(rename_all = "lowercase")]
23pub enum LogFormat {
24 #[default]
25 Pretty,
26 Json,
27}
28
29#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq)]
31#[serde(rename_all = "lowercase")]
32pub enum LogLevel {
33 Trace,
34 Debug,
35 #[default]
36 Info,
37 Warn,
38 Error,
39 Fatal,
40}
41
42impl Display for LogLevel {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 let level = match self {
45 LogLevel::Trace => "trace",
46 LogLevel::Debug => "debug",
47 LogLevel::Info => "info",
48 LogLevel::Warn => "warn",
49 LogLevel::Error => "error",
50 LogLevel::Fatal => "fatal",
51 };
52
53 write!(f, "{level}")
54 }
55}
56
57impl From<LogLevel> for EnvFilter {
58 fn from(value: LogLevel) -> Self {
59 EnvFilter::new(format!("warn,agglayer={value},pessimistic_proof={value}"))
60 }
61}
62
63#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq)]
72pub enum LogOutput {
73 #[default]
74 Stdout,
75 Stderr,
76 File(PathBuf),
77}
78
79impl<'de> Deserialize<'de> for LogOutput {
80 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81 where
82 D: Deserializer<'de>,
83 {
84 let s = String::deserialize(deserializer)?;
85 match s.as_str() {
88 "stdout" => Ok(LogOutput::Stdout),
89 "stderr" => Ok(LogOutput::Stderr),
90 _ => Ok(LogOutput::File(PathBuf::from(s))),
91 }
92 }
93}
94
95impl LogOutput {
96 pub fn as_make_writer(&self) -> BoxMakeWriter {
100 match self {
101 LogOutput::Stdout => BoxMakeWriter::new(std::io::stdout),
102 LogOutput::Stderr => BoxMakeWriter::new(std::io::stderr),
103 LogOutput::File(path) => {
104 let appender = tracing_appender::rolling::never(".", path);
105 BoxMakeWriter::new(appender)
106 }
107 }
108 }
109}