1#[macro_use]
2extern crate slog;
3#[macro_use]
4extern crate lazy_static;
5
6use slog::Drain;
7use slog::FnValue;
8use slog::Level;
9use slog::LevelFilter;
10use slog::Logger;
11use std::env;
12use std::fs::OpenOptions;
13
14lazy_static! {
15 static ref ROOT_LOGGER: Logger = make_root_logger(
16 "FIL_PROOFS_LOG_JSON",
17 "FIL_PROOFS_MIN_LOG_LEVEL",
18 "FIL_PROOFS_LOG_FILE"
19 );
20}
21
22pub fn make_root_logger(
23 use_json_env_name: &str,
24 min_log_level_env_name: &str,
25 log_file_env_name: &str,
26) -> Logger {
27 let log_file_name = env::var(log_file_env_name).unwrap_or_else(|_| "/dev/stdout".to_string());
28 let log_file: Box<dyn std::io::Write + Send> = match log_file_name.as_ref() {
29 "/dev/stdout" => Box::new(std::io::stdout()),
30 "/dev/stderr" => Box::new(std::io::stderr()),
31 filename => {
32 let tryfile = OpenOptions::new().create(true).append(true).open(filename);
33 match tryfile {
34 Ok(file) => Box::new(file),
35 Err(_) => Box::new(std::io::stdout()),
37 }
38 }
39 };
40
41 let drain = match env::var(use_json_env_name).as_ref().map(String::as_str) {
42 Ok("true") => {
43 let json_drain = slog_json::Json::new(log_file)
44 .add_default_keys()
45 .build()
46 .fuse();
47
48 slog_async::Async::new(json_drain).build().fuse()
49 }
50 _ => {
51 match log_file_name.as_ref() {
52 "/dev/stdout" | "/dev/stderr" => {
54 let term_decorator = slog_term::TermDecorator::new().build();
55 let term_drain = slog_term::FullFormat::new(term_decorator).build().fuse();
56
57 slog_async::Async::new(term_drain).build().fuse()
58 }
59 _ => {
61 let plain_decorator = slog_term::PlainDecorator::new(log_file);
62 let plain_drain = slog_term::FullFormat::new(plain_decorator).build().fuse();
63
64 slog_async::Async::new(plain_drain).build().fuse()
65 }
66 }
67 }
68 };
69
70 let min_log_level = match env::var(min_log_level_env_name) {
71 Ok(val) => match val.parse::<u64>() {
72 Ok(parsed) => match Level::from_usize(parsed as usize) {
73 Some(level) => level,
74 None => Level::Info,
75 },
76 _ => Level::Info,
77 },
78 _ => Level::Info,
79 };
80
81 let with_filter = LevelFilter::new(drain, min_log_level).map(slog::Fuse);
82
83 Logger::root(
84 with_filter,
85 o!("place" => FnValue(move |info| {
86 format!("{}:{} {}",
87 info.file(),
88 info.line(),
89 info.module(),
90 )
91 })),
92 )
93}
94
95pub fn make_logger(root_name: &'static str) -> Logger {
96 ROOT_LOGGER.new(o!("root" => root_name))
97}