use std::env::current_exe; use std::fs; use std::path::Path; use tracing::{error, Level, subscriber}; use tracing_appender::non_blocking::{WorkerGuard}; use tracing_appender::rolling::{RollingFileAppender, Rotation}; use tracing_unwrap::{OptionExt, ResultExt}; use crate::constants::{FAILOVER_LOG_LEVEL_KEY, GATEWAY_LOG_LEVEL_KEY, NODE_LOG_LEVEL_KEY, TICKET_LOG_LEVEL_KEY}; use crate::parameter_store::get_parameter; fn read_cargo_toml() -> toml::Value{ let cargo_toml_content = fs::read_to_string("Cargo.toml") .expect_or_log("Failed to read Cargo.toml file"); let cargo_toml: toml::Value = toml::from_str(&cargo_toml_content) .expect_or_log("Failed to parse Cargo.toml"); cargo_toml } fn get_app_name() -> Option { let cargo_toml = read_cargo_toml(); let package = cargo_toml .get("package") .expect("`[package]` section is missing in Cargo.toml"); let name = package .get("name") .expect_or_log("`name` field is missing in Cargo.toml"); let name_str = name .as_str() .expect_or_log("Package name is not a string"); Option::from(name_str.to_string()) } fn get_log_level_parameter_key() -> Option { let mut ret: Option = None; match get_app_name() { None => { ret = None } Some(app_name) => { match app_name.as_str() { "device-gateway" => { ret = Option::from(GATEWAY_LOG_LEVEL_KEY.to_string()) } "device-node" => { ret = Option::from(NODE_LOG_LEVEL_KEY.to_string()) } "device-ticket" => { ret = Option::from(TICKET_LOG_LEVEL_KEY.to_string()) } "device-failover" => { ret = Option::from(FAILOVER_LOG_LEVEL_KEY.to_string()) } _ => { return ret } } } } ret } pub async fn init(log_file_name: &str) -> WorkerGuard { let mut level: Level = Level::INFO; let log_level_parameter_key = get_log_level_parameter_key() .expect("log level parameter key not found"); let log_level = get_parameter(log_level_parameter_key).await; match log_level.to_lowercase().as_str() { "debug" => { level = Level::DEBUG }, "info" => { level = Level::INFO }, "warn" => { level = Level::WARN }, _ => {} } let log_dir = get_log_dir(); if !Path::new(&log_dir).exists() { fs::create_dir_all(&log_dir).expect("failed to create log directory"); } let file_appender = RollingFileAppender::builder() .rotation(Rotation::DAILY) .filename_suffix(log_file_name) .build(log_dir) .expect("failed to initialize rolling file appender"); let (file_writer, _guard) = tracing_appender::non_blocking(file_appender); let subscriber = tracing_subscriber::fmt() .with_max_level(level) .with_writer(file_writer) //.with_writer(console_writer) .with_ansi(false) .finish(); subscriber::set_global_default(subscriber) .expect("trace init fail"); _guard } pub fn expect_or_log(result: Result, message: &str) -> T { match result { Ok(val) => val, Err(err) => { let err_message = err.to_string(); error!("{}: {}", message, err_message); panic!("{}: {}", message, err_message); } } } fn get_log_dir() -> String { let mut current_dir = current_exe().unwrap(); current_dir.pop(); current_dir.push("log"); current_dir.display().to_string() }