1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ciuse std::io::Write; 16cc290419Sopenharmony_ciuse std::path::Path; 17cc290419Sopenharmony_ciuse std::sync::{Arc, Mutex}; 18cc290419Sopenharmony_ciuse std::time::SystemTime; 19cc290419Sopenharmony_ci 20cc290419Sopenharmony_ciuse hdc::config; 21cc290419Sopenharmony_ci 22cc290419Sopenharmony_ci// #[derive(Default)] 23cc290419Sopenharmony_ci 24cc290419Sopenharmony_cipub struct LoggerMeta { 25cc290419Sopenharmony_ci stdout_require: bool, 26cc290419Sopenharmony_ci run_in_server: bool, // scrolling dump only by server 27cc290419Sopenharmony_ci current_size: usize, 28cc290419Sopenharmony_ci log_file: std::path::PathBuf, 29cc290419Sopenharmony_ci log_level: log::LevelFilter, 30cc290419Sopenharmony_ci} 31cc290419Sopenharmony_ci 32cc290419Sopenharmony_ciimpl Default for LoggerMeta { 33cc290419Sopenharmony_ci fn default() -> Self { 34cc290419Sopenharmony_ci Self { 35cc290419Sopenharmony_ci stdout_require: Default::default(), 36cc290419Sopenharmony_ci run_in_server: Default::default(), 37cc290419Sopenharmony_ci current_size: Default::default(), 38cc290419Sopenharmony_ci log_file: Default::default(), 39cc290419Sopenharmony_ci log_level: log::LevelFilter::Debug, 40cc290419Sopenharmony_ci } 41cc290419Sopenharmony_ci } 42cc290419Sopenharmony_ci} 43cc290419Sopenharmony_ci 44cc290419Sopenharmony_citype LoggerMeta_ = Arc<Mutex<LoggerMeta>>; 45cc290419Sopenharmony_ci 46cc290419Sopenharmony_cistruct HostLoggerMeta {} 47cc290419Sopenharmony_ciimpl HostLoggerMeta { 48cc290419Sopenharmony_ci fn get_instance() -> LoggerMeta_ { 49cc290419Sopenharmony_ci static mut LOGGER_META: Option<LoggerMeta_> = None; 50cc290419Sopenharmony_ci unsafe { 51cc290419Sopenharmony_ci LOGGER_META 52cc290419Sopenharmony_ci .get_or_insert_with(|| Arc::new(Mutex::new(LoggerMeta::default()))) 53cc290419Sopenharmony_ci .clone() 54cc290419Sopenharmony_ci } 55cc290419Sopenharmony_ci } 56cc290419Sopenharmony_ci 57cc290419Sopenharmony_ci fn init(run_in_server: bool, spawned_server: bool, log_level: log::LevelFilter) { 58cc290419Sopenharmony_ci let instance = Self::get_instance(); 59cc290419Sopenharmony_ci let Ok(mut meta) = instance.lock() else { 60cc290419Sopenharmony_ci println!("init lock error"); 61cc290419Sopenharmony_ci return; 62cc290419Sopenharmony_ci }; 63cc290419Sopenharmony_ci meta.log_level = log_level; 64cc290419Sopenharmony_ci if run_in_server && !spawned_server { 65cc290419Sopenharmony_ci meta.stdout_require = true; 66cc290419Sopenharmony_ci } 67cc290419Sopenharmony_ci meta.run_in_server = run_in_server; 68cc290419Sopenharmony_ci meta.log_file = Path::new(&std::env::temp_dir()) 69cc290419Sopenharmony_ci .join(config::LOG_FILE_NAME.to_string() + config::LOG_TAIL_NAME); 70cc290419Sopenharmony_ci if run_in_server { 71cc290419Sopenharmony_ci Self::dump_log_file(config::LOG_BAK_NAME, meta.log_level); 72cc290419Sopenharmony_ci if let Err(err) = std::fs::File::create(&meta.log_file) { 73cc290419Sopenharmony_ci println!("File::create failed, {}, {err}", meta.log_file.display()); 74cc290419Sopenharmony_ci } 75cc290419Sopenharmony_ci } 76cc290419Sopenharmony_ci } 77cc290419Sopenharmony_ci 78cc290419Sopenharmony_ci fn write_log(content: String) { 79cc290419Sopenharmony_ci let instance = Self::get_instance(); 80cc290419Sopenharmony_ci let mut meta = instance.lock().unwrap(); 81cc290419Sopenharmony_ci if meta.run_in_server && meta.current_size > config::LOG_FILE_SIZE { 82cc290419Sopenharmony_ci meta.current_size = 0; 83cc290419Sopenharmony_ci Self::dump_log_file(config::LOG_CACHE_NAME, meta.log_level); 84cc290419Sopenharmony_ci std::fs::File::create(&meta.log_file).unwrap(); 85cc290419Sopenharmony_ci } 86cc290419Sopenharmony_ci meta.current_size += content.len(); 87cc290419Sopenharmony_ci if let Ok(mut f) = std::fs::File::options().append(true).open(&meta.log_file) { 88cc290419Sopenharmony_ci writeln!(&mut f, "{}", content).unwrap(); 89cc290419Sopenharmony_ci } 90cc290419Sopenharmony_ci if meta.stdout_require { 91cc290419Sopenharmony_ci println!("{}", content); 92cc290419Sopenharmony_ci } 93cc290419Sopenharmony_ci } 94cc290419Sopenharmony_ci 95cc290419Sopenharmony_ci fn dump_log_file(file_type: &str, log_level: log::LevelFilter) { 96cc290419Sopenharmony_ci let file_path = Path::new(&std::env::temp_dir()) 97cc290419Sopenharmony_ci .join(config::LOG_FILE_NAME.to_string() + config::LOG_TAIL_NAME); 98cc290419Sopenharmony_ci let ts = humantime::format_rfc3339_millis(SystemTime::now()) 99cc290419Sopenharmony_ci .to_string() 100cc290419Sopenharmony_ci .replace(':', ""); 101cc290419Sopenharmony_ci let file_cache_path = if log_level == log::LevelFilter::Trace { 102cc290419Sopenharmony_ci Path::new(&std::env::temp_dir()) 103cc290419Sopenharmony_ci .join(file_type.to_string() + &ts[..19] + config::LOG_TAIL_NAME) 104cc290419Sopenharmony_ci } else { 105cc290419Sopenharmony_ci Path::new(&std::env::temp_dir()).join(file_type.to_string() + config::LOG_TAIL_NAME) 106cc290419Sopenharmony_ci }; 107cc290419Sopenharmony_ci if file_path.exists() { 108cc290419Sopenharmony_ci if let Err(err) = std::fs::rename(&file_path, file_cache_path) { 109cc290419Sopenharmony_ci hdc::error!("rename failed, {err}"); 110cc290419Sopenharmony_ci } 111cc290419Sopenharmony_ci } 112cc290419Sopenharmony_ci } 113cc290419Sopenharmony_ci 114cc290419Sopenharmony_ci fn get_running_mode() -> String { 115cc290419Sopenharmony_ci let instance = Self::get_instance(); 116cc290419Sopenharmony_ci let Ok(meta) = instance.lock() else { 117cc290419Sopenharmony_ci return "".to_string(); 118cc290419Sopenharmony_ci }; 119cc290419Sopenharmony_ci if meta.run_in_server { 120cc290419Sopenharmony_ci "server".to_string() 121cc290419Sopenharmony_ci } else { 122cc290419Sopenharmony_ci "client".to_string() 123cc290419Sopenharmony_ci } 124cc290419Sopenharmony_ci } 125cc290419Sopenharmony_ci} 126cc290419Sopenharmony_ci 127cc290419Sopenharmony_cistruct SimpleHostLogger; 128cc290419Sopenharmony_ciimpl log::Log for SimpleHostLogger { 129cc290419Sopenharmony_ci fn enabled(&self, metadata: &log::Metadata) -> bool { 130cc290419Sopenharmony_ci metadata.level() <= log::max_level() 131cc290419Sopenharmony_ci } 132cc290419Sopenharmony_ci fn log(&self, record: &log::Record) { 133cc290419Sopenharmony_ci if self.enabled(record.metadata()) { 134cc290419Sopenharmony_ci let ts = humantime::format_rfc3339_millis(SystemTime::now()).to_string(); 135cc290419Sopenharmony_ci let level = &record.level().to_string()[..1]; 136cc290419Sopenharmony_ci let Some(file) = record.file() else { 137cc290419Sopenharmony_ci println!("Get record file failed"); 138cc290419Sopenharmony_ci return; 139cc290419Sopenharmony_ci }; 140cc290419Sopenharmony_ci // cargo编译下的文件目录可能存在\\的目录,需要通过编译宏隔离 141cc290419Sopenharmony_ci #[cfg(target_os = "windows")] 142cc290419Sopenharmony_ci let file = file.replace('\\', "/"); 143cc290419Sopenharmony_ci let running_mode = HostLoggerMeta::get_running_mode(); 144cc290419Sopenharmony_ci let content = format!( 145cc290419Sopenharmony_ci "{} {} {} [{}] {}:{} - {}", 146cc290419Sopenharmony_ci &ts[..10], 147cc290419Sopenharmony_ci &ts[11..23], 148cc290419Sopenharmony_ci level, 149cc290419Sopenharmony_ci running_mode, 150cc290419Sopenharmony_ci file.split_once('/').unwrap_or(("", "")).1, 151cc290419Sopenharmony_ci record.line().unwrap_or_default(), 152cc290419Sopenharmony_ci record.args() 153cc290419Sopenharmony_ci ); 154cc290419Sopenharmony_ci HostLoggerMeta::write_log(content); 155cc290419Sopenharmony_ci } 156cc290419Sopenharmony_ci } 157cc290419Sopenharmony_ci fn flush(&self) {} 158cc290419Sopenharmony_ci} 159cc290419Sopenharmony_ci 160cc290419Sopenharmony_cistatic LOGGER: SimpleHostLogger = SimpleHostLogger; 161cc290419Sopenharmony_ci 162cc290419Sopenharmony_cipub fn logger_init(log_level: log::LevelFilter, run_in_server: bool, spawned_server: bool) { 163cc290419Sopenharmony_ci HostLoggerMeta::init(run_in_server, spawned_server, log_level); 164cc290419Sopenharmony_ci if let Err(err) = log::set_logger(&LOGGER) { 165cc290419Sopenharmony_ci println!("log::set_logger failed, {err}"); 166cc290419Sopenharmony_ci return; 167cc290419Sopenharmony_ci } 168cc290419Sopenharmony_ci log::set_max_level(log_level); 169cc290419Sopenharmony_ci} 170