1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 use std::io::Write;
16 use std::path::Path;
17 use std::sync::{Arc, Mutex};
18 use std::time::SystemTime;
19
20 use hdc::config;
21
22 #[derive(Default)]
23
24 pub struct LoggerMeta {
25 stdout_require: bool,
26 run_in_server: bool, // scrolling dump only by server
27 current_size: usize,
28 log_file: std::path::PathBuf,
29 }
30
31 type LoggerMeta_ = Arc<Mutex<LoggerMeta>>;
32
33 struct HostLoggerMeta {}
34 impl HostLoggerMeta {
get_instance() -> LoggerMeta_35 fn get_instance() -> LoggerMeta_ {
36 static mut LOGGER_META: Option<LoggerMeta_> = None;
37 unsafe {
38 LOGGER_META
39 .get_or_insert_with(|| Arc::new(Mutex::new(LoggerMeta::default())))
40 .clone()
41 }
42 }
43
init(run_in_server: bool, spawned_server: bool)44 fn init(run_in_server: bool, spawned_server: bool) {
45 let instance = Self::get_instance();
46 let mut meta = instance.lock().unwrap();
47 if run_in_server && !spawned_server {
48 meta.stdout_require = true;
49 }
50 meta.run_in_server = run_in_server;
51 meta.log_file = Path::new(&std::env::temp_dir()).join(config::LOG_FILE_NAME);
52 if run_in_server {
53 std::fs::File::create(&meta.log_file).unwrap();
54 }
55 }
56
write_log(content: String)57 fn write_log(content: String) {
58 let instance = Self::get_instance();
59 let mut meta = instance.lock().unwrap();
60 if meta.run_in_server && meta.current_size > config::LOG_FILE_SIZE {
61 meta.current_size = 0;
62 // TODO: mv to new file
63 }
64 meta.current_size += content.len();
65 if let Ok(mut f) = std::fs::File::options().append(true).open(&meta.log_file) {
66 writeln!(&mut f, "{}", content).unwrap();
67 }
68 if meta.stdout_require {
69 println!("{}", content);
70 }
71 }
72 }
73
74 struct SimpleHostLogger;
75 impl log::Log for SimpleHostLogger {
enabled(&self, metadata: &log::Metadata) -> bool76 fn enabled(&self, metadata: &log::Metadata) -> bool {
77 metadata.level() <= log::max_level()
78 }
log(&self, record: &log::Record)79 fn log(&self, record: &log::Record) {
80 if self.enabled(record.metadata()) {
81 let ts = humantime::format_rfc3339_millis(SystemTime::now()).to_string();
82 let level = &record.level().to_string()[..1];
83 let file = record.file().unwrap();
84 let content = format!(
85 "{} {} {} {}:{} - {}",
86 &ts[..10],
87 &ts[11..23],
88 level,
89 file.split_once('/').unwrap().1,
90 record.line().unwrap(),
91 record.args()
92 );
93 HostLoggerMeta::write_log(content);
94 }
95 }
flush(&self)96 fn flush(&self) {}
97 }
98
99 static LOGGER: SimpleHostLogger = SimpleHostLogger;
100
logger_init(log_level: log::LevelFilter, run_in_server: bool, spawned_server: bool)101 pub fn logger_init(log_level: log::LevelFilter, run_in_server: bool, spawned_server: bool) {
102 HostLoggerMeta::init(run_in_server, spawned_server);
103 log::set_logger(&LOGGER).unwrap();
104 log::set_max_level(log_level);
105 }
106