sketching/
lib.rs

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
21/// Start up the logging for test mode.
22pub fn test_init() {
23    let filter = EnvFilter::builder()
24        // Skipping trace on tests by default saves a *TON* of ram.
25        .with_default_directive(LevelFilter::INFO.into())
26        .from_env_lossy()
27        // escargot builds cargo packages while we integration test and is SUPER noisy.
28        .add_directive(
29            "escargot=ERROR"
30                .parse()
31                .expect("failed to generate log filter"),
32        )
33        // hyper's very noisy in debug mode with connectivity-related things that we only need in extreme cases.
34        .add_directive("hyper=INFO".parse().expect("failed to generate log filter"));
35
36    // start the logging!
37    let _ = tracing_subscriber::Registry::default()
38        .with(ForestLayer::new(TestCapturePrinter::new(), NoTag).with_filter(filter))
39        .try_init();
40}
41
42/// This is for tagging events. Currently not wired in.
43pub 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}