ntp_daemon/config/
format.rs

1use std::str::FromStr;
2
3use serde::Deserialize;
4use thiserror::Error;
5use tracing::Subscriber;
6use tracing_subscriber::{
7    field::RecordFields,
8    fmt::{
9        format::{
10            Compact, DefaultFields, Format, Full, Json, JsonFields, Pretty, PrettyFields, Writer,
11        },
12        FormatEvent, FormatFields,
13    },
14    registry::LookupSpan,
15};
16
17#[derive(Debug, Clone)]
18pub enum LogFormat {
19    Full(Format<Full>),
20    Compact(Format<Compact>),
21    Pretty(Format<Pretty>),
22    Json(Format<Json>),
23}
24
25impl LogFormat {
26    pub fn get_format_fields(&self) -> LogFormatFields {
27        match self {
28            LogFormat::Json(_) => LogFormatFields::Json(JsonFields::default()),
29            LogFormat::Pretty(_) => LogFormatFields::Pretty(PrettyFields::default()),
30            _ => LogFormatFields::Default(DefaultFields::default()),
31        }
32    }
33}
34
35impl<'de> Deserialize<'de> for LogFormat {
36    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
37    where
38        D: serde::Deserializer<'de>,
39    {
40        let data: String = Deserialize::deserialize(deserializer)?;
41        LogFormat::from_str(&data).map_err(serde::de::Error::custom)
42    }
43}
44
45impl Default for LogFormat {
46    fn default() -> Self {
47        LogFormat::Full(Default::default())
48    }
49}
50
51#[derive(Error, Debug)]
52#[error("Invalid log format, must be one of full, compact, pretty, json")]
53pub struct InvalidLogFormat;
54
55impl FromStr for LogFormat {
56    type Err = InvalidLogFormat;
57
58    fn from_str(s: &str) -> Result<Self, Self::Err> {
59        match s {
60            "full" => Ok(LogFormat::Full(Default::default())),
61            "compact" => Ok(LogFormat::Compact(Format::default().compact())),
62            "pretty" => Ok(LogFormat::Pretty(Format::default().pretty())),
63            "json" => Ok(LogFormat::Json(Format::default().json().with_ansi(false))),
64            _ => Err(InvalidLogFormat),
65        }
66    }
67}
68
69impl<S, N> FormatEvent<S, N> for LogFormat
70where
71    S: Subscriber + for<'a> LookupSpan<'a>,
72    N: for<'a> FormatFields<'a> + 'static,
73{
74    fn format_event(
75        &self,
76        ctx: &tracing_subscriber::fmt::FmtContext<'_, S, N>,
77        writer: tracing_subscriber::fmt::format::Writer<'_>,
78        event: &tracing::Event<'_>,
79    ) -> std::fmt::Result {
80        match self {
81            LogFormat::Full(f) => f.format_event(ctx, writer, event),
82            LogFormat::Compact(f) => f.format_event(ctx, writer, event),
83            LogFormat::Pretty(f) => f.format_event(ctx, writer, event),
84            LogFormat::Json(f) => f.format_event(ctx, writer, event),
85        }
86    }
87}
88
89pub enum LogFormatFields {
90    Json(JsonFields),
91    Pretty(PrettyFields),
92    Default(DefaultFields),
93}
94
95impl<'a> FormatFields<'a> for LogFormatFields {
96    fn format_fields<R: RecordFields>(&self, writer: Writer<'a>, fields: R) -> std::fmt::Result {
97        match self {
98            LogFormatFields::Json(f) => f.format_fields(writer, fields),
99            LogFormatFields::Pretty(f) => f.format_fields(writer, fields),
100            LogFormatFields::Default(f) => f.format_fields(writer, fields),
101        }
102    }
103}