| 64 | /// On success, this returns a guard which must be kept alive. |
| 65 | #[inline] |
| 66 | pub fn initialize_logging<T: AsRef<Path>>(args: LogArgs<T>) -> Result<LogGuard, Error> { |
| 67 | let filter_layer = create_filter_layer(); |
| 68 | let (reloadable_filter_layer, reloadable_handle) = tracing_subscriber::reload::Layer::new(filter_layer); |
| 69 | ENV_FILTER_RELOADABLE_HANDLE.lock().unwrap().replace(reloadable_handle); |
| 70 | let mut mcp_path = None; |
| 71 | |
| 72 | // First we construct the file logging layer if a file name was provided. |
| 73 | let (file_layer, _file_guard) = match args.log_file_path { |
| 74 | Some(log_file_path) => { |
| 75 | let log_path = log_file_path.as_ref(); |
| 76 | |
| 77 | // Make the log path parent directory if it doesn't exist. |
| 78 | if let Some(parent) = log_path.parent() { |
| 79 | if log_path.ends_with("qchat.log") { |
| 80 | mcp_path = Some(parent.to_path_buf()); |
| 81 | } |
| 82 | std::fs::create_dir_all(parent)?; |
| 83 | } |
| 84 | |
| 85 | // We delete the old log file when requested each time the logger is initialized, otherwise we only |
| 86 | // delete the file when it has grown too large. |
| 87 | if args.delete_old_log_file { |
| 88 | std::fs::remove_file(log_path).ok(); |
| 89 | } else if log_path.exists() && std::fs::metadata(log_path)?.len() > MAX_FILE_SIZE { |
| 90 | std::fs::remove_file(log_path)?; |
| 91 | } |
| 92 | |
| 93 | // Create the new log file or append to the existing one. |
| 94 | let file = if args.delete_old_log_file { |
| 95 | File::create(log_path)? |
| 96 | } else { |
| 97 | File::options().append(true).create(true).open(log_path)? |
| 98 | }; |
| 99 | |
| 100 | // On posix-like systems, we modify permissions so that only the owner has access. |
| 101 | #[cfg(unix)] |
| 102 | { |
| 103 | use std::os::unix::fs::PermissionsExt; |
| 104 | if let Ok(metadata) = file.metadata() { |
| 105 | let mut permissions = metadata.permissions(); |
| 106 | permissions.set_mode(0o600); |
| 107 | file.set_permissions(permissions).ok(); |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | let (non_blocking, guard) = tracing_appender::non_blocking(file); |
| 112 | let file_layer = fmt::layer().with_line_number(true).with_writer(non_blocking); |
| 113 | |
| 114 | (Some(file_layer), Some(guard)) |
| 115 | }, |
| 116 | None => (None, None), |
| 117 | }; |
| 118 | |
| 119 | // If we log to stdout, we need to add this layer to our logger. |
| 120 | let (stdout_layer, _stdout_guard) = if args.log_to_stdout { |
| 121 | let (non_blocking, guard) = tracing_appender::non_blocking(std::io::stdout()); |
| 122 | let stdout_layer = fmt::layer().with_line_number(true).with_writer(non_blocking); |
| 123 | (Some(stdout_layer), Some(guard)) |