1use openconnect_sys::{PRG_DEBUG, PRG_ERR, PRG_INFO, PRG_TRACE};
2use tracing::{
3 event,
4 subscriber::{set_global_default, SetGlobalDefaultError},
5 Level,
6};
7use tracing_appender::rolling::{RollingFileAppender, Rotation};
8
9pub struct Logger;
10
11impl Logger {
12 pub fn get_log_path() -> &'static str {
13 #[cfg(target_os = "linux")]
14 const LOG_PATH: &str = "/var/log/openconnect-rs";
15
16 #[cfg(target_os = "macos")]
17 const LOG_PATH: &str = "/Library/Logs/openconnect-rs";
18
19 #[cfg(target_os = "windows")]
20 const LOG_PATH: &str = "C:\\ProgramData\\openconnect-rs";
21
22 LOG_PATH
23 }
24
25 pub fn init() -> Result<(), SetGlobalDefaultError> {
26 let file_appender = RollingFileAppender::builder()
27 .max_log_files(5)
28 .rotation(Rotation::DAILY)
29 .filename_prefix("openconnect-rs.log")
30 .build(Self::get_log_path())
31 .expect("failed to create file appender");
32
33 let subscriber = tracing_subscriber::fmt()
35 .compact()
36 .with_level(true)
37 .with_target(true)
38 .with_max_level(Level::TRACE)
39 .with_writer(file_appender)
40 .finish();
41
42 set_global_default(subscriber)
43 }
44
45 pub(crate) unsafe extern "C" fn raw_handle_process_log(
46 _privdata: *mut ::std::os::raw::c_void,
47 level: ::std::os::raw::c_int,
48 buf: *const ::std::os::raw::c_char,
49 ) {
50 let buf = std::ffi::CStr::from_ptr(buf).to_str().ok();
51 let level = level as u32;
52 let level = match level {
53 PRG_ERR => Level::ERROR,
54 PRG_INFO => Level::INFO,
55 PRG_DEBUG => Level::DEBUG,
56 PRG_TRACE => Level::TRACE,
57 _ => unreachable!("unknown log level: {}", level),
58 };
59 if buf.is_some() {
60 Logger::log(level, buf.unwrap_or(""));
61 }
62 }
63
64 pub fn log(level: Level, message: &str) {
65 match level {
66 Level::ERROR => event!(Level::ERROR, "{}", message),
67 Level::WARN => event!(Level::WARN, "{}", message),
68 Level::INFO => event!(Level::INFO, "{}", message),
69 Level::DEBUG => event!(Level::DEBUG, "{}", message),
70 Level::TRACE => event!(Level::TRACE, "{}", message),
71 }
72 }
73}