1#![deny(warnings)]
2#![warn(unused_extern_crates)]
3#![allow(non_snake_case)]
4use std::fmt::Display;
5use std::str::FromStr;
6
7use num_enum::{IntoPrimitive, TryFromPrimitive};
8use serde::Deserialize;
9use tracing_forest::printer::TestCapturePrinter;
10use tracing_forest::tag::NoTag;
11use tracing_forest::util::*;
12use tracing_forest::Tag;
13use tracing_subscriber::filter::Directive;
14use tracing_subscriber::prelude::*;
15
16pub mod macros;
17pub mod otel;
18
19pub use {tracing, tracing_forest, tracing_subscriber};
20
21pub fn test_init() {
23 let filter = EnvFilter::builder()
24 .with_default_directive(LevelFilter::INFO.into())
26 .from_env_lossy()
27 .add_directive(
29 "escargot=ERROR"
30 .parse()
31 .expect("failed to generate log filter"),
32 )
33 .add_directive("hyper=INFO".parse().expect("failed to generate log filter"));
35
36 let _ = tracing_subscriber::Registry::default()
38 .with(ForestLayer::new(TestCapturePrinter::new(), NoTag).with_filter(filter))
39 .try_init();
40}
41
42pub fn event_tagger(_event: &Event) -> Option<Tag> {
44 None
45}
46
47#[derive(Debug, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
48#[repr(u64)]
49pub enum EventTag {
50 AdminDebug,
51 AdminError,
52 AdminWarn,
53 AdminInfo,
54 RequestError,
55 RequestWarn,
56 RequestInfo,
57 RequestTrace,
58 SecurityCritical,
59 SecurityDebug,
60 SecurityInfo,
61 SecurityAccess,
62 SecurityError,
63 FilterError,
64 FilterWarn,
65 FilterInfo,
66 FilterTrace,
67 PerfTrace,
68}
69
70impl EventTag {
71 pub fn pretty(self) -> &'static str {
72 match self {
73 EventTag::AdminDebug => "admin.debug",
74 EventTag::AdminError => "admin.error",
75 EventTag::AdminWarn => "admin.warn",
76 EventTag::AdminInfo => "admin.info",
77 EventTag::RequestError => "request.error",
78 EventTag::RequestWarn => "request.warn",
79 EventTag::RequestInfo => "request.info",
80 EventTag::RequestTrace => "request.trace",
81 EventTag::SecurityCritical => "security.critical",
82 EventTag::SecurityDebug => "security.debug",
83 EventTag::SecurityInfo => "security.info",
84 EventTag::SecurityAccess => "security.access",
85 EventTag::SecurityError => "security.error",
86 EventTag::FilterError => "filter.error",
87 EventTag::FilterWarn => "filter.warn",
88 EventTag::FilterInfo => "filter.info",
89 EventTag::FilterTrace => "filter.trace",
90 EventTag::PerfTrace => "perf.trace",
91 }
92 }
93
94 pub fn emoji(self) -> &'static str {
95 use EventTag::*;
96 match self {
97 AdminDebug | SecurityDebug => "🐛",
98 AdminError | FilterError | RequestError | SecurityError => "🚨",
99 AdminWarn | FilterWarn | RequestWarn => "⚠️",
100 AdminInfo | FilterInfo | RequestInfo | SecurityInfo => "ℹ️",
101 RequestTrace | FilterTrace | PerfTrace => "📍",
102 SecurityCritical => "🔐",
103 SecurityAccess => "🔓",
104 }
105 }
106}
107
108#[derive(Clone, Copy, Deserialize, Debug, Default)]
109pub enum LogLevel {
110 #[default]
111 #[serde(rename = "info")]
112 Info,
113 #[serde(rename = "debug")]
114 Debug,
115 #[serde(rename = "trace")]
116 Trace,
117}
118
119impl FromStr for LogLevel {
120 type Err = &'static str;
121
122 fn from_str(s: &str) -> Result<Self, Self::Err> {
123 match s {
124 "info" => Ok(LogLevel::Info),
125 "debug" => Ok(LogLevel::Debug),
126 "trace" => Ok(LogLevel::Trace),
127 _ => Err("Must be one of info, debug, trace"),
128 }
129 }
130}
131
132impl Display for LogLevel {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 f.write_str(match self {
135 LogLevel::Info => "info",
136 LogLevel::Debug => "debug",
137 LogLevel::Trace => "trace",
138 })
139 }
140}
141
142impl From<LogLevel> for Directive {
143 fn from(value: LogLevel) -> Self {
144 match value {
145 LogLevel::Info => Directive::from(Level::INFO),
146 LogLevel::Debug => Directive::from(Level::DEBUG),
147 LogLevel::Trace => Directive::from(Level::TRACE),
148 }
149 }
150}