-
Notifications
You must be signed in to change notification settings - Fork 0
/
app_logger.rs
135 lines (122 loc) · 5.54 KB
/
app_logger.rs
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* Date Created: 06/03/2024. */
//! The application logger.
use time::macros::format_description;
use time_tz::OffsetDateTimeExt;
use tracing_appender::{non_blocking::WorkerGuard, rolling::{RollingFileAppender, Rotation}};
use tracing_subscriber::{
fmt::{time::OffsetTime, Layer, writer::MakeWriterExt},
EnvFilter, layer::{SubscriberExt, Layer as _}
};
// TRACE, DEBUG, INFO, WARN, ERROR.
//
// Level implements the PartialOrd and Ord traits, allowing two Levels to be compared
// to determine which is considered more or less verbose. Levels which are more verbose
// are considered “greater than” levels which are less verbose, with Level::ERROR considered
// the lowest, and Level::TRACE considered the highest.
//
// assert!(Level::TRACE > Level::DEBUG);
// assert!(Level::ERROR < Level::WARN);
// assert!(Level::INFO <= Level::DEBUG);
//
// https://docs.rs/tracing/latest/tracing/struct.Level.html
//
// fn with_min_level(self, level: Level) -> WithMinLevel<Self>
// will only write output for events at or above the provided verbosity Level.
// https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/writer/trait.MakeWriterExt.html#method.with_min_level
//
// fn with_max_level(self, level: Level) -> WithMaxLevel<Self>
// will only write output for events at or below the provided verbosity Level.
// Level::TRACE is considered to be _more verbosethanLevel::INFO
// Events whose level is more verbose than level will be ignored
// https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/writer/trait.MakeWriterExt.html#method.with_max_level
/// Setting up the application logger.
///
/// # Note on Local Time Offset Calculating
///
/// Please note this block of the code:
///
/// ```text
/// // Each log line starts with a local date and time token.
/// let system_tz = time_tz::system::get_timezone()
/// .expect("Failed to find system timezone");
/// let localtime = time::OffsetDateTime::now_utc().to_timezone(system_tz);
///
/// let timer = OffsetTime::new(
/// localtime.offset(),
/// format_description!("[year]-[month]-[day]-[hour]:[minute]:[second]"),
/// );
/// ```
///
/// Originally `localtime.offset()` was ``UtcOffset::current_local_offset().unwrap()``.
///
/// ``UtcOffset::current_local_offset().unwrap()`` raises
/// [IndeterminateOffset](https://docs.rs/time/latest/time/error/struct.IndeterminateOffset.html)
/// error.
///
/// According to this GitHub issue on Dec 19, 2020,
/// [Document #293 in local-offset feature description #297](https://github.com/time-rs/time/pull/297),
/// this problem has not been fixed.
///
/// See also the following issues:
///
/// * Nov 25, 2020 -- [Time 0.2.23 fails to determine local offset #296](https://github.com/time-rs/time/issues/296).
///
/// * Nov 2, 2021 -- [Better solution for getting local offset on unix #380](https://github.com/time-rs/time/issues/380).
///
/// * Dec 5, 2019 -- [tzdb support #193](https://github.com/time-rs/time/issues/193).
/// [This reply](https://github.com/time-rs/time/issues/193#issuecomment-1037227056) on Feb 13, 2022
/// points to crate [time-tz](https://crates.io/crates/time-tz), which solves the above error.
///
/// # Return
///
/// - [WorkerGuard](https://docs.rs/tracing-appender/latest/tracing_appender/non_blocking/struct.WorkerGuard.html).
/// This guard must be kept alive during the live of the application server for the log to work.
///
/// # Note on ``RUST_LOG`` Environment Variable
///
/// Please see [Enabling logging](https://docs.rs/env_logger/latest/env_logger/#enabling-logging).
///
/// In the context of this application, some example of valid configurations are:
///
/// * ``RUST_LOG=off,learn_actix_web=debug``
/// * ``RUST_LOG=off,learn_actix_web=info`` -- nothing will get log.
/// * ``RUST_LOG=off,learn_actix_web=debug,actix_server=info``
///
pub fn init_app_logger() -> WorkerGuard {
let log_appender = RollingFileAppender::builder()
.rotation(Rotation::DAILY) // Daily log file.
.filename_suffix("log") // log file names will be suffixed with `.log`
.build("./log") // try to build an appender that stores log files in `/var/log`
.expect("Initialising rolling file appender failed");
let (non_blocking_appender, log_guard) = tracing_appender::non_blocking(log_appender);
// Each log line starts with a local date and time token.
let system_tz = time_tz::system::get_timezone()
.expect("Failed to find system timezone");
let localtime = time::OffsetDateTime::now_utc().to_timezone(system_tz);
let timer = OffsetTime::new(
localtime.offset(),
format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"),
);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("debug"))
.unwrap();
let subscriber = tracing_subscriber::registry()
.with(
Layer::new()
.with_timer(timer)
.with_ansi(false)
.with_writer(non_blocking_appender
.and(std::io::stdout))
.with_filter(filter_layer)
);
// tracing::subscriber::set_global_default(subscriber) can only be called once.
// Subsequent calls raise SetGlobalDefaultError, ignore these errors.
//
// There are integeration test methods which call this init_app_logger(...) repeatedly!!
//
match tracing::subscriber::set_global_default(subscriber) {
Err(err) => tracing::error!("Logger set_global_default, ignored: {}", err),
_ => (),
}
log_guard
}