mirror of
https://github.com/watchexec/watchexec.git
synced 2024-09-29 22:51:33 +02:00
feat(cli): use non-blocking logging
This commit is contained in:
parent
ad27bb2874
commit
d72362002c
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -3685,6 +3685,18 @@ dependencies = [
|
|||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-appender"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"thiserror",
|
||||||
|
"time",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-attributes"
|
name = "tracing-attributes"
|
||||||
version = "0.1.27"
|
version = "0.1.27"
|
||||||
@ -4060,6 +4072,7 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-appender",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tracing-test",
|
"tracing-test",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
@ -44,6 +44,7 @@ serde_json = "1.0.107"
|
|||||||
tempfile = "3.8.1"
|
tempfile = "3.8.1"
|
||||||
termcolor = "1.4.0"
|
termcolor = "1.4.0"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
|
tracing-appender = "0.2.3"
|
||||||
which = "6.0.1"
|
which = "6.0.1"
|
||||||
|
|
||||||
[dependencies.blake3]
|
[dependencies.blake3]
|
||||||
|
@ -15,6 +15,7 @@ use clap::{
|
|||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use tokio::{fs::File, io::AsyncReadExt};
|
use tokio::{fs::File, io::AsyncReadExt};
|
||||||
use tracing::{debug, info, trace, warn};
|
use tracing::{debug, info, trace, warn};
|
||||||
|
use tracing_appender::non_blocking::WorkerGuard;
|
||||||
use watchexec::{paths::PATH_SEPARATOR, sources::fs::WatchedPath};
|
use watchexec::{paths::PATH_SEPARATOR, sources::fs::WatchedPath};
|
||||||
use watchexec_signals::Signal;
|
use watchexec_signals::Signal;
|
||||||
|
|
||||||
@ -1145,7 +1146,7 @@ fn expand_args_up_to_doubledash() -> Result<Vec<OsString>, std::io::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn get_args() -> Result<Args> {
|
pub async fn get_args() -> Result<(Args, Option<WorkerGuard>)> {
|
||||||
let prearg_logs = logging::preargs();
|
let prearg_logs = logging::preargs();
|
||||||
if prearg_logs {
|
if prearg_logs {
|
||||||
warn!("⚠ RUST_LOG environment variable set or hardcoded, logging options have no effect");
|
warn!("⚠ RUST_LOG environment variable set or hardcoded, logging options have no effect");
|
||||||
@ -1157,9 +1158,11 @@ pub async fn get_args() -> Result<Args> {
|
|||||||
debug!("parsing arguments");
|
debug!("parsing arguments");
|
||||||
let mut args = Args::parse_from(args);
|
let mut args = Args::parse_from(args);
|
||||||
|
|
||||||
if !prearg_logs {
|
let log_guard = if !prearg_logs {
|
||||||
logging::postargs(&args.logging).await?;
|
logging::postargs(&args.logging).await?
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// https://no-color.org/
|
// https://no-color.org/
|
||||||
if args.color == ColourMode::Auto && std::env::var("NO_COLOR").is_ok() {
|
if args.color == ColourMode::Auto && std::env::var("NO_COLOR").is_ok() {
|
||||||
@ -1290,5 +1293,5 @@ pub async fn get_args() -> Result<Args> {
|
|||||||
debug_assert!(args.workdir.is_some());
|
debug_assert!(args.workdir.is_some());
|
||||||
debug_assert!(args.project_origin.is_some());
|
debug_assert!(args.project_origin.is_some());
|
||||||
info!(?args, "got arguments");
|
info!(?args, "got arguments");
|
||||||
Ok(args)
|
Ok((args, log_guard))
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
use std::{path::PathBuf, env::var, fs::File, sync::Mutex};
|
use std::{env::var, io::stderr, path::PathBuf};
|
||||||
|
|
||||||
use clap::{ArgAction, Parser, ValueHint};
|
use clap::{ArgAction, Parser, ValueHint};
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{bail, Result};
|
||||||
use tokio::fs::metadata;
|
use tokio::fs::metadata;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
use tracing_appender::{non_blocking, non_blocking::WorkerGuard, rolling};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Parser)]
|
#[derive(Debug, Clone, Parser)]
|
||||||
pub struct LoggingArgs {
|
pub struct LoggingArgs {
|
||||||
/// Set diagnostic log level
|
/// Set diagnostic log level
|
||||||
///
|
///
|
||||||
/// This enables diagnostic logging, which is useful for investigating bugs or gaining more
|
/// This enables diagnostic logging, which is useful for investigating bugs or gaining more
|
||||||
/// insight into faulty filters or "missing" events. Use multiple times to increase args.verbose.
|
/// insight into faulty filters or "missing" events. Use multiple times to increase verbosity.
|
||||||
///
|
///
|
||||||
/// Goes up to '-vvvv'. When submitting bug reports, default to a '-vvv' log level.
|
/// Goes up to '-vvvv'. When submitting bug reports, default to a '-vvv' log level.
|
||||||
///
|
///
|
||||||
@ -77,27 +78,30 @@ pub fn preargs() -> bool {
|
|||||||
log_on
|
log_on
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn postargs(args: &LoggingArgs) -> Result<()> {
|
pub async fn postargs(args: &LoggingArgs) -> Result<Option<WorkerGuard>> {
|
||||||
if args.verbose == 0 {
|
if args.verbose == 0 {
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_file = if let Some(file) = &args.log_file {
|
let (log_writer, guard) = if let Some(file) = &args.log_file {
|
||||||
let is_dir = metadata(&file).await.map_or(false, |info| info.is_dir());
|
let is_dir = metadata(&file).await.map_or(false, |info| info.is_dir());
|
||||||
let path = if is_dir {
|
let (dir, filename) = if is_dir {
|
||||||
let filename = format!(
|
(
|
||||||
|
file.to_owned(),
|
||||||
|
PathBuf::from(format!(
|
||||||
"watchexec.{}.log",
|
"watchexec.{}.log",
|
||||||
chrono::Utc::now().format("%Y-%m-%dT%H-%M-%SZ")
|
chrono::Utc::now().format("%Y-%m-%dT%H-%M-%SZ")
|
||||||
);
|
)),
|
||||||
file.join(filename)
|
)
|
||||||
|
} else if let (Some(parent), Some(file_name)) = (file.parent(), file.file_name()) {
|
||||||
|
(parent.into(), PathBuf::from(file_name))
|
||||||
} else {
|
} else {
|
||||||
file.to_owned()
|
bail!("Failed to determine log file name");
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: use tracing-appender instead
|
non_blocking(rolling::never(dir, filename))
|
||||||
Some(File::create(path).into_diagnostic()?)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
non_blocking(stderr())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut builder = tracing_subscriber::fmt().with_env_filter(match args.verbose {
|
let mut builder = tracing_subscriber::fmt().with_env_filter(match args.verbose {
|
||||||
@ -113,16 +117,16 @@ pub async fn postargs(args: &LoggingArgs) -> Result<()> {
|
|||||||
builder = builder.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE);
|
builder = builder.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
match if let Some(writer) = log_file {
|
match if args.log_file.is_some() {
|
||||||
builder.json().with_writer(Mutex::new(writer)).try_init()
|
builder.json().with_writer(log_writer).try_init()
|
||||||
} else if args.verbose > 3 {
|
} else if args.verbose > 3 {
|
||||||
builder.pretty().try_init()
|
builder.pretty().with_writer(log_writer).try_init()
|
||||||
} else {
|
} else {
|
||||||
builder.try_init()
|
builder.with_writer(log_writer).try_init()
|
||||||
} {
|
} {
|
||||||
Ok(()) => info!("logging initialised"),
|
Ok(()) => info!("logging initialised"),
|
||||||
Err(e) => eprintln!("Failed to initialise logging, continuing with none\n{e}"),
|
Err(e) => eprintln!("Failed to initialise logging, continuing with none\n{e}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(Some(guard))
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ async fn run_completions(shell: ShellCompletion) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run() -> Result<()> {
|
pub async fn run() -> Result<()> {
|
||||||
let args = args::get_args().await?;
|
let (args, _log_guard) = args::get_args().await?;
|
||||||
|
|
||||||
if args.manual {
|
if args.manual {
|
||||||
run_manpage(args).await
|
run_manpage(args).await
|
||||||
|
Loading…
Reference in New Issue
Block a user