summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-daemon/src/logging.rs50
-rw-r--r--mullvad-daemon/src/main.rs56
-rw-r--r--mullvad-daemon/src/system_service.rs7
-rw-r--r--mullvad-jni/src/lib.rs22
-rw-r--r--talpid-core/src/logging/mod.rs3
5 files changed, 88 insertions, 50 deletions
diff --git a/mullvad-daemon/src/logging.rs b/mullvad-daemon/src/logging.rs
index c1aa521680..8ad461e4bf 100644
--- a/mullvad-daemon/src/logging.rs
+++ b/mullvad-daemon/src/logging.rs
@@ -46,7 +46,6 @@ impl<'a, T: Clone + io::Write> MakeWriter<'a> for OptionalMakeWriter<T> {
}
pub const WARNING_SILENCED_CRATES: &[&str] = &["netlink_proto", "quinn_udp"];
-const DAEMON_LOG_FILENAME: &str = "daemon.log";
pub const SILENCED_CRATES: &[&str] = &[
"h2",
"tokio_core",
@@ -92,6 +91,27 @@ pub struct LogHandle {
_file_appender_guard: Option<non_blocking::WorkerGuard>,
}
+/// A location to put logs.
+///
+/// It is necessary to logically separate the directory from the absolute path of the log file due
+/// to the API of [`tracing_appender::rolling`].
+#[derive(Clone, Debug, PartialEq)]
+pub struct LogLocation {
+ /// The directory where the logs will be recorded.
+ pub directory: PathBuf,
+ /// The filename where the logs will be recorded (relative to [Self::directory]).
+ pub filename: PathBuf,
+}
+
+impl LogLocation {
+ /// Construct the final path of the log file made up by the components of this [`LogLocation`].
+ ///
+ /// `self.directory/self.filename`
+ pub fn log_path(&self) -> PathBuf {
+ self.directory.join(&self.filename)
+ }
+}
+
/// A simple, asynchronous log sink.
///
/// To read from a [`LogStreamer`] sink, check out the associated [`LogHandle`] and [`LogHandle::get_log_stream`].
@@ -142,9 +162,14 @@ impl LogHandle {
}
}
+/// Initialize a global logger.
+///
+/// * log_level: Base log level, used if `RUST_LOG` is not set.
+/// * log_location: Path to the log file, see [`LogLocation`].
+/// * output_timestamp: Whether timestamps should be included in the log output.
pub fn init_logger(
log_level: log::LevelFilter,
- log_dir: Option<&PathBuf>,
+ log_location: Option<LogLocation>,
output_timestamp: bool,
) -> Result<LogHandle, Error> {
let level_filter = match log_level {
@@ -162,13 +187,16 @@ pub fn init_logger(
let default_filter = silence_crates(env_filter);
// TODO: Switch this to a rolling appender, likely daily or hourly
- let (_file_appender_guard, non_blocking_file_appender) = if let Some(log_dir) = log_dir {
- let file_appender = tracing_appender::rolling::never(log_dir, DAEMON_LOG_FILENAME);
- let (appender, guard) = non_blocking(file_appender);
- (Some(guard), OptionalMakeWriter(Some(appender)))
- } else {
- (None, OptionalMakeWriter(None))
- };
+ let (_file_appender_guard, non_blocking_file_appender) =
+ if let Some(log_location) = log_location.as_ref() {
+ rotate_log(&log_location.log_path()).map_err(Error::RotateLog)?;
+ let file_appender =
+ tracing_appender::rolling::never(&log_location.directory, &log_location.filename);
+ let (appender, guard) = non_blocking(file_appender);
+ (Some(guard), OptionalMakeWriter(Some(appender)))
+ } else {
+ (None, OptionalMakeWriter(None))
+ };
let (tx, _) = tokio::sync::broadcast::channel(128);
let log_stream = LogStreamer { tx };
@@ -185,10 +213,6 @@ pub fn init_logger(
.with_ansi(true)
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE);
- if let Some(log_dir) = log_dir {
- rotate_log(&log_dir.join(DAEMON_LOG_FILENAME)).map_err(Error::RotateLog)?;
- }
-
#[cfg(all(target_os = "android", debug_assertions))]
let reg = {
let android_layer = paranoid_android::layer("mullvad-daemon");
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index ea0e9d395a..bbc99ca7ee 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -3,8 +3,9 @@ use std::{path::PathBuf, thread, time::Duration};
#[cfg(not(windows))]
use mullvad_daemon::cleanup_old_rpc_socket;
use mullvad_daemon::{
- Daemon, DaemonCommandChannel, DaemonConfig, exception_logging, logging, rpc_uniqueness_check,
- runtime, version,
+ Daemon, DaemonCommandChannel, DaemonConfig, exception_logging,
+ logging::{self, LogLocation},
+ rpc_uniqueness_check, runtime, version,
};
use talpid_types::ErrorExt;
@@ -59,9 +60,10 @@ async fn run() -> Result<(), String> {
// uniqueness check must happen before logging initializaton,
// as initializing logs will rotate any existing log file.
assert_unique().await?;
- let (log_dir, reload_handle) = init_daemon_logging(config)?;
+ let (log_location, reload_handle) = init_daemon_logging(config)?;
log::trace!("Using configuration: {:?}", config);
+ let log_dir = log_location.map(|l| l.directory);
run_standalone(log_dir, reload_handle).await
}
@@ -110,29 +112,36 @@ async fn assert_unique() -> Result<(), &'static str> {
/// Initialize logging to stderr and to file (if configured).
fn init_daemon_logging(
config: &cli::Config,
-) -> Result<(Option<PathBuf>, logging::LogHandle), String> {
- let log_dir = get_log_dir(config)?;
+) -> Result<(Option<LogLocation>, logging::LogHandle), String> {
+ let log_location = get_log_dir(config)?.map(|directory| LogLocation {
+ directory,
+ filename: PathBuf::from("daemon.log"),
+ });
- let reload_handle = init_logger(config, log_dir.clone())?;
+ let reload_handle = init_logger(config, log_location.clone())?;
- if let Some(ref log_dir) = log_dir {
- log::info!("Logging to {}", log_dir.display());
+ if let Some(log_location) = log_location.as_ref() {
+ log::info!("Logging to {}", log_location.log_path().display());
}
- Ok((log_dir, reload_handle))
+ Ok((log_location, reload_handle))
}
/// Initialize logging to stder and to the [`EARLY_BOOT_LOG_FILENAME`]
#[cfg(target_os = "linux")]
fn init_early_boot_logging(config: &cli::Config) {
+ let logging = get_log_dir(config)
+ .ok()
+ .flatten()
+ .map(|log_dir| LogLocation {
+ directory: log_dir,
+ filename: PathBuf::from(EARLY_BOOT_LOG_FILENAME),
+ });
+
// If it's possible to log to the filesystem - attempt to do so, but failing that mustn't stop
// the daemon from starting here.
- if let Ok(Some(log_dir)) = get_log_dir(config)
- && init_logger(config, Some(log_dir.join(EARLY_BOOT_LOG_FILENAME))).is_ok()
- {
- return;
- }
-
- let _ = init_logger(config, None);
+ if init_logger(config, logging).is_err() {
+ let _ = init_logger(config, None);
+ };
}
/// Initialize logging to stderr and to file (if provided).
@@ -140,26 +149,23 @@ fn init_early_boot_logging(config: &cli::Config) {
/// Also install the [exception_logging] signal handler to log faults.
fn init_logger(
config: &cli::Config,
- log_file: Option<PathBuf>,
+ log_location: Option<LogLocation>,
) -> Result<logging::LogHandle, String> {
#[cfg(unix)]
- if let Some(log_file) = &log_file {
+ if let Some(log_location) = log_location.as_ref() {
use std::os::unix::ffi::OsStrExt;
exception_logging::set_log_file(
- std::ffi::CString::new(log_file.as_os_str().as_bytes())
+ std::ffi::CString::new(log_location.log_path().as_os_str().as_bytes())
.map_err(|_| "Log file path contains null-bytes".to_string())?,
);
}
exception_logging::enable();
- let reload_handle = logging::init_logger(
- config.log_level,
- log_file.as_ref(),
- config.log_stdout_timestamps,
- )
- .map_err(|e| e.display_chain_with_msg("Unable to initialize logger"))?;
+ let reload_handle =
+ logging::init_logger(config.log_level, log_location, config.log_stdout_timestamps)
+ .map_err(|e| e.display_chain_with_msg("Unable to initialize logger"))?;
log_panics::init();
version::log_version();
Ok(reload_handle)
diff --git a/mullvad-daemon/src/system_service.rs b/mullvad-daemon/src/system_service.rs
index a45fd01ebb..6425779d6f 100644
--- a/mullvad-daemon/src/system_service.rs
+++ b/mullvad-daemon/src/system_service.rs
@@ -62,7 +62,7 @@ windows_service::define_windows_service!(service_main, handle_service_main);
pub fn handle_service_main(_arguments: Vec<OsString>) {
let config = cli::get_config();
- let (log_dir, reload_handle) =
+ let (log_location, reload_handle) =
init_daemon_logging(config).expect("Failed to initialize logging");
log::info!("Service started.");
@@ -115,7 +115,10 @@ pub fn handle_service_main(_arguments: Vec<OsString>) {
Ok(runtime) => runtime,
};
- let result = runtime.block_on(crate::create_daemon(log_dir, reload_handle));
+ let result = runtime.block_on(crate::create_daemon(
+ log_location.map(|l| l.directory),
+ reload_handle,
+ ));
let result = if let Ok(daemon) = result {
let shutdown_handle = daemon.shutdown_handle();
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index a23e408976..17d3ef47e6 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -14,7 +14,10 @@ use jnix::{
use mullvad_api::ApiEndpoint;
use mullvad_daemon::{
Daemon, DaemonCommandChannel, DaemonCommandSender, DaemonConfig, cleanup_old_rpc_socket,
- exception_logging, logging, logging::LogHandle, runtime::new_multi_thread, version,
+ exception_logging, logging,
+ logging::{LogHandle, LogLocation},
+ runtime::new_multi_thread,
+ version,
};
use std::collections::HashMap;
use std::{
@@ -26,8 +29,6 @@ use std::{
};
use talpid_types::{ErrorExt, android::AndroidContext};
-const LOG_FILENAME: &str = "daemon.log";
-
/// Mullvad daemon instance. It must be initialized and destroyed by `MullvadDaemon.initialize` and
/// `MullvadDaemon.shutdown`, respectively.
static DAEMON_CONTEXT: Mutex<Option<DaemonContext>> = Mutex::new(None);
@@ -223,15 +224,18 @@ async fn spawn_daemon_inner(
}
fn start_logging(log_dir: &Path) -> Result<LogHandle, String> {
- let log_file = log_dir.join(LOG_FILENAME);
+ let log_location = LogLocation {
+ directory: log_dir.to_owned(),
+ filename: PathBuf::from("daemon.log"),
+ };
+ let exception_log_path = CString::new(log_location.log_path().as_os_str().as_bytes())
+ .map_err(|_| "Log file path contained interior null bytes: {log_file:?}")?;
- let log_handle = logging::init_logger(log::LevelFilter::Debug, Some(&log_file), true)
+ let log_handle = logging::init_logger(log::LevelFilter::Debug, Some(log_location), true)
.map_err(|e| e.display_chain())?;
+
log_panics::init();
- exception_logging::set_log_file(
- CString::new(log_file.as_os_str().as_bytes())
- .map_err(|_| "Log file path contained interior null bytes: {log_file:?}")?,
- );
+ exception_logging::set_log_file(exception_log_path);
exception_logging::enable();
Ok(log_handle)
diff --git a/talpid-core/src/logging/mod.rs b/talpid-core/src/logging/mod.rs
index 016f3b2cc3..e4a0023b05 100644
--- a/talpid-core/src/logging/mod.rs
+++ b/talpid-core/src/logging/mod.rs
@@ -23,5 +23,6 @@ pub fn rotate_log(file: &Path) -> Result<(), RotateLogError> {
);
}
- fs::File::create(file).map(|_| ()).map_err(RotateLogError)
+ fs::File::create(file).map_err(RotateLogError)?;
+ Ok(())
}