1use humantime;
2use log::*;
3use serde_json::json;
4use std::thread;
5use std::time::SystemTime;
6
7pub use log::Level;
8
9pub enum FiaasEnv {
10 Local,
11 Dev,
12 Prod,
13}
14
15struct FiaasLogger {
16 finn_app: &'static str,
17 env: FiaasEnv,
18 level: log::Level,
19}
20
21impl Log for FiaasLogger {
22 fn enabled(&self, metadata: &Metadata) -> bool {
23 metadata.level() <= self.level
24 }
25
26 fn log(&self, record: &Record) {
27 if self.enabled(record.metadata()) {
28 let timestamp = humantime::format_rfc3339_millis(SystemTime::now());
29
30 match self.env {
31 FiaasEnv::Local => match record.level() {
32 Level::Error => eprintln!(
33 "[{timestamp} {level} {logger}] {message}",
34 timestamp = timestamp,
35 logger = record.target(),
36 level = record.level(),
37 message = record.args(),
38 ),
39 _ => println!(
40 "[{timestamp} {level} {logger}] {message}",
41 timestamp = timestamp,
42 logger = record.target(),
43 level = record.level(),
44 message = record.args(),
45 ),
46 },
47 FiaasEnv::Dev | FiaasEnv::Prod => {
48 let t = thread::current();
49 match record.level() {
50 Level::Error => eprintln!(
51 "{}",
52 serde_json::to_string(&json!({
53 "@version":1,
54 "@timestamp": timestamp.to_string(),
55 "logger": record.target(),
56 "thread": format!("{}-{:?}", t.name().unwrap_or("unnamed"), t.id()),
57 "level": record.level().to_string(),
58 "message": record.args(),
59 "finn_app": self.finn_app
60 }))
61 .unwrap()
62 ),
63 _ => println!(
64 "{}",
65 serde_json::to_string(&json!({
66 "@version":1,
67 "@timestamp": timestamp.to_string(),
68 "logger": record.target(),
69 "thread": format!("{}-{:?}", t.name().unwrap_or("unnamed"), t.id()),
70 "level": record.level().to_string(),
71 "message": record.args(),
72 "finn_app": self.finn_app
73 }))
74 .unwrap()
75 ),
76 }
77 }
78 }
79 }
80 }
81
82 fn flush(&self) {}
83}
84
85pub fn try_init(
86 finn_app: &'static str,
87 env: FiaasEnv,
88 level: Level,
89) -> Result<(), log::SetLoggerError> {
90 let r = log::set_boxed_logger(Box::new(FiaasLogger {
91 finn_app,
92 env,
93 level,
94 }));
95 if r.is_ok() {
96 log::set_max_level(level.to_level_filter());
97 }
98 r
99}
100
101pub fn init(finn_app: &'static str, env: FiaasEnv, level: Level) {
102 try_init(finn_app, env, level).unwrap();
103}
104
105pub fn init_env(finn_app: &'static str) {
106 let level = match std::env::var("RUST_LOG")
107 .expect("RUST_LOG must be set")
108 .as_ref()
109 {
110 "error" => Level::Error,
111 "warn" => Level::Warn,
112 "info" => Level::Info,
113 "debug" => Level::Debug,
114 "trace" => Level::Trace,
115 _ => panic!("RUST_LOG must be one of error, warn, info, debug and trace"),
116 };
117
118 let env = match std::env::var("FIAAS_ENVIRONMENT")
119 .expect("FIAAS_ENVIRONMENT must be set")
120 .as_ref()
121 {
122 "local" => FiaasEnv::Local,
123 "dev" => FiaasEnv::Dev,
124 "prod" => FiaasEnv::Prod,
125 _ => panic!("FIAAS_ENVIRONMENT must be one of local, dev and prod"),
126 };
127
128 init(finn_app, env, level);
129}