feat: switch from log to tracing

This commit is contained in:
Almaz
2025-05-30 21:58:07 +00:00
committed by GitHub
parent cf317e8caa
commit f5ccd52a5d
14 changed files with 140 additions and 254 deletions
Generated
+35 -128
View File
@@ -62,56 +62,6 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.59.0",
]
[[package]]
name = "async-compression"
version = "0.4.23"
@@ -305,12 +255,6 @@ dependencies = [
"tracing-error",
]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "compact_str"
version = "0.8.1"
@@ -497,19 +441,6 @@ dependencies = [
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"jiff",
"log",
]
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -1099,12 +1030,6 @@ dependencies = [
"serde",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.13.0"
@@ -1120,30 +1045,6 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
dependencies = [
"jiff-static",
"log",
"portable-atomic",
"portable-atomic-util",
"serde",
]
[[package]]
name = "jiff-static"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
name = "js-sys"
version = "0.3.77"
@@ -1290,6 +1191,16 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -1314,18 +1225,18 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owo-colors"
version = "4.2.1"
@@ -1379,21 +1290,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "portable-atomic"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]]
name = "potential_utf"
version = "0.1.2"
@@ -1429,10 +1325,8 @@ dependencies = [
"crossterm",
"derivative",
"dirs",
"env_logger",
"fancy-regex",
"futures",
"log",
"maxminddb",
"ratatui",
"reqwest",
@@ -1441,6 +1335,9 @@ dependencies = [
"serde_json",
"tokio",
"toml",
"tracing",
"tracing-log",
"tracing-subscriber",
"tui-logger",
"url",
]
@@ -2298,15 +2195,29 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
@@ -2328,6 +2239,8 @@ dependencies = [
"log",
"parking_lot",
"ratatui",
"tracing",
"tracing-subscriber",
"unicode-segmentation",
]
@@ -2389,12 +2302,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.1"
+6 -3
View File
@@ -12,10 +12,8 @@ crossterm = { version = "=0.28.1", features = [
], optional = true }
derivative = "=2.2.0"
dirs = "=6.0.0"
env_logger = "=0.11.8"
fancy-regex = "=0.14.0"
futures = { version = "=0.3.31", optional = true }
log = "=0.4.27"
maxminddb = { version = "=0.26.0", features = ["mmap"] }
ratatui = { version = "=0.29.0", optional = true }
rlimit = "=0.10.2"
@@ -23,7 +21,12 @@ serde = "=1.0.219"
serde_json = "=1.0.140"
tokio = { version = "=1.45.1", features = ["full"] }
toml = "=0.8.22"
tui-logger = { version = "=0.17.3", optional = true }
tracing = "=0.1.41"
tracing-log = "=0.2.0"
tracing-subscriber = "=0.3.19"
tui-logger = { version = "=0.17.3", features = [
"tracing-support",
], optional = true }
url = "=2.5.4"
[features]
+1 -5
View File
@@ -1,5 +1,5 @@
# Use debug logging level
# Useful for debugging but can produce a lot of output
# Produces a lot of output
debug = false
@@ -23,10 +23,6 @@ timeout = 5.0
# "" - Disable checking entirely
check_url = "https://checkip.amazonaws.com"
# Enable logging of proxy rejection reasons
# Useful for debugging but can produce a lot of output
debug = false
# Maximum concurrent proxy checks
# Make sure you have enough RAM first and your network can handle it, gradually increasing the default value
max_concurrent_checks = 4096
+4 -7
View File
@@ -48,13 +48,10 @@ pub async fn check_all(
)))?;
new_storage.lock().await.push(proxy);
}
Err(e) if config.checking.debug => {
log::log!(
if log::log_enabled!(log::Level::Debug) {
log::Level::Debug
} else {
log::Level::Info
},
Err(e)
if tracing::event_enabled!(tracing::Level::DEBUG) =>
{
tracing::debug!(
"{} | {}",
proxy.as_str(true),
pretty_error(&e)
+1 -3
View File
@@ -25,7 +25,6 @@ pub struct ScrapingConfig {
pub struct CheckingConfig {
pub check_url: String,
pub debug: bool,
pub max_concurrent_checks: usize,
pub timeout: tokio::time::Duration,
}
@@ -104,7 +103,7 @@ impl Config {
let lim = usize::try_from(lim).unwrap_or(usize::MAX);
if raw_config.checking.max_concurrent_checks.get() > lim {
log::warn!(
tracing::warn!(
"max_concurrent_checks config value is too high for \
your OS. It will be ignored and {lim} will be used."
);
@@ -138,7 +137,6 @@ impl Config {
},
checking: CheckingConfig {
check_url: raw_config.checking.check_url,
debug: raw_config.checking.debug,
max_concurrent_checks,
timeout: tokio::time::Duration::from_secs_f64(
raw_config.checking.timeout,
+1 -9
View File
@@ -1,9 +1,5 @@
#[cfg(feature = "tui")]
use crate::ipdb;
#[cfg(feature = "tui")]
use crate::proxy::ProxyType;
use crate::{ipdb, proxy::ProxyType};
#[cfg(feature = "tui")]
pub enum AppEvent {
IpDbTotal(ipdb::DbType, Option<u64>),
IpDbDownloaded(ipdb::DbType, usize),
@@ -18,12 +14,8 @@ pub enum AppEvent {
Done,
}
#[cfg(feature = "tui")]
pub enum Event {
Tick,
Crossterm(crossterm::event::Event),
App(AppEvent),
}
#[cfg(not(feature = "tui"))]
pub enum Event {}
+4 -4
View File
@@ -83,7 +83,7 @@ impl DbType {
async fn save_etag(
&self,
etag: reqwest::header::HeaderValue,
etag: impl AsRef<[u8]>,
) -> color_eyre::Result<()> {
let path = self.etag_path().await?;
tokio::fs::write(&path, etag).await.wrap_err_with(move || {
@@ -150,7 +150,7 @@ impl DbType {
})?;
if response.status() == reqwest::StatusCode::NOT_MODIFIED {
log::info!(
tracing::info!(
"Latest {} database is already cached at {}",
self.name(),
db_path.display()
@@ -177,13 +177,13 @@ impl DbType {
.wrap_err_with(|| format!("failed to save {} database", self.name()))?;
if is_docker().await {
log::info!(
tracing::info!(
"Downloaded {} database to Docker volume ({} in container)",
self.name(),
db_path.display()
);
} else {
log::info!(
tracing::info!(
"Downloaded {} database to {}",
self.name(),
db_path.display()
+53 -15
View File
@@ -36,6 +36,7 @@
mod checker;
mod config;
#[cfg(feature = "tui")]
mod event;
mod fs;
mod ipdb;
@@ -44,13 +45,17 @@ mod parsers;
mod proxy;
mod raw_config;
mod scraper;
mod ui;
#[cfg(feature = "tui")]
mod tui;
mod utils;
use std::sync::Arc;
use color_eyre::eyre::WrapErr as _;
use ui::UI as _;
#[cfg(not(feature = "tui"))]
use tracing_subscriber::{
layer::SubscriberExt as _, util::SubscriberInitExt as _,
};
fn create_reqwest_client() -> reqwest::Result<reqwest::Client> {
reqwest::Client::builder()
@@ -64,16 +69,13 @@ fn create_reqwest_client() -> reqwest::Result<reqwest::Client> {
#[tokio::main]
async fn main() -> color_eyre::Result<()> {
color_eyre::install().wrap_err("failed to install color_eyre hooks")?;
let ui_impl =
ui::UIImpl::new().wrap_err("failed to initialize user interface")?;
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
let ui_task = tokio::task::spawn(ui_impl.run(tx.clone(), rx));
let raw_config_path = raw_config::get_config_path();
let raw_config = raw_config::read_config(&raw_config_path)
.await
.wrap_err_with(move || format!("failed to read {raw_config_path}"))?;
let raw_config = raw_config::read_config(std::path::Path::new(
&raw_config_path,
))
.await
.wrap_err_with(move || format!("failed to read {raw_config_path}"))?;
let config = Arc::new(
config::Config::from_raw_config(raw_config)
@@ -81,9 +83,34 @@ async fn main() -> color_eyre::Result<()> {
.wrap_err("failed to create Config from RawConfig")?,
);
if config.debug {
ui::UIImpl::set_log_level(log::LevelFilter::Debug);
}
let targets_filter = tracing_subscriber::filter::Targets::new()
.with_default(tracing::level_filters::LevelFilter::INFO)
// TODO: remove for hickory_proto >= 0.25.0
.with_target(
"hickory_proto::xfer::dns_exchange",
tracing::level_filters::LevelFilter::ERROR,
)
.with_target(
"proxy_scraper_checker",
if config.debug {
tracing::level_filters::LevelFilter::DEBUG
} else {
tracing::level_filters::LevelFilter::INFO
},
);
#[cfg(feature = "tui")]
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
#[cfg(feature = "tui")]
let tui_task =
tokio::task::spawn(tui::Tui::new(targets_filter)?.run(tx.clone(), rx));
#[cfg(not(feature = "tui"))]
tracing_subscriber::registry()
.with(targets_filter)
.with(tracing_subscriber::fmt::layer())
.init();
let http_client = create_reqwest_client()
.wrap_err("failed to create reqwest HTTP client")?;
@@ -134,10 +161,14 @@ async fn main() -> color_eyre::Result<()> {
while let Some(task) = output_dependencies_tasks.join_next().await {
task.wrap_err("failed to join output dependencies task")??;
}
drop(output_dependencies_tasks);
let proxies = if config.checking.check_url.is_empty() {
proxies.into_iter().collect()
} else {
#[cfg(not(feature = "tui"))]
tracing::info!("Started checking {} proxies", proxies.len());
checker::check_all(
Arc::clone(&config),
proxies,
@@ -152,9 +183,16 @@ async fn main() -> color_eyre::Result<()> {
.await
.wrap_err("failed to save proxies")?;
log::info!("Thank you for using proxy-scraper-checker!");
tracing::info!("Thank you for using proxy-scraper-checker!");
#[cfg(feature = "tui")]
tx.send(event::Event::App(event::AppEvent::Done))?;
#[cfg(feature = "tui")]
drop(tx);
ui_task.await?
#[cfg(feature = "tui")]
tui_task.await??;
Ok(())
}
+5 -5
View File
@@ -45,7 +45,7 @@ struct ProxyJson<'a> {
fn group_proxies<'a>(
config: &Config,
proxies: &'a Vec<Proxy>,
proxies: &'a [Proxy],
) -> HashMap<ProxyType, Vec<&'a Proxy>> {
let mut groups: HashMap<_, _> =
config.enabled_protocols().map(|p| (p.clone(), Vec::new())).collect();
@@ -189,7 +189,7 @@ pub async fn save_proxies(
)?;
let text = create_proxy_list_str(
&proxies.iter().collect(),
&proxies.iter().collect::<Vec<_>>(),
anonymous_only,
true,
);
@@ -226,19 +226,19 @@ pub async fn save_proxies(
.canonicalize()
.unwrap_or_else(move |_| config.output.path.clone());
if is_docker().await {
log::info!(
tracing::info!(
"Proxies have been saved to ./out ({} in container)",
path.display()
);
} else {
log::info!("Proxies have been saved to {}", path.display());
tracing::info!("Proxies have been saved to {}", path.display());
}
Ok(())
}
fn create_proxy_list_str(
proxies: &Vec<&Proxy>,
proxies: &[&Proxy],
anonymous_only: bool,
include_protocol: bool,
) -> String {
+12 -7
View File
@@ -1,4 +1,9 @@
use std::{collections::HashSet, env, num::NonZero, path::PathBuf};
use std::{
collections::HashSet,
env,
num::NonZero,
path::{Path, PathBuf},
};
use color_eyre::eyre::WrapErr as _;
use serde::{Deserialize, Deserializer};
@@ -50,7 +55,6 @@ pub struct ScrapingConfig {
pub struct CheckingConfig {
#[serde(deserialize_with = "validate_http_url")]
pub check_url: String,
pub debug: bool,
pub max_concurrent_checks: NonZero<usize>,
#[serde(deserialize_with = "validate_positive_f64")]
pub timeout: f64,
@@ -119,11 +123,12 @@ pub fn get_config_path() -> String {
env::var(CONFIG_ENV).unwrap_or_else(|_| "config.toml".to_owned())
}
pub async fn read_config(path: &str) -> color_eyre::Result<RawConfig> {
let raw_config = tokio::fs::read_to_string(path)
.await
.wrap_err_with(move || format!("failed to read {path} to string"))?;
pub async fn read_config(path: &Path) -> color_eyre::Result<RawConfig> {
let raw_config =
tokio::fs::read_to_string(path).await.wrap_err_with(move || {
format!("failed to read {} to string", path.display())
})?;
toml::from_str(&raw_config).wrap_err_with(move || {
format!("failed to parse {path} as TOML config file")
format!("failed to parse {} as TOML config file", path.display())
})
}
+3 -3
View File
@@ -49,7 +49,7 @@ async fn scrape_one(
let text = match text_result {
Ok(text) => text,
Err(e) => {
log::warn!("{} | {}", source, pretty_error(&e));
tracing::warn!("{} | {}", source, pretty_error(&e));
return Ok(());
}
};
@@ -58,14 +58,14 @@ async fn scrape_one(
PROXY_REGEX.captures_iter(&text).collect::<Result<Vec<_>, _>>()?;
if matches.is_empty() {
log::warn!("{source} | No proxies found");
tracing::warn!("{source} | No proxies found");
return Ok(());
}
if config.scraping.max_proxies_per_source != 0
&& matches.len() > config.scraping.max_proxies_per_source
{
log::warn!(
tracing::warn!(
"{} | Too many proxies ({}) - skipped",
source,
matches.len(),
+15 -9
View File
@@ -18,6 +18,9 @@ use ratatui::{
text::{Line, Text},
widgets::{Block, Gauge},
};
use tracing_subscriber::{
layer::SubscriberExt as _, util::SubscriberInitExt as _,
};
use tui_logger::{TuiLoggerWidget, TuiWidgetEvent, TuiWidgetState};
use crate::{
@@ -33,22 +36,25 @@ pub struct Tui {
terminal: DefaultTerminal,
}
impl super::UI for Tui {
fn new() -> color_eyre::Result<Self> {
tui_logger::init_logger(log::LevelFilter::Info)
impl Tui {
pub fn new(
filter: tracing_subscriber::filter::Targets,
) -> color_eyre::Result<Self> {
tui_logger::init_logger(tui_logger::LevelFilter::Trace)
.wrap_err("failed to initialize tui_logger")?;
tui_logger::set_default_level(log::LevelFilter::Trace);
tracing_subscriber::registry()
.with(filter)
.with(tui_logger::TuiTracingSubscriberLayer)
.init();
Ok(Self {
terminal: ratatui::try_init()
.wrap_err("failed to initialize ratatui")?,
})
}
fn set_log_level(log_level: log::LevelFilter) {
log::set_max_level(log_level);
}
async fn run(
pub async fn run(
mut self,
tx: tokio::sync::mpsc::UnboundedSender<Event>,
mut rx: tokio::sync::mpsc::UnboundedReceiver<Event>,
-27
View File
@@ -1,27 +0,0 @@
use color_eyre::eyre::WrapErr as _;
use crate::event::Event;
pub struct LoggerUI;
impl super::UI for LoggerUI {
fn new() -> color_eyre::Result<Self> {
env_logger::Builder::new()
.filter_level(log::LevelFilter::Info)
.try_init()
.wrap_err("failed to initialize env_logger")?;
Ok(Self {})
}
fn set_log_level(log_level: log::LevelFilter) {
log::set_max_level(log_level);
}
async fn run(
self,
_tx: tokio::sync::mpsc::UnboundedSender<Event>,
_rx: tokio::sync::mpsc::UnboundedReceiver<Event>,
) -> color_eyre::Result<()> {
Ok(())
}
}
-29
View File
@@ -1,29 +0,0 @@
#![expect(clippy::pub_use)]
use std::marker::Sized;
use crate::event::Event;
pub trait UI {
fn new() -> color_eyre::Result<Self>
where
Self: Sized;
fn set_log_level(log_level: log::LevelFilter);
async fn run(
self,
tx: tokio::sync::mpsc::UnboundedSender<Event>,
rx: tokio::sync::mpsc::UnboundedReceiver<Event>,
) -> color_eyre::Result<()>;
}
#[cfg(feature = "tui")]
mod tui;
#[cfg(feature = "tui")]
pub use tui::Tui as UIImpl;
#[cfg(not(feature = "tui"))]
mod logger;
#[cfg(not(feature = "tui"))]
pub use logger::LoggerUI as UIImpl;