pub mod format;
pub mod time;
pub mod writer;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use writer::Guard;
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub struct Subscriber {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub format: Option<Format>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub writer: Option<Writer>,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LevelFilter {
Error,
Warn,
#[default]
Info,
Debug,
Trace,
}
impl From<LevelFilter> for tracing_core::LevelFilter {
fn from(value: LevelFilter) -> Self {
match value {
LevelFilter::Error => Self::ERROR,
LevelFilter::Warn => Self::WARN,
LevelFilter::Info => Self::INFO,
LevelFilter::Debug => Self::DEBUG,
LevelFilter::Trace => Self::TRACE,
}
}
}
pub type SubscriberBuilder<
N = format::FormatFields,
E = format::FormatEvent,
F = tracing_core::LevelFilter,
W = writer::MakeWriter,
> = tracing_subscriber::fmt::SubscriberBuilder<N, E, F, W>;
impl Subscriber {
pub fn builder(self) -> Result<(SubscriberBuilder, Guard), writer::Error> {
let Self { format, writer } = self;
let writer = writer.unwrap_or_default();
let format = format.unwrap_or_default();
let (writer, guard) = writer::MakeWriter::new(writer)?;
let builder = tracing_subscriber::fmt()
.fmt_fields(format::FormatFields::from(
format.formatter.clone().unwrap_or_default(),
))
.event_format(format::FormatEvent::from(format))
.with_writer(writer);
Ok((builder, guard))
}
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub struct Format {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ansi: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub target: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub level: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thread_ids: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thread_names: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub line_number: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub formatter: Option<Formatter>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timer: Option<Timer>,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Formatter {
#[default]
Full,
Compact,
Pretty,
Json(Option<Json>),
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub struct Json {
#[serde(default, skip_serializing_if = "Option::is_none")]
flatten_event: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
current_span: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
span_list: Option<bool>,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Timer {
None,
Local(#[serde(default, skip_serializing_if = "Option::is_none")] Option<String>),
Utc(#[serde(default, skip_serializing_if = "Option::is_none")] Option<String>),
#[default]
System,
Uptime,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Writer {
Null,
#[default]
Stdout,
Stderr,
File {
path: PathBuf,
behaviour: FileOpenBehaviour,
#[serde(default, skip_serializing_if = "Option::is_none")]
non_blocking: Option<NonBlocking>,
},
Rolling {
directory: PathBuf,
rolling: Option<Rolling>,
#[serde(default, skip_serializing_if = "Option::is_none")]
non_blocking: Option<NonBlocking>,
},
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Rotation {
Minutely,
Hourly,
Daily,
#[default]
Never,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub struct Rolling {
#[serde(default, skip_serializing_if = "Option::is_none")]
limit: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
prefix: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
suffix: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
rotation: Option<Rotation>,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum BackpressureBehaviour {
Drop,
Block,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum FileOpenBehaviour {
Truncate,
Append,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub struct NonBlocking {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub buffer_length: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub behaviour: Option<BackpressureBehaviour>,
}