aboutsummaryrefslogtreecommitdiff
path: root/src/logging.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/logging.rs')
-rw-r--r--src/logging.rs173
1 files changed, 70 insertions, 103 deletions
diff --git a/src/logging.rs b/src/logging.rs
index 1f51d2b2..0b1d25a4 100644
--- a/src/logging.rs
+++ b/src/logging.rs
@@ -17,85 +17,52 @@
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
-use crate::cli;
-use log::{self, Level};
-use time;
-
use std::env;
-use std::fs::{self, File, OpenOptions};
+use std::fs::{File, OpenOptions};
use std::io::{self, LineWriter, Stdout, Write};
use std::path::PathBuf;
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
-pub fn initialize(options: &cli::Options) -> Result<LoggerProxy, log::SetLoggerError> {
+use crossbeam_channel::Sender;
+use log::{self, Level};
+use time;
+
+use crate::cli;
+use crate::message_bar::Message;
+use crate::term::color;
+
+const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG";
+
+pub fn initialize(
+ options: &cli::Options,
+ message_tx: Sender<Message>,
+) -> Result<Option<PathBuf>, log::SetLoggerError> {
// Use env_logger if RUST_LOG environment variable is defined. Otherwise,
// use the alacritty-only logger.
if ::std::env::var("RUST_LOG").is_ok() {
::env_logger::try_init()?;
- Ok(LoggerProxy::default())
+ Ok(None)
} else {
- let logger = Logger::new(options.log_level);
- let proxy = logger.proxy();
-
+ let logger = Logger::new(options.log_level, message_tx);
+ let path = logger.file_path();
log::set_boxed_logger(Box::new(logger))?;
-
- Ok(proxy)
+ Ok(path)
}
}
-/// Proxy object for bidirectional communicating with the global logger.
-#[derive(Clone, Default)]
-pub struct LoggerProxy {
- errors: Arc<AtomicBool>,
- warnings: Arc<AtomicBool>,
- logfile_proxy: OnDemandLogFileProxy,
-}
-
-impl LoggerProxy {
- /// Check for new logged errors.
- pub fn errors(&self) -> bool {
- self.errors.load(Ordering::Relaxed)
- }
-
- /// Check for new logged warnings.
- pub fn warnings(&self) -> bool {
- self.warnings.load(Ordering::Relaxed)
- }
-
- /// Get the path of the log file if it has been created.
- pub fn log_path(&self) -> Option<&str> {
- if self.logfile_proxy.created.load(Ordering::Relaxed) {
- Some(&self.logfile_proxy.path)
- } else {
- None
- }
- }
-
- /// Clear log warnings/errors from the Alacritty UI.
- pub fn clear(&mut self) {
- self.errors.store(false, Ordering::Relaxed);
- self.warnings.store(false, Ordering::Relaxed);
- }
-
- pub fn delete_log(&mut self) {
- self.logfile_proxy.delete_log();
- }
-}
-
-struct Logger {
+pub struct Logger {
level: log::LevelFilter,
logfile: Mutex<OnDemandLogFile>,
stdout: Mutex<LineWriter<Stdout>>,
- errors: Arc<AtomicBool>,
- warnings: Arc<AtomicBool>,
+ message_tx: Sender<Message>,
}
impl Logger {
// False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734
#[allow(clippy::new_ret_no_self)]
- fn new(level: log::LevelFilter) -> Self {
+ fn new(level: log::LevelFilter, message_tx: Sender<Message>) -> Self {
log::set_max_level(level);
let logfile = Mutex::new(OnDemandLogFile::new());
@@ -105,16 +72,15 @@ impl Logger {
level,
logfile,
stdout,
- errors: Arc::new(AtomicBool::new(false)),
- warnings: Arc::new(AtomicBool::new(false)),
+ message_tx,
}
}
- fn proxy(&self) -> LoggerProxy {
- LoggerProxy {
- errors: self.errors.clone(),
- warnings: self.warnings.clone(),
- logfile_proxy: self.logfile.lock().expect("").proxy(),
+ fn file_path(&self) -> Option<PathBuf> {
+ if let Ok(logfile) = self.logfile.lock() {
+ Some(logfile.path().clone())
+ } else {
+ None
}
}
}
@@ -125,61 +91,62 @@ impl log::Log for Logger {
}
fn log(&self, record: &log::Record<'_>) {
- if self.enabled(record.metadata()) &&
- record.target().starts_with("alacritty")
- {
+ if self.enabled(record.metadata()) && record.target().starts_with("alacritty") {
let now = time::strftime("%F %R", &time::now()).unwrap();
let msg = if record.level() >= Level::Trace {
- format!("[{}] [{}] [{}:{}] {}\n",
- now,
- record.level(),
- record.file().unwrap_or("?"),
- record.line()
- .map(|l| l.to_string())
- .unwrap_or_else(|| "?".into()),
- record.args())
+ format!(
+ "[{}] [{}] [{}:{}] {}\n",
+ now,
+ record.level(),
+ record.file().unwrap_or("?"),
+ record
+ .line()
+ .map(|l| l.to_string())
+ .unwrap_or_else(|| "?".into()),
+ record.args()
+ )
} else {
- format!("[{}] [{}] {}\n",
- now,
- record.level(),
- record.args())
+ format!("[{}] [{}] {}\n", now, record.level(), record.args())
};
if let Ok(ref mut logfile) = self.logfile.lock() {
let _ = logfile.write_all(msg.as_ref());
+
+ if record.level() <= Level::Warn {
+ #[cfg(not(windows))]
+ let env_var = format!("${}", ALACRITTY_LOG_ENV);
+ #[cfg(windows)]
+ let env_var = format!("%{}%", ALACRITTY_LOG_ENV);
+
+ let msg = format!(
+ "[{}] See log at {} ({}):\n{}",
+ record.level(),
+ logfile.path.to_string_lossy(),
+ env_var,
+ record.args(),
+ );
+ let color = match record.level() {
+ Level::Error => color::RED,
+ Level::Warn => color::YELLOW,
+ _ => unreachable!(),
+ };
+
+ let mut message = Message::new(msg, color);
+ message.set_topic(record.file().unwrap_or("?").into());
+ let _ = self.message_tx.send(message);
+ }
}
if let Ok(ref mut stdout) = self.stdout.lock() {
let _ = stdout.write_all(msg.as_ref());
}
-
- match record.level() {
- Level::Error => self.errors.store(true, Ordering::Relaxed),
- Level::Warn => self.warnings.store(true, Ordering::Relaxed),
- _ => (),
- }
}
}
fn flush(&self) {}
}
-#[derive(Clone, Default)]
-struct OnDemandLogFileProxy {
- created: Arc<AtomicBool>,
- path: String,
-}
-
-impl OnDemandLogFileProxy {
- fn delete_log(&mut self) {
- if self.created.load(Ordering::Relaxed) && fs::remove_file(&self.path).is_ok() {
- let _ = writeln!(io::stdout(), "Deleted log file at {:?}", self.path);
- self.created.store(false, Ordering::Relaxed);
- }
- }
-}
-
struct OnDemandLogFile {
file: Option<LineWriter<File>>,
created: Arc<AtomicBool>,
@@ -191,6 +158,9 @@ impl OnDemandLogFile {
let mut path = env::temp_dir();
path.push(format!("Alacritty-{}.log", process::id()));
+ // Set log path as an environment variable
+ env::set_var(ALACRITTY_LOG_ENV, path.as_os_str());
+
OnDemandLogFile {
path,
file: None,
@@ -227,11 +197,8 @@ impl OnDemandLogFile {
Ok(self.file.as_mut().unwrap())
}
- fn proxy(&self) -> OnDemandLogFileProxy {
- OnDemandLogFileProxy {
- created: self.created.clone(),
- path: self.path.to_string_lossy().to_string(),
- }
+ fn path(&self) -> &PathBuf {
+ &self.path
}
}