Replace old logging module with the log create

This commit is contained in:
Manos Pitsidianakis 2023-05-01 16:22:35 +03:00
parent 30cc5d3d02
commit 85d4316a6a
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0
25 changed files with 428 additions and 401 deletions

1
Cargo.lock generated
View File

@ -1178,6 +1178,7 @@ dependencies = [
"isahc",
"libc",
"libloading",
"log",
"mailin-embedded",
"native-tls",
"nix",

View File

@ -1448,8 +1448,6 @@ Available levels are, in partial order:
.It
.Em OFF
.It
.Em FATAL
.It
.Em ERROR
.It
.Em WARN

View File

@ -20,6 +20,7 @@ name = "melib"
path = "src/lib.rs"
[dependencies]
log = { version = "0.4", features = ["std"]}
async-stream = "^0.3"
base64 = { version = "^0.13", optional = true }
bincode = { version = "^1.3.0", default-features = false }

View File

@ -120,12 +120,10 @@ impl AddressBook {
}
}
Err(err) => {
crate::log(
format!(
"Could not load mutt alias file {:?}: {}",
mutt_alias_file, err
),
crate::WARN,
log::warn!(
"Could not load mutt alias file {:?}: {}",
mutt_alias_file,
err
);
}
}
@ -139,10 +137,7 @@ impl AddressBook {
}
}
Err(err) => {
crate::log(
format!("Could not load vcards from {:?}: {}", vcard_path, err),
crate::WARN,
);
log::warn!("Could not load vcards from {:?}: {}", vcard_path, err);
}
}
}

View File

@ -305,10 +305,7 @@ pub fn load_cards(p: &std::path::Path) -> Result<Vec<Card>> {
}
}
Err(err) => {
crate::log(
format!("Could not parse vcard from {}: {}", f.display(), err),
crate::WARN,
);
log::warn!("Could not parse vcard from {}: {}", f.display(), err);
}
}
}

View File

