-
-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathlog.rs
More file actions
120 lines (102 loc) · 4.2 KB
/
Copy pathlog.rs
File metadata and controls
120 lines (102 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::constants::{ACCESS_LOG_FILE, SYSTEM_LOG_FILE};
use rpxy_lib::log_event_names;
use std::{str::FromStr, sync::OnceLock};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{filter::filter_fn, fmt, prelude::*};
#[allow(unused)]
pub use tracing::{debug, error, info, warn};
/// Initialize the logger with the RUST_LOG environment variable.
pub fn init_logger(log_dir_path: Option<&str>) {
let level = std::env::var("RUST_LOG")
.ok()
.and_then(|s| tracing::Level::from_str(&s).ok())
.unwrap_or(tracing::Level::INFO);
match log_dir_path {
None => init_stdio_logger(level),
Some(path) => init_file_logger(level, path),
}
}
static ACCESS_LOG_GUARD: OnceLock<WorkerGuard> = OnceLock::new();
static SYSTEM_LOG_GUARD: OnceLock<WorkerGuard> = OnceLock::new();
/// file logging
fn init_file_logger(level: tracing::Level, log_dir_path: &str) {
println!("Activate logging to files: {}", log_dir_path);
let log_dir = std::path::Path::new(log_dir_path);
if !log_dir.exists() {
println!("Directory does not exist, creating: {}", log_dir.display());
std::fs::create_dir_all(log_dir).expect("Failed to create log directory");
}
let access_log_path = log_dir.join(ACCESS_LOG_FILE);
let system_log_path = log_dir.join(SYSTEM_LOG_FILE);
println!("Access log: {}", access_log_path.display());
println!("System and error log: {}", system_log_path.display());
let access_log_appender = tracing_appender::rolling::daily(&log_dir_path, ACCESS_LOG_FILE);
let (access_non_blocking, guard) = tracing_appender::non_blocking(access_log_appender);
_ = ACCESS_LOG_GUARD.set(guard);
let system_log_appender = tracing_appender::rolling::daily(log_dir_path, SYSTEM_LOG_FILE);
let (system_non_blocking, guard) = tracing_appender::non_blocking(system_log_appender);
_ = SYSTEM_LOG_GUARD.set(guard);
let access_layer = fmt::layer()
.with_line_number(false)
.with_thread_ids(false)
.with_thread_names(false)
.with_target(false)
.with_level(false)
.compact()
.with_ansi(false)
.with_writer(access_non_blocking)
.with_filter(AccessLogFilter);
let system_layer = fmt::layer()
.with_line_number(false)
.with_thread_ids(false)
.with_thread_names(false)
.with_target(false)
.with_level(true)
.compact()
.with_ansi(false)
.with_writer(system_non_blocking)
.with_filter(filter_fn(move |metadata| {
(is_cargo_pkg(metadata) && metadata.name() != log_event_names::ACCESS_LOG && metadata.level() <= &level)
|| metadata.level() <= &tracing::Level::WARN.min(level)
}));
tracing_subscriber::registry().with(access_layer).with(system_layer).init();
}
/// stdio logging
fn init_stdio_logger(level: tracing::Level) {
// This limits the logger to emit only this crate with any level above RUST_LOG,
// for included crates it will emit only ERROR (in prod)/INFO (in dev) or above level.
let base_layer = fmt::layer().with_level(true).with_thread_ids(false);
let debug = level > tracing::Level::INFO;
let filter = filter_fn(move |metadata| {
if debug {
(is_cargo_pkg(metadata) && metadata.level() <= &level) || metadata.level() <= &tracing::Level::INFO.min(level)
} else {
(is_cargo_pkg(metadata) && metadata.level() <= &level) || metadata.level() <= &tracing::Level::WARN.min(level)
}
});
let stdio_layer = if debug {
base_layer
.with_line_number(true)
.with_target(true)
.with_thread_names(true)
.with_target(true)
.compact()
.with_filter(filter)
} else {
base_layer.with_target(false).compact().with_filter(filter)
};
tracing_subscriber::registry().with(stdio_layer).init();
}
/// Access log filter
struct AccessLogFilter;
impl<S> tracing_subscriber::layer::Filter<S> for AccessLogFilter {
fn enabled(&self, metadata: &tracing::Metadata<'_>, _: &tracing_subscriber::layer::Context<'_, S>) -> bool {
is_cargo_pkg(metadata) && metadata.name().contains(log_event_names::ACCESS_LOG) && metadata.level() <= &tracing::Level::INFO
}
}
#[inline]
/// Matches cargo package name with `_` instead of `-`
fn is_cargo_pkg(metadata: &tracing::Metadata<'_>) -> bool {
let pkg_name = env!("CARGO_PKG_NAME").replace('-', "_");
metadata.target().starts_with(&pkg_name)
}