feat(log): switch to `tracing` for logging (#163)

* feat(log): use 'tracing-subscriber' instead of 'env_logger'

resolves #161

* feat: use 'tracing' instead of 'log'

* feat: make 'INFO' the default log level
This commit is contained in:
Jean SIMARD 2023-10-20 23:30:16 +02:00 committed by GitHub
parent cd9ace952c
commit 70541bb842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 48 additions and 60 deletions

39
Cargo.lock generated
View File

@ -864,19 +864,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.3.2"
@ -2326,7 +2313,6 @@ dependencies = [
"byte-unit",
"config",
"dotenvy",
"env_logger",
"futures-util",
"glob",
"hotwatch",
@ -2334,7 +2320,6 @@ dependencies = [
"humantime-serde",
"infer",
"lazy-regex",
"log",
"mime",
"petname",
"rand",
@ -2345,6 +2330,8 @@ dependencies = [
"shuttle-actix-web",
"shuttle-runtime",
"tokio",
"tracing",
"tracing-subscriber",
"url",
"uts2ts",
]
@ -2761,15 +2748,6 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.47"
@ -3024,11 +3002,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.37"
version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9"
dependencies = [
"cfg-if",
"log",
"pin-project-lite",
"tracing-attributes",
@ -3037,9 +3014,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.26"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
@ -3048,9 +3025,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.31"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
"valuable",

View File

@ -23,8 +23,6 @@ actix-web = { version = "4.4.0" }
actix-multipart = "0.6.1"
actix-files = "0.6.2"
awc = { version = "3.2.0" }
env_logger = "0.10.0"
log = "0.4.20"
serde = "1.0.189"
futures-util = "0.3.28"
petname = { version = "1.1.3", default-features = false, features = [
@ -46,6 +44,8 @@ hotwatch = "0.5.0"
shuttle-actix-web = { version = "0.29.0", optional = true }
shuttle-runtime = { version = "0.29.0", optional = true }
tokio = { version = "1.33.0", optional = true }
tracing = "0.1.39"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
uts2ts = "0.4.1"
[dependencies.config]

View File

@ -12,12 +12,12 @@ pub fn check(host: &str, headers: &HeaderMap, tokens: Option<Vec<String>>) -> Re
.map(|v| v.split_whitespace().last().unwrap_or_default());
if !tokens.iter().any(|v| v == auth_header.unwrap_or_default()) {
#[cfg(debug_assertions)]
log::warn!(
tracing::warn!(
"authorization failure for {host} (token: {})",
auth_header.unwrap_or("none"),
);
#[cfg(not(debug_assertions))]
log::warn!("authorization failure for {host}");
tracing::warn!("authorization failure for {host}");
return Err(error::ErrorUnauthorized("unauthorized\n"));
}
}

View File

@ -177,19 +177,19 @@ impl Config {
#[allow(deprecated)]
pub fn warn_deprecation(&self) {
if self.server.auth_token.is_some() {
log::warn!("[server].auth_token is deprecated, please use [server].auth_tokens");
tracing::warn!("[server].auth_token is deprecated, please use [server].auth_tokens");
}
if self.server.landing_page.is_some() {
log::warn!("[server].landing_page is deprecated, please use [landing_page].text");
tracing::warn!("[server].landing_page is deprecated, please use [landing_page].text");
}
if self.server.landing_page_content_type.is_some() {
log::warn!(
tracing::warn!(
"[server].landing_page_content_type is deprecated, please use [landing_page].content_type"
);
}
if let Some(random_url) = &self.paste.random_url {
if random_url.enabled.is_some() {
log::warn!(
tracing::warn!(
"[paste].random_url.enabled is deprecated, disable it by commenting out [paste].random_url"
);
}

View File

@ -18,6 +18,10 @@ use std::path::{Path, PathBuf};
use std::sync::{mpsc, RwLock};
use std::thread;
use std::time::Duration;
#[cfg(not(feature = "shuttle"))]
use tracing_subscriber::{
filter::LevelFilter, layer::SubscriberExt as _, util::SubscriberInitExt as _, EnvFilter,
};
#[cfg(feature = "shuttle")]
use {
actix_web::web::{self, ServiceConfig},
@ -36,7 +40,14 @@ fn setup(config_folder: &Path) -> IoResult<(Data<RwLock<Config>>, ServerConfig,
// Initialize logger.
#[cfg(not(feature = "shuttle"))]
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
tracing_subscriber::registry()
.with(
EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy(),
)
.with(tracing_subscriber::fmt::layer())
.init();
// Parse configuration.
let config_path = match env::var(CONFIG_ENV).ok() {
@ -47,7 +58,7 @@ fn setup(config_folder: &Path) -> IoResult<(Data<RwLock<Config>>, ServerConfig,
None => config_folder.join("config.toml"),
};
let config = Config::parse(&config_path).expect("failed to parse config");
log::trace!("{:#?}", config);
tracing::trace!("{:#?}", config);
config.warn_deprecation();
let server_config = config.server.clone();
let paste_config = RwLock::new(config.paste.clone());
@ -80,18 +91,18 @@ fn setup(config_folder: &Path) -> IoResult<(Data<RwLock<Config>>, ServerConfig,
Ok(config) => match cloned_config.write() {
Ok(mut cloned_config) => {
*cloned_config = config.clone();
log::info!("Configuration has been updated.");
tracing::info!("Configuration has been updated.");
if let Err(e) = config_sender.send(config) {
log::error!("Failed to send config for the cleanup routine: {}", e)
tracing::error!("Failed to send config for the cleanup routine: {}", e)
}
cloned_config.warn_deprecation();
}
Err(e) => {
log::error!("Failed to acquire config: {}", e);
tracing::error!("Failed to acquire config: {}", e);
}
},
Err(e) => {
log::error!("Failed to update config: {}", e);
tracing::error!("Failed to update config: {}", e);
}
}
}
@ -110,11 +121,11 @@ fn setup(config_folder: &Path) -> IoResult<(Data<RwLock<Config>>, ServerConfig,
.and_then(|v| v.delete_expired_files.clone())
{
if cleanup_config.enabled {
log::debug!("Running cleanup...");
tracing::debug!("Running cleanup...");
for file in util::get_expired_files(&upload_path) {
match fs::remove_file(&file) {
Ok(()) => log::info!("Removed expired file: {:?}", file),
Err(e) => log::error!("Cannot remove expired file: {}", e),
Ok(()) => tracing::info!("Removed expired file: {:?}", file),
Err(e) => tracing::error!("Cannot remove expired file: {}", e),
}
}
thread::sleep(cleanup_config.interval);
@ -131,7 +142,7 @@ fn setup(config_folder: &Path) -> IoResult<(Data<RwLock<Config>>, ServerConfig,
*paste_config = new_config.paste;
}
Err(e) => {
log::error!("Failed to update config for the cleanup routine: {}", e);
tracing::error!("Failed to update config for the cleanup routine: {}", e);
}
}
}
@ -175,7 +186,7 @@ async fn main() -> IoResult<()> {
}
// Run the server.
log::info!("Server is running at {}", server_config.address);
tracing::info!("Server is running at {}", server_config.address);
http_server.run().await
}

View File

@ -69,7 +69,7 @@ where
.and_then(|v| v.parse::<u128>().ok())
{
if content_length > self.max_bytes {
log::warn!("Upload rejected due to exceeded limit.");
tracing::warn!("Upload rejected due to exceeded limit.");
return Box::pin(async move {
// drain the body due to https://github.com/actix/actix-web/issues/2695
let mut payload = request.take_payload();

View File

@ -162,7 +162,7 @@ async fn delete(
let host = connection.realip_remote_addr().unwrap_or("unknown host");
let tokens = config.get_tokens(TokenType::Delete);
if tokens.is_none() {
log::warn!("delete endpoint is not served because there are no delete_tokens set");
tracing::warn!("delete endpoint is not served because there are no delete_tokens set");
return Err(error::ErrorForbidden("endpoint is not exposed\n"));
}
auth::check(host, request.headers(), tokens)?;
@ -170,9 +170,9 @@ async fn delete(
return Err(error::ErrorNotFound("file is not found or expired :(\n"));
}
match fs::remove_file(path) {
Ok(_) => log::info!("deleted file: {:?}", file),
Ok(_) => tracing::info!("deleted file: {:?}", file),
Err(e) => {
log::error!("cannot delete file: {}", e);
tracing::error!("cannot delete file: {}", e);
return Err(error::ErrorInternalServerError("cannot delete file"));
}
}
@ -193,7 +193,7 @@ async fn version(
let tokens = config.get_tokens(TokenType::Auth);
auth::check(host, request.headers(), tokens)?;
if !config.server.expose_version.unwrap_or(false) {
log::warn!("server is not configured to expose version endpoint");
tracing::warn!("server is not configured to expose version endpoint");
Err(error::ErrorForbidden("endpoint is not exposed\n"))?;
}
let version = env!("CARGO_PKG_VERSION");
@ -249,7 +249,7 @@ async fn upload(
bytes.append(&mut chunk?.to_vec());
}
if bytes.is_empty() {
log::warn!("{} sent zero bytes", host);
tracing::warn!("{} sent zero bytes", host);
return Err(error::ErrorBadRequest("invalid file size"));
}
if paste_type != PasteType::Oneshot
@ -304,7 +304,7 @@ async fn upload(
paste.store_url(expiry_date, &config)?
}
};
log::info!(
tracing::info!(
"{} ({}) is uploaded from {}",
file_name,
Byte::from_bytes(paste.data.len() as u128).get_appropriate_unit(false),
@ -318,7 +318,7 @@ async fn upload(
}
urls.push(format!("{}/{}\n", server_url, file_name));
} else {
log::warn!("{} sent an invalid form field", host);
tracing::warn!("{} sent an invalid form field", host);
return Err(error::ErrorBadRequest("invalid form field"));
}
}
@ -351,7 +351,7 @@ async fn list(
let tokens = config.get_tokens(TokenType::Auth);
auth::check(host, request.headers(), tokens)?;
if !config.server.expose_list.unwrap_or(false) {
log::warn!("server is not configured to expose list endpoint");
tracing::warn!("server is not configured to expose list endpoint");
Err(error::ErrorForbidden("endpoint is not exposed\n"))?;
}
let entries: Vec<ListItem> = fs::read_dir(config.server.upload_path)?
@ -365,7 +365,7 @@ async fn list(
metadata
}
Err(e) => {
log::error!("failed to read metadata: {e}");
tracing::error!("failed to read metadata: {e}");
return None;
}
};