1#![doc = include_str!("../README.md")]
2#![doc = "\n## Example\n\n```rust"]
3#![doc = include_str!("../examples/main.rs")]
4#![doc = "```"]
5
6use std::{
7 fmt::Display,
8 fs::{self, OpenOptions},
9 io::Write,
10 path::Path,
11};
12
13use color_eyre::owo_colors::OwoColorize;
14use env_logger::{Builder, Env};
15use jiff::{Timestamp, tz};
16
17#[inline(always)]
18pub fn init(path: Option<&Path>) {
19 let file = path.map(|path| {
20 let _ = fs::remove_file(path);
21 OpenOptions::new()
22 .create(true)
23 .append(true)
24 .open(path)
25 .unwrap()
26 });
27
28 Builder::from_env(Env::default().default_filter_or(
29 "info,bitcoin=off,bitcoincore-rpc=off,fjall=off,lsm_tree=off,rolldown=off,brk_rolldown=off,rmcp=off,brk_rmcp=off,tracing=off",
30 ))
31 .format(move |buf, record| {
32 let date_time = Timestamp::now()
33 .to_zoned(tz::TimeZone::system())
34 .strftime("%Y-%m-%d %H:%M:%S")
35 .to_string();
36 let level = record.level().as_str().to_lowercase();
37 let level = format!("{level:5}");
38 let target = record.target();
39 let dash = "-";
40 let args = record.args();
41
42 if let Some(file) = file.as_ref() {
43 let _ = write(
44 file.try_clone().unwrap(),
45 &date_time,
46 target,
47 &level,
48 dash,
49 args,
50 );
51 }
52
53 let colored_date_time = date_time.bright_black();
54 let colored_level = match level.chars().next().unwrap() {
55 'e' => level.red().to_string(),
56 'w' => level.yellow().to_string(),
57 'i' => level.green().to_string(),
58 'd' => level.blue().to_string(),
59 't' => level.cyan().to_string(),
60 _ => panic!(),
61 };
62 let colored_dash = dash.bright_black();
63
64 write(
65 buf,
66 colored_date_time,
67 target,
68 colored_level,
69 colored_dash,
70 args,
71 )
72 })
73 .init();
74}
75
76fn write(
77 mut buf: impl Write,
78 date_time: impl Display,
79 _target: impl Display,
80 level: impl Display,
81 dash: impl Display,
82 args: impl Display,
83) -> Result<(), std::io::Error> {
84 writeln!(buf, "{date_time} {dash} {level} {args}")
85 }