@ -62,6 +62,7 @@ use super::email::{Envelope, EnvelopeHash, Flag};
use crate::{
conf::AccountSettings,
error::{Error, ErrorKind, Result},
LogLevel,
};
#[macro_export]
@ -261,7 +262,7 @@ pub enum BackendEvent {
Notice {
description: String,
content: Option<String>,
level: crate::LoggingLevel,
level: LogLevel,
},
Refresh(RefreshEvent),
AccountStateChange {
@ -275,7 +276,7 @@ impl From<Error> for BackendEvent {
BackendEvent::Notice {
description: val.summary.to_string(),
content: Some(val.to_string()),
level: crate::LoggingLevel::ERROR,
level: LogLevel::ERROR,
}
}
}

View File

@ -753,13 +753,10 @@ impl MailBackend for ImapType {
cmd.push_str("\\Draft ");
}
Ok(_) => {
crate::log(
format!(
"Application error: more than one flag bit set in \
set_flags: {:?}",
flags
),
crate::ERROR,
log::error!(
"Application error: more than one flag bit set in set_flags: \
{:?}",
flags
);
return Err(Error::new(format!(
"Application error: more than one flag bit set in set_flags: \
@ -826,13 +823,10 @@ impl MailBackend for ImapType {
cmd.push_str("\\Draft ");
}
Ok(_) => {
crate::log(
format!(
"Application error: more than one flag bit set in \
set_flags: {:?}",
flags
),
crate::ERROR,
log::error!(
"Application error: more than one flag bit set in set_flags: \
{:?}",
flags
);
return Err(Error::new(format!(
"Application error: more than one flag bit set in set_flags: \
@ -1716,23 +1710,18 @@ async fn fetch_hlpr(state: &mut FetchState) -> Result<Vec<Envelope>> {
FetchStage::InitialCache => {
match cache::fetch_cached_envs(state).await {
Err(err) => {
crate::log(
format!(
"IMAP cache error: could not fetch cache for {}. Reason: {}",
state.uid_store.account_name, err
),
crate::ERROR,
log::error!(
"IMAP cache error: could not fetch cache for {}. Reason: {}",
state.uid_store.account_name,
err
);
/* Try resetting the database */
if let Some(ref mut cache_handle) = state.cache_handle {
if let Err(err) = cache_handle.reset() {
crate::log(
format!(
"IMAP cache error: could not reset cache for {}. Reason: \
{}",
state.uid_store.account_name, err
),
crate::ERROR,
log::error!(
"IMAP cache error: could not reset cache for {}. Reason: {}",
state.uid_store.account_name,
err
);
}
}

View File

@ -25,6 +25,7 @@ use crate::{
connections::{lookup_ipv4, timeout, Connection},
email::parser::BytesExt,
error::*,
LogLevel,
};
extern crate native_tls;
use std::{
@ -260,10 +261,7 @@ impl ImapStream {
.get_ref()
.set_keepalive(Some(Duration::new(60 * 9, 0)))
{
crate::log(
format!("Could not set TCP keepalive in IMAP connection: {}", err),
crate::LoggingLevel::WARN,
);
log::warn!("Could not set TCP keepalive in IMAP connection: {}", err);
}
let mut res = Vec::with_capacity(8 * 1024);
let mut ret = ImapStream {
@ -658,13 +656,11 @@ impl ImapConnection {
| ImapResponse::Bad(code)
| ImapResponse::Preauth(code)
| ImapResponse::Bye(code) => {
crate::log(
format!(
"Could not use COMPRESS=DEFLATE in account `{}`: server \
replied with `{}`",
self.uid_store.account_name, code
),
crate::LoggingLevel::WARN,
log::warn!(
"Could not use COMPRESS=DEFLATE in account `{}`: server \
replied with `{}`",
self.uid_store.account_name,
code
);
}
ImapResponse::Ok(_) => {
@ -737,7 +733,7 @@ impl ImapConnection {
crate::backends::BackendEvent::Notice {
description: response_code.to_string(),
content: None,
level: crate::logging::LoggingLevel::ERROR,
level: LogLevel::ERROR,
},
);
ret.extend_from_slice(&response);
@ -754,7 +750,7 @@ impl ImapConnection {
crate::backends::BackendEvent::Notice {
description: response_code.to_string(),
content: None,
level: crate::logging::LoggingLevel::ERROR,
level: LogLevel::ERROR,
},
);
ret.extend_from_slice(&response);

View File

@ -287,7 +287,7 @@ impl ImapConnection {
)
})
{
crate::log(err.to_string(), crate::INFO);
log::info!("{err}");
}
}
for response in v {
@ -391,7 +391,7 @@ impl ImapConnection {
)
})
{
crate::log(err.to_string(), crate::INFO);
log::info!("{err}");
}
}
for response in v {

View File

@ -24,6 +24,7 @@ use crate::{
connections::{lookup_ipv4, Connection},
email::parser::BytesExt,
error::*,
log,
};
extern crate native_tls;
use std::{collections::HashSet, future::Future, pin::Pin, sync::Arc, time::Instant};
@ -199,10 +200,7 @@ impl NntpStream {
.get_ref()
.set_keepalive(Some(std::time::Duration::new(60 * 9, 0)))
{
crate::log(
format!("Could not set TCP keepalive in NNTP connection: {}", err),
crate::LoggingLevel::WARN,
);
log::warn!("Could not set TCP keepalive in NNTP connection: {}", err);
}
ret.read_response(&mut res, false, &["200 ", "201 "])

View File

@ -43,41 +43,20 @@
//! - A `ShellExpandTrait` to expand paths like a shell.
//! - A `debug` macro that works like `std::dbg` but for multiple threads. (see
//! [`debug` macro](./macro.debug.html))
#[macro_use]
pub mod dbg {
#[macro_export]
macro_rules! log_tag {
() => {
eprint!(
"[{}][{:?}] {}:{}_{}: ",
$crate::datetime::timestamp_to_string(
$crate::datetime::now(),
Some("%Y-%m-%d %T"),
false
),
std::thread::current()
.name()
.map(std::string::ToString::to_string)
.unwrap_or_else(|| format!("{:?}", std::thread::current().id())),
file!(),
line!(),
column!()
);
};
}
#[allow(clippy::redundant_closure)]
#[macro_export]
macro_rules! debug {
($val:literal) => {
{
if cfg!(feature="debug-tracing") {
log_tag!();
eprintln!($val);
if cfg!(feature="debug-tracing") {
$crate::log::debug!($val);
}
$val
}
$val
}
};
($val:expr) => {
if cfg!(feature="debug-tracing") {
@ -86,8 +65,7 @@ pub mod dbg {
// of temporaries - https://stackoverflow.com/a/48732525/1063961
match $val {
tmp => {
log_tag!();
eprintln!("{} = {:?}", stringify, tmp);
$crate::log::debug!("{} = {:?}", stringify, tmp);
tmp
}
}
@ -97,8 +75,7 @@ pub mod dbg {
};
($fmt:literal, $($arg:tt)*) => {
if cfg!(feature="debug-tracing") {
log_tag!();
eprintln!($fmt, $($arg)*);
$crate::log::debug!($fmt, $($arg)*);
}
};
}
@ -112,7 +89,7 @@ pub use datetime::UnixTimestamp;
#[macro_use]
mod logging;
pub use self::logging::{LoggingLevel::*, *};
pub use self::logging::{LogLevel, StderrLogger};
pub mod addressbook;
pub use addressbook::*;
@ -142,6 +119,7 @@ pub mod sqlite3;
#[macro_use]
extern crate serde_derive;
pub extern crate log;
/* parser */
extern crate data_encoding;
extern crate encoding;

View File

@ -23,30 +23,98 @@ use std::{
fs::OpenOptions,
io::{BufWriter, Write},
path::PathBuf,
sync::{Arc, Mutex},
sync::{
atomic::{AtomicU8, Ordering},
Arc, Mutex,
},
};
use log::{Level, LevelFilter, Log, Metadata, Record};
use crate::shellexpand::ShellExpandTrait;
#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub enum LoggingLevel {
OFF,
FATAL,
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
#[repr(u8)]
pub enum LogLevel {
OFF = 0,
ERROR,
WARN,
#[default]
INFO,
DEBUG,
TRACE,
}
impl std::fmt::Display for LoggingLevel {
impl From<u8> for LogLevel {
fn from(verbosity: u8) -> Self {
match verbosity {
0 => LogLevel::OFF,
1 => LogLevel::ERROR,
2 => LogLevel::WARN,
3 => LogLevel::INFO,
4 => LogLevel::DEBUG,
_ => LogLevel::TRACE,
}
}
}
impl From<Level> for LogLevel {
fn from(l: Level) -> Self {
match l {
Level::Error => Self::ERROR,
Level::Warn => Self::WARN,
Level::Info => Self::INFO,
Level::Debug => Self::DEBUG,
Level::Trace => Self::TRACE,
}
}
}
impl From<LogLevel> for Level {
fn from(l: LogLevel) -> Self {
match l {
LogLevel::ERROR => Self::Error,
LogLevel::WARN => Self::Warn,
LogLevel::OFF | LogLevel::INFO => Self::Info,
LogLevel::DEBUG => Self::Debug,
LogLevel::TRACE => Self::Trace,
}
}
}
impl From<LevelFilter> for LogLevel {
fn from(l: LevelFilter) -> Self {
match l {
LevelFilter::Off => Self::OFF,
LevelFilter::Error => Self::ERROR,
LevelFilter::Warn => Self::WARN,
LevelFilter::Info => Self::INFO,
LevelFilter::Debug => Self::DEBUG,
LevelFilter::Trace => Self::TRACE,
}
}
}
impl From<LogLevel> for LevelFilter {
fn from(l: LogLevel) -> Self {
match l {
LogLevel::OFF => Self::Off,
LogLevel::ERROR => Self::Error,
LogLevel::WARN => Self::Warn,
LogLevel::INFO => Self::Info,
LogLevel::DEBUG => Self::Debug,
LogLevel::TRACE => Self::Trace,
}
}
}
impl std::fmt::Display for LogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match self {
OFF => "OFF",
FATAL => "FATAL",
ERROR => "ERROR",
WARN => "WARN",
INFO => "INFO",
@ -57,73 +125,173 @@ impl std::fmt::Display for LoggingLevel {
}
}
impl Default for LoggingLevel {
fn default() -> Self {
LoggingLevel::INFO
use LogLevel::*;
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub enum Destination {
File,
#[default]
Stderr,
None,
}
#[derive(Clone)]
pub struct StderrLogger {
dest: Arc<Mutex<BufWriter<std::fs::File>>>,
level: Arc<AtomicU8>,
print_level: bool,
print_module_names: bool,
debug_dest: Destination,
}
impl std::fmt::Debug for StderrLogger {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(stringify!(StderrLogger))
.field("level", &LogLevel::from(self.level.load(Ordering::SeqCst)))
.field("print_level", &self.print_level)
.field("print_module_names", &self.print_module_names)
.field("debug_dest", &self.debug_dest)
.finish()
}
}
use LoggingLevel::*;
struct LoggingBackend {
dest: BufWriter<std::fs::File>,
level: LoggingLevel,
impl Default for StderrLogger {
fn default() -> Self {
Self::new(LogLevel::default())
}
}
thread_local!(static LOG: Arc<Mutex<LoggingBackend>> = Arc::new(Mutex::new({
let data_dir = xdg::BaseDirectories::with_prefix("meli").unwrap();
let log_file = OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */
.create(true) /* a new file will be created if the file does not yet already exist.*/
.read(true)
.open(data_dir.place_data_file("meli.log").unwrap()).unwrap();
LoggingBackend {
dest: BufWriter::new(log_file),
level: LoggingLevel::default(),
}}))
);
impl StderrLogger {
pub fn new(level: LogLevel) -> Self {
let logger = {
let data_dir = xdg::BaseDirectories::with_prefix("meli").unwrap();
let log_file = OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */
.create(true) /* a new file will be created if the file does not yet already exist.*/
.read(true)
.open(data_dir.place_data_file("meli.log").unwrap()).unwrap();
StderrLogger {
dest: Arc::new(Mutex::new(BufWriter::new(log_file).into())),
level: Arc::new(AtomicU8::new(level as u8)),
print_level: true,
print_module_names: true,
#[cfg(feature = "debug-tracing")]
debug_dest: Destination::Stderr,
#[cfg(not(feature = "debug-tracing"))]
debug_dest: Destination::None,
}
};
pub fn log<S: AsRef<str>>(val: S, level: LoggingLevel) {
LOG.with(|f| {
let mut b = f.lock().unwrap();
if level <= b.level {
b.dest
#[cfg(feature = "debug-tracing")]
log::set_max_level(
if matches!(LevelFilter::from(logger.log_level()), LevelFilter::Off) {
LevelFilter::Off
} else {
LevelFilter::Trace
},
);
#[cfg(not(feature = "debug-tracing"))]
log::set_max_level(LevelFilter::from(logger.log_level()));
log::set_boxed_logger(Box::new(logger.clone())).unwrap();
logger
}
pub fn log_level(&self) -> LogLevel {
self.level.load(Ordering::SeqCst).into()
}
pub fn change_log_dest(&mut self, path: PathBuf) {
let path = path.expand(); // expand shell stuff
let mut dest = self.dest.lock().unwrap();
*dest = BufWriter::new(OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */
.create(true) /* a new file will be created if the file does not yet already exist.*/
.read(true)
.open(path).unwrap()).into();
}
}
impl Log for StderrLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
!["polling", "async_io"]
.iter()
.any(|t| metadata.target().starts_with(t))
&& (metadata.level() <= Level::from(self.log_level())
|| !matches!(self.debug_dest, Destination::None))
//metadata.level() <= self.log_level_filter() &&
// self.includes_module(metadata.target())
}
fn log(&self, record: &Record) {
if !self.enabled(record.metadata()) {
return;
}
fn write(
writer: &mut impl Write,
record: &Record,
(print_level, print_module_names): (bool, bool),
) -> Option<()> {
writer
.write_all(
crate::datetime::timestamp_to_string(crate::datetime::now(), None, false)
.as_bytes(),
)
.unwrap();
b.dest.write_all(b" [").unwrap();
b.dest.write_all(level.to_string().as_bytes()).unwrap();
b.dest.write_all(b"]: ").unwrap();
b.dest.write_all(val.as_ref().as_bytes()).unwrap();
b.dest.write_all(b"\n").unwrap();
b.dest.flush().unwrap();
.ok()?;
writer.write_all(b" [").ok()?;
if print_level {
writer
.write_all(record.level().to_string().as_bytes())
.ok()?;
}
write!(writer, "]: ").ok()?;
if print_module_names {
write!(writer, "{}: ", record.metadata().target()).ok()?;
}
write!(writer, "{}", record.args()).ok()?;
writer.write_all(b"\n").ok()?;
writer.flush().ok()?;
Some(())
}
});
}
pub fn get_log_level() -> LoggingLevel {
let mut level = INFO;
LOG.with(|f| {
level = f.lock().unwrap().level;
});
level
}
// if logging isn't enabled for this level do a quick out
match (
self.debug_dest,
record.metadata().level() <= Level::from(self.log_level()),
) {
(Destination::None, false) => return,
(Destination::None | Destination::File, _) => {
_ = self.dest.lock().ok().and_then(|mut d| {
write(
&mut (*d),
record,
(self.print_level, self.print_module_names),
)
});
}
(Destination::Stderr, true) => {
_ = self.dest.lock().ok().and_then(|mut d| {
write(
&mut (*d),
record,
(self.print_level, self.print_module_names),
)
});
_ = write(
&mut std::io::stderr(),
record,
(self.print_level, self.print_module_names),
);
}
(Destination::Stderr, false) => {
_ = write(
&mut std::io::stderr(),
record,
(self.print_level, self.print_module_names),
);
}
}
}
pub fn change_log_dest(path: PathBuf) {
LOG.with(|f| {
let path = path.expand(); // expand shell stuff
let mut backend = f.lock().unwrap();
backend.dest = BufWriter::new(OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */
.create(true) /* a new file will be created if the file does not yet already exist.*/
.read(true)
.open(path).unwrap());
});
}
pub fn change_log_level(new_val: LoggingLevel) {
LOG.with(|f| {
let mut backend = f.lock().unwrap();
backend.level = new_val;
});
fn flush(&self) {
self.dest.lock().ok().and_then(|mut w| w.flush().ok());
}
}

View File

@ -24,7 +24,7 @@ use std::path::PathBuf;
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput};
pub use rusqlite::{self, params, Connection};
use crate::{error::*, logging::log, Envelope};
use crate::{error::*, log, Envelope};
#[derive(Copy, Clone, Debug)]
pub struct DatabaseDescription {
@ -61,13 +61,10 @@ pub fn open_or_create_db(
}?;
let mut set_mode = false;
if !db_path.exists() {
log(
format!(
"Creating {} database in {}",
description.name,
db_path.display()
),
crate::INFO,
log::info!(
"Creating {} database in {}",
description.name,
db_path.display()
);
set_mode = true;
}
@ -83,12 +80,10 @@ pub fn open_or_create_db(
}
let version: i32 = conn.pragma_query_value(None, "user_version", |row| row.get(0))?;
if version != 0_i32 && version as u32 != description.version {
log(
format!(
"Database version mismatch, is {} but expected {}",
version, description.version
),
crate::INFO,
log::info!(
"Database version mismatch, is {} but expected {}",
version,
description.version
);
if second_try {
return Err(Error::new(format!(
@ -124,13 +119,10 @@ pub fn reset_db(description: &DatabaseDescription, identifier: Option<&str>) ->
if !db_path.exists() {
return Ok(());
}
log(
format!(
"Resetting {} database in {}",
description.name,
db_path.display()
),
crate::INFO,
log::info!(
"Resetting {} database in {}",
description.name,
db_path.display()
);
std::fs::remove_file(&db_path)?;
Ok(())

View File

@ -1748,12 +1748,9 @@ impl Component for Composer {
}
let editor_command = format!("{} {}", editor, f.path().display());
log(
format!(
"Executing: sh -c \"{}\"",
editor_command.replace('"', "\\\"")
),
DEBUG,
log::debug!(
"Executing: sh -c \"{}\"",
editor_command.replace('"', "\\\"")
);
match Command::new("sh")
.args(["-c", &editor_command])
@ -1893,10 +1890,7 @@ impl Component for Composer {
context.input_kill();
}
log(
format!("Executing: sh -c \"{}\"", command.replace('"', "\\\"")),
DEBUG,
);
log::debug!("Executing: sh -c \"{}\"", command.replace('"', "\\\""));
match Command::new("sh")
.args(["-c", command])
.stdin(Stdio::inherit())
@ -2170,13 +2164,9 @@ pub fn send_draft(
match output {
Err(err) => {
debug!("{:?} could not sign draft msg", err);
log(
format!(
"Could not sign draft in account `{}`: {}.",
log::error!(
"Could not sign draft in account `{}`: {err}.",
context.accounts[&account_hash].name(),
err.to_string()
),
ERROR,
);
context.replies.push_back(UIEvent::Notification(
Some(format!(
@ -2358,12 +2348,9 @@ pub fn send_draft_async(
.unwrap();
} else if !store_sent_mail && is_ok {
let f = create_temp_file(message.as_bytes(), None, None, false);
log(
format!(
"store_sent_mail is false; stored sent mail to {}",
f.path().display()
),
INFO,
log::info!(
"store_sent_mail is false; stored sent mail to {}",
f.path().display()
);
}
ret

View File

@ -557,7 +557,7 @@ pub trait MailListingTrait: ListingTrait {
name: "message copying".into(),
handle,
on_finish: None,
logging_level: melib::LoggingLevel::INFO,
log_level: LogLevel::INFO,
},
);
}
@ -594,7 +594,7 @@ pub trait MailListingTrait: ListingTrait {
name: "message moving".into(),
handle,
on_finish: None,
logging_level: melib::LoggingLevel::INFO,
log_level: LogLevel::INFO,
},
);
}
@ -692,7 +692,7 @@ pub trait MailListingTrait: ListingTrait {
),
});
}))),
logging_level: melib::LoggingLevel::INFO,
log_level: LogLevel::INFO,
},
);
}

View File

@ -1426,7 +1426,7 @@ impl CompactListing {
"Encountered an error while searching for `{}`: {}.",
search_term, &err
);
log(message.clone(), ERROR);
log::error!("{}", message);
context.replies.push_back(UIEvent::Notification(
Some("Could not perform search".to_string()),
message,

View File

@ -1501,7 +1501,7 @@ impl Component for MailView {
err.to_string(),
Some(NotificationType::Error(err.kind)),
));
log(format!("Failed to open envelope: {}", err), ERROR);
log::error!("Failed to open envelope: {err}");
self.init_futures(context);
return;
} else {
@ -2140,7 +2140,7 @@ impl Component for MailView {
.unwrap_or_else(|| "Not found".into()),
err
);
log(&err_string, ERROR);
log::error!("{err_string}");
context.replies.push_back(UIEvent::Notification(
Some("Failed to open e-mail".to_string()),
err_string,
@ -2151,7 +2151,7 @@ impl Component for MailView {
}
}
}))),
logging_level: melib::LoggingLevel::DEBUG,
log_level: LogLevel::DEBUG,
},
);
return true;
@ -2503,7 +2503,7 @@ impl Component for MailView {
err.to_string(),
Some(NotificationType::Error(err.kind)),
));
log(format!("Failed to open envelope: {}", err), ERROR);
log::error!("Failed to open envelope: {err}");
self.init_futures(context);
return true;
} else {
@ -2523,10 +2523,7 @@ impl Component for MailView {
err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)),
));
log(
format!("Failed to create file at {}: {}", path.display(), err),
ERROR,
);
log::error!("Failed to create file at {}: {err}", path.display());
return true;
}
Ok(()) => {
@ -2557,7 +2554,7 @@ impl Component for MailView {
err.to_string(),
Some(NotificationType::Error(err.kind)),
));
log(format!("Failed to open envelope: {}", err), ERROR);
log::error!("Failed to open envelope: {err}");
self.init_futures(context);
return true;
} else {
@ -2582,10 +2579,7 @@ impl Component for MailView {
err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)),
));
log(
format!("Failed to create file at {}: {}", path.display(), err),
ERROR,
);
log::error!("Failed to create file at {}: {err}", path.display());
}
Ok(()) => {
context.replies.push_back(UIEvent::Notification(
@ -2609,10 +2603,7 @@ impl Component for MailView {
err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)),
));
log(
format!("Failed to create file at {}: {}", path.display(), err),
ERROR,
);
log::error!("Failed to create file at {}: {err}", path.display());
return true;
}
Ok(()) => {

View File

@ -100,6 +100,7 @@ impl ThreadView {
view.new_cursor_pos = view.new_expanded_pos;
view
}
pub fn update(&mut self, context: &Context) {
if self.entries.is_empty() {
return;
@ -439,7 +440,6 @@ impl ThreadView {
copy_area(grid, &self.content, dest_area, src_area);
}
/// draw the list
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
let (upper_left, bottom_right) = area;
let (width, height) = self.content.size();
@ -492,8 +492,7 @@ impl ThreadView {
let page_no = (self.new_cursor_pos).wrapping_div(rows);
let top_idx = page_no * rows;
/* This closure (written for code clarity, should be inlined by the compiler)
* returns the **line** of an entry in the ThreadView grid. */
/* returns the **line** of an entry in the ThreadView grid. */
let get_entry_area = |idx: usize, entries: &[ThreadEntry]| {
let entries = &entries;
let visual_indentation = entries[idx].index.0 * 4;
@ -991,6 +990,7 @@ impl Component for ThreadView {
}
self.dirty = false;
}
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let UIEvent::Action(Listing(OpenInNewTab)) = event {
/* Handle this before self.mailview does */

View File

@ -117,11 +117,8 @@ mod dbus {
}
if let Err(err) = notification.show() {
debug!("Could not show dbus notification: {:?}", &err);
melib::log(
format!("Could not show dbus notification: {}", err),
melib::ERROR,
);
log::debug!("Could not show dbus notification: {:?}", &err);
log::error!("Could not show dbus notification: {err}");
}
}
false
@ -194,8 +191,8 @@ impl Component for NotificationCommand {
if *kind == Some(NotificationType::NewMail) {
if let Some(ref path) = context.settings.notifications.xbiff_file_path {
if let Err(err) = update_xbiff(path) {
debug!("Could not update xbiff file: {:?}", &err);
melib::log(format!("Could not update xbiff file: {}.", err), ERROR);
log::debug!("Could not update xbiff file: {:?}", &err);
log::error!("Could not update xbiff file: {err}.");
}
}
}
@ -220,11 +217,8 @@ impl Component for NotificationCommand {
context.children.push(child);
}
Err(err) => {
log(
format!("Could not run notification script: {}.", err),
ERROR,
);
debug!("Could not run notification script: {:?}", err);
log::error!("Could not run notification script: {err}.");
log::debug!("Could not run notification script: {:?}", err);
}
}
} else {
@ -256,11 +250,8 @@ impl Component for NotificationCommand {
return false;
}
Err(err) => {
log(
format!("Could not run notification script: {}.", err),
ERROR,
);
debug!("Could not run notification script: {:?}", err);
log::error!("Could not run notification script: {err}.");
log::debug!("Could not run notification script: {:?}", err);
}
}
}

View File

@ -32,7 +32,7 @@ use std::{
process::{Command, Stdio},
};
use melib::{backends::TagHash, search::Query};
use melib::{backends::TagHash, search::Query, StderrLogger};
use crate::{conf::deserializers::non_empty_string, terminal::Color};
@ -610,6 +610,8 @@ pub struct Settings {
pub pgp: PGPSettings,
pub terminal: TerminalSettings,
pub log: LogSettings,
#[serde(skip)]
_logger: StderrLogger,
}
impl Settings {
@ -624,11 +626,10 @@ impl Settings {
s.insert(id, ac);
}
let mut _logger = StderrLogger::new(fs.log.maximum_level);
if let Some(ref log_path) = fs.log.log_file {
melib::change_log_dest(log_path.into());
}
if fs.log.maximum_level != melib::LoggingLevel::default() {
melib::change_log_level(fs.log.maximum_level);
_logger.change_log_dest(log_path.into());
}
Ok(Settings {
@ -642,16 +643,16 @@ impl Settings {
pgp: fs.pgp,
terminal: fs.terminal,
log: fs.log,
_logger,
})
}
pub fn without_accounts() -> Result<Settings> {
let fs = FileSettings::new()?;
let mut _logger = StderrLogger::new(fs.log.maximum_level);
if let Some(ref log_path) = fs.log.log_file {
melib::change_log_dest(log_path.into());
}
if fs.log.maximum_level != melib::LoggingLevel::default() {
melib::change_log_level(fs.log.maximum_level);
_logger.change_log_dest(log_path.into());
}
Ok(Settings {
@ -665,6 +666,7 @@ impl Settings {
pgp: fs.pgp,
terminal: fs.terminal,
log: fs.log,
_logger,
})
}
}
@ -1015,7 +1017,7 @@ pub struct LogSettings {
#[serde(default)]
pub log_file: Option<PathBuf>,
#[serde(default)]
pub maximum_level: melib::LoggingLevel,
pub maximum_level: melib::LogLevel,
}
pub use dotaddressable::*;
@ -1047,7 +1049,7 @@ mod dotaddressable {
impl DotAddressable for crate::terminal::Key {}
impl DotAddressable for usize {}
impl DotAddressable for Query {}
impl DotAddressable for melib::LoggingLevel {}
impl DotAddressable for melib::LogLevel {}
impl DotAddressable for PathBuf {}
impl DotAddressable for ToggleFlag {}
impl DotAddressable for SearchBackend {}

View File

@ -47,9 +47,10 @@ use melib::{
backends::*,
email::*,
error::{Error, ErrorKind, Result},
log,
text_processing::GlobMatch,
thread::{SortField, SortOrder, Threads},
AddressBook, Collection,
AddressBook, Collection, LogLevel,
};
use smallvec::SmallVec;
@ -127,12 +128,10 @@ impl MailboxEntry {
ret.path = melib::backends::utf7::decode_utf7_imap(&ret.path);
}
Some(other) => {
melib::log(
format!(
"mailbox `{}`: unrecognized mailbox name charset: {}",
&ret.name, other
),
melib::WARN,
log::warn!(
"mailbox `{}`: unrecognized mailbox name charset: {}",
&ret.name,
other
);
}
}
@ -199,7 +198,7 @@ pub enum JobRequest {
},
Generic {
name: Cow<'static, str>,
logging_level: melib::LoggingLevel,
log_level: LogLevel,
handle: JoinHandle<Result<()>>,
on_finish: Option<crate::types::CallbackFn>,
},
@ -636,13 +635,11 @@ impl Account {
}
for missing_mailbox in &mailbox_conf_hash_set {
melib::log(
format!(
"Account `{}` mailbox `{}` configured but not present in account's mailboxes. \
Is it misspelled?",
&self.name, missing_mailbox,
),
melib::WARN,
log::warn!(
"Account `{}` mailbox `{}` configured but not present in account's mailboxes. Is \
it misspelled?",
&self.name,
missing_mailbox,
);
self.sender
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
@ -667,12 +664,10 @@ impl Account {
});
mailbox_comma_sep_list_string
.drain(mailbox_comma_sep_list_string.len().saturating_sub(2)..);
melib::log(
format!(
"Account `{}` has the following mailboxes: [{}]",
&self.name, mailbox_comma_sep_list_string,
),
melib::WARN,
log::warn!(
"Account `{}` has the following mailboxes: [{}]",
&self.name,
mailbox_comma_sep_list_string,
);
self.sender
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
@ -766,13 +761,10 @@ impl Account {
)
}) {
Err(err) => {
melib::log(
format!(
"Failed to update envelope {} in cache: {}",
envelope.message_id_display(),
err
),
melib::ERROR,
log::error!(
"Failed to update envelope {} in cache: {}",
envelope.message_id_display(),
err
);
}
Ok(job) => {
@ -786,7 +778,7 @@ impl Account {
)
.into(),
handle,
logging_level: melib::LoggingLevel::TRACE,
log_level: LogLevel::TRACE,
on_finish: None,
},
);
@ -833,20 +825,17 @@ impl Account {
)
.into(),
handle,
logging_level: melib::LoggingLevel::TRACE,
log_level: LogLevel::TRACE,
on_finish: None,
},
);
}
Err(err) => {
melib::log(
format!(
"Failed to update envelope {} in cache: {}",
self.collection.envelopes.read().unwrap()[&env_hash]
.message_id_display(),
err
),
melib::ERROR,
log::error!(
"Failed to update envelope {} in cache: {}",
self.collection.envelopes.read().unwrap()[&env_hash]
.message_id_display(),
err
);
}
}
@ -869,14 +858,11 @@ impl Account {
)
}) {
Err(err) => {
melib::log(
format!(
"Failed to update envelope {} in cache: {}",
&self.collection.envelopes.read().unwrap()[&new_hash]
.message_id_display(),
err
),
melib::ERROR,
log::error!(
"Failed to update envelope {} in cache: {}",
&self.collection.envelopes.read().unwrap()[&new_hash]
.message_id_display(),
err
);
}
Ok(job) => {
@ -891,7 +877,7 @@ impl Account {
)
.into(),
handle,
logging_level: melib::LoggingLevel::TRACE,
log_level: LogLevel::TRACE,
on_finish: None,
},
);
@ -934,7 +920,7 @@ impl Account {
)
.into(),
handle,
logging_level: melib::LoggingLevel::TRACE,
log_level: LogLevel::TRACE,
on_finish: None,
},
);
@ -996,14 +982,11 @@ impl Account {
if self.settings.conf.search_backend == crate::conf::SearchBackend::Sqlite3 {
if let Err(err) = crate::sqlite3::remove(env_hash) {
let envelopes = self.collection.envelopes.read().unwrap();
melib::log(
format!(
"Failed to remove envelope {} [{}] in cache: {}",
&envelopes[&env_hash].message_id_display(),
env_hash,
err
),
melib::ERROR,
log::error!(
"Failed to remove envelope {} [{}] in cache: {}",
&envelopes[&env_hash].message_id_display(),
env_hash,
err
);
}
}
@ -1235,10 +1218,7 @@ impl Account {
if let Some(mailbox_hash) = mailbox {
if let Err(err) = self.save(bytes, *mailbox_hash, Some(flags)) {
debug!("{:?} could not save msg", err);
melib::log(
format!("Could not save in '{}' mailbox: {}.", *mailbox_hash, err),
melib::ERROR,
);
log::error!("Could not save in '{}' mailbox: {}.", *mailbox_hash, err);
} else {
saved_at = Some(*mailbox_hash);
break;
@ -1253,12 +1233,9 @@ impl Account {
} else {
let file = crate::types::create_temp_file(bytes, None, None, false);
debug!("message saved in {}", file.path.display());
melib::log(
format!(
"Message was stored in {} so that you can restore it manually.",
file.path.display()
),
melib::INFO,
log::info!(
"Message was stored in {} so that you can restore it manually.",
file.path.display()
);
Err(Error::new(format!(
"Message was stored in {} so that you can restore it manually.",
@ -1336,7 +1313,7 @@ impl Account {
}
let output = msmtp.wait().expect("Failed to wait on mailer");
if output.success() {
melib::log("Message sent.", melib::LoggingLevel::TRACE);
log::trace!("Message sent.");
} else {
let error_message = if let Some(exit_code) = output.code() {
format!(
@ -1349,7 +1326,7 @@ impl Account {
command
)
};
melib::log(&error_message, melib::LoggingLevel::ERROR);
log::error!("{}", error_message);
return Err(Error::new(error_message).set_summary("Message not sent."));
}
Ok(None)
@ -1426,7 +1403,7 @@ impl Account {
}
let output = msmtp.wait().expect("Failed to wait on mailer");
if output.success() {
melib::log("Message sent.", melib::LoggingLevel::TRACE);
log::trace!("Message sent.");
} else {
let error_message = if let Some(exit_code) = output.code() {
format!(
@ -1440,7 +1417,7 @@ impl Account {
command
)
};
melib::log(&error_message, melib::LoggingLevel::ERROR);
log::error!("{}", error_message);
return Err(Error::new(error_message).set_summary("Message not sent."));
}
Ok(())
@ -1895,15 +1872,12 @@ impl Account {
..
} => {
if let Ok(Some(Err(err))) = handle.chan.try_recv() {
melib::log(format!("Could not save message: {}", err), melib::ERROR);
log::error!("Could not save message: {err}");
let file = crate::types::create_temp_file(bytes, None, None, false);
debug!("message saved in {}", file.path.display());
melib::log(
format!(
"Message was stored in {} so that you can restore it manually.",
file.path.display()
),
melib::INFO,
log::debug!("message saved in {}", file.path.display());
log::info!(
"Message was stored in {} so that you can restore it manually.",
file.path.display()
);
self.sender
.send(ThreadEvent::UIEvent(UIEvent::Notification(
@ -2199,7 +2173,7 @@ impl Account {
ref name,
ref mut handle,
ref mut on_finish,
logging_level,
log_level,
} => {
match handle.chan.try_recv() {
Ok(Some(Err(err))) => {
@ -2212,7 +2186,7 @@ impl Account {
.expect("Could not send event on main channel");
}
Ok(Some(Ok(()))) if on_finish.is_none() => {
if logging_level <= melib::LoggingLevel::INFO {
if log_level <= LogLevel::INFO {
self.sender
.send(ThreadEvent::UIEvent(UIEvent::Notification(
Some(format!("{}: {} succeeded", &self.name, name,)),

View File

@ -30,7 +30,7 @@ use std::{
process::{Command, Stdio},
};
use melib::{email::Attachment, text_processing::GlobMatch, Error, Result};
use melib::{email::Attachment, log, text_processing::GlobMatch, Error, Result};
use crate::{
state::Context,
@ -186,10 +186,7 @@ impl MailcapEntry {
})
.collect::<Vec<String>>();
let cmd_string = format!("{} {}", cmd, args.join(" "));
melib::log(
format!("Executing: sh -c \"{}\"", cmd_string.replace('"', "\\\"")),
melib::DEBUG,
);
log::debug!("Executing: sh -c \"{}\"", cmd_string.replace('"', "\\\""));
if copiousoutput {
let out = if needs_stdin {
let mut child = Command::new("sh")

View File

@ -36,7 +36,7 @@ use melib::{
},
sqlite3::{self as melib_sqlite3, rusqlite::params, DatabaseDescription},
thread::{SortField, SortOrder},
Error, Result, ERROR,
Error, Result,
};
use smallvec::SmallVec;
@ -174,13 +174,9 @@ pub async fn insert(
err
)
);
log(
format!(
"Failed to open envelope {}: {}",
envelope.message_id_display(),
err
),
ERROR,
log::error!(
"Failed to open envelope {}: {err}",
envelope.message_id_display(),
);
return Err(err);
}
@ -195,13 +191,9 @@ pub async fn insert(
envelope.message_id_display(),
err
);
log(
format!(
"Failed to insert envelope {}: {}",
envelope.message_id_display(),
err
),
ERROR,
log::error!(
"Failed to insert envelope {}: {err}",
envelope.message_id_display(),
);
return Err(Error::new(err.to_string()));
}
@ -246,18 +238,13 @@ pub async fn insert(
)
.map_err(|e| Error::new(e.to_string()))
{
debug!(
"Failed to insert envelope {}: {}",
log::debug!(
"Failed to insert envelope {}: {err}",
envelope.message_id_display(),
err
);
log(
format!(
"Failed to insert envelope {}: {}",
envelope.message_id_display(),
err
),
ERROR,
log::error!(
"Failed to insert envelope {}: {err}",
envelope.message_id_display(),
);
}
Ok(())
@ -279,11 +266,8 @@ pub fn remove(env_hash: EnvelopeHash) -> Result<()> {
)
.map_err(|e| Error::new(e.to_string()))
{
debug!("Failed to remove envelope {}: {}", env_hash, err);
log(
format!("Failed to remove envelope {}: {}", env_hash, err),
ERROR,
);
log::debug!("Failed to remove envelope {env_hash}: {err}");
log::error!("Failed to remove envelope {env_hash}: {err}");
return Err(err);
}
Ok(())

View File

@ -881,7 +881,7 @@ impl State {
name: "Message index rebuild".into(),
handle,
on_finish: None,
logging_level: melib::LoggingLevel::INFO,
log_level: LogLevel::INFO,
},
);
self.context.replies.push_back(UIEvent::Notification(
@ -1080,15 +1080,13 @@ impl State {
level,
},
) => {
log(
format!(
"{}: {}{}{}",
self.context.accounts[&account_hash].name(),
description.as_str(),
if content.is_some() { ": " } else { "" },
content.as_ref().map(|s| s.as_str()).unwrap_or("")
),
level,
log::log!(
level.into(),
"{}: {}{}{}",
self.context.accounts[&account_hash].name(),
description.as_str(),
if content.is_some() { ": " } else { "" },
content.as_ref().map(|s| s.as_str()).unwrap_or("")
);
self.rcv_event(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
description.to_string(),
@ -1208,7 +1206,7 @@ impl State {
Ok(Some(_)) => true,
Ok(None) => false,
Err(err) => {
log(format!("Failed to wait on editor process: {}", err), ERROR);
log::error!("Failed to wait on editor process: {err}");
return None;
}
}
@ -1219,7 +1217,7 @@ impl State {
Ok(Some(_)) => true,
Ok(None) => false,
Err(err) => {
log(format!("Failed to wait on child process: {}", err), ERROR);
log::error!("Failed to wait on child process: {err}");
return None;
}
}

View File

@ -27,7 +27,7 @@ use std::{
},
};
use melib::{error::*, log, ERROR};
use melib::{error::*, log};
#[cfg(not(target_os = "macos"))]
use nix::{
fcntl::{open, OFlag},
@ -123,23 +123,15 @@ pub fn create_pty(
nix::unistd::setsid().unwrap();
match unsafe { set_controlling_terminal(slave_fd) } {
Ok(c) if c < 0 => {
log(
format!(
"Could not execute `{}`: ioctl(fd, TIOCSCTTY, NULL) returned {}",
command, c,
),
ERROR,
log::error!(
"Could not execute `{command}`: ioctl(fd, TIOCSCTTY, NULL) returned {c}",
);
std::process::exit(c);
}
Ok(_) => {}
Err(err) => {
log(
format!(
"Could not execute `{}`: ioctl(fd, TIOCSCTTY, NULL) returned {}",
command, err,
),
ERROR,
log::error!(
"Could not execute `{command}`: ioctl(fd, TIOCSCTTY, NULL) returned {err}",
);
std::process::exit(-1);
}
@ -160,18 +152,15 @@ pub fn create_pty(
&CString::new(command.as_bytes()).unwrap(),
],
) {
log(format!("Could not execute `{}`: {}", command, e,), ERROR);
log::error!("Could not execute `{command}`: {e}");
std::process::exit(-1);
}
}
}
log(
format!(
"Could not execute `{}`: did not find the standard POSIX sh shell in PATH = {}",
command,
String::from_utf8_lossy(&path_var),
),
ERROR,
log::error!(
"Could not execute `{command}`: did not find the standard POSIX sh shell in PATH \
= {}",
String::from_utf8_lossy(&path_var),
);
std::process::exit(-1);
}