use crate::Config;
use crate::model::errors::{LbResult, core_err_unexpected};
use crate::service::debug::{generate_panic_content, generate_panic_filename};
use std::backtrace::Backtrace;
use std::fs::OpenOptions;
use std::io::Write;
use std::{env, panic};
use tracing::metadata::LevelFilter;
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{Layer, filter, fmt};
pub static LOG_FILE: &str = "lockbook.log";
pub fn init(config: &Config) -> LbResult<()> {
if config.logs {
let lockbook_log_level = env::var("LOG_LEVEL")
.ok()
.and_then(|s| s.as_str().parse().ok())
.unwrap_or(LevelFilter::DEBUG);
let mut layers = Vec::with_capacity(2);
#[cfg(not(target_arch = "wasm32"))]
layers.push(
fmt::Layer::new()
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
.with_ansi(config.colored_logs)
.with_target(true)
.with_writer(tracing_appender::rolling::never(&config.writeable_path, LOG_FILE))
.with_filter(lockbook_log_level)
.with_filter(filter::filter_fn(|metadata| {
metadata.target().starts_with("lb_rs")
|| metadata.target().starts_with("dbrs")
|| metadata.target().starts_with("workspace")
|| metadata.target().starts_with("lb_fs")
}))
.boxed(),
);
if config.stdout_logs {
#[cfg(not(target_os = "android"))]
layers.push(
fmt::Layer::new()
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
.with_ansi(config.colored_logs)
.with_target(true)
.with_filter(lockbook_log_level)
.with_filter(filter::filter_fn(|metadata| {
metadata.target().starts_with("lb_rs")
|| metadata.target().starts_with("dbrs")
|| metadata.target().starts_with("workspace")
|| metadata.target().starts_with("lb_fs")
}))
.boxed(),
);
#[cfg(target_os = "android")]
if let Some(writer) =
tracing_logcat::LogcatMakeWriter::new(tracing_logcat::LogcatTag::Target).ok()
{
layers.push(
fmt::Layer::new()
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
.with_ansi(false)
.with_writer(writer)
.with_filter(lockbook_log_level)
.with_filter(filter::filter_fn(|metadata| {
metadata.target().starts_with("lb_rs")
|| metadata.target().starts_with("workspace")
|| metadata.target().starts_with("lb_java")
}))
.boxed(),
);
}
}
tracing::subscriber::set_global_default(
tracing_subscriber::Registry::default().with(layers),
)
.map_err(core_err_unexpected)?;
panic_capture(config);
}
Ok(())
}
fn panic_capture(config: &Config) {
let path = config.writeable_path.clone();
panic::set_hook(Box::new(move |error_header| {
let bt = Backtrace::force_capture();
tracing::error!("panic detected: {error_header} {}", bt);
eprintln!("panic detected and logged: {error_header} {bt}");
let file_name = generate_panic_filename(&path);
let content = generate_panic_content(&error_header.to_string(), &bt.to_string());
let mut file = OpenOptions::new()
.create(true)
.append(true)
.open(&file_name)
.unwrap();
file.write_all(content.as_bytes()).unwrap();
}));
}