From 7d0db3f8ec910c5975b076fbbc70b36f9b20535d Mon Sep 17 00:00:00 2001 From: yggverse Date: Sun, 8 Jun 2025 19:48:10 +0300 Subject: [PATCH] implement `match_time` argument, make some optimizations --- Cargo.toml | 1 + README.md | 16 ++++++++++------ src/argument.rs | 4 ++++ src/debug.rs | 2 +- src/main.rs | 25 ++++++++++++++++++++----- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5101505..3d2fbfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ repository = "https://github.com/YGGverse/htcount" [dependencies] anyhow = "1.0" +chrono = "0.4" clap = { version = "4.5", features = ["derive"] } diff --git a/README.md b/README.md index d0be592..e720e5c 100644 --- a/README.md +++ b/README.md @@ -50,19 +50,22 @@ htcount --source /var/log/nginx/access.log\ [default: nginx] - --export-json +--export-json Export results to JSON file (e.g. `/path/to/stats.json`) - --export-svg +--export-svg Export results to SVG file (e.g. `/path/to/badge.svg`) * use `{hits}` / `{hosts}` pattern to replace parsed values - --template-svg +--template-svg Use custom SVG file template with `{hits}` / `{hosts}` placeholders [default: default/counter.svg] +-m, --match-time + Filter records match time pattern (e.g. `%d/%b/%Y`) + -c, --capacity Expected memory index capacity @@ -86,7 +89,6 @@ htcount --source /var/log/nginx/access.log\ Print version ``` - ### systemd ``` /etc/systemd/system/htcount.service @@ -101,8 +103,9 @@ Type=simple ExecStart=/usr/local/bin/htcount --source /var/log/nginx/access.log\ --export-svg /var/www/htcount/visitors.svg\ --template-svg /path/to/default/template.svg\ - --ignore-host 127.0.0.1 - --ignore-host 127.0.0.2 + --ignore-host 127.0.0.1\ + --ignore-host 127.0.0.2\ + --match-time %d/%b/%Y\ --update 3600\ --debug n StandardOutput=null @@ -114,6 +117,7 @@ WantedBy=multi-user.target * make sure `/var/www/htcount` exists * replace `/path/to/default/template.svg` with your value * use `ignore-host` to skip local host requests +* `match-time %d/%b/%Y` today records only * `systemctl daemon-reload` - update configuration * `systemctl enable` - launch on system startup diff --git a/src/argument.rs b/src/argument.rs index bea400c..ac7e383 100644 --- a/src/argument.rs +++ b/src/argument.rs @@ -30,6 +30,10 @@ pub struct Argument { #[arg(long, default_value_t = String::from("default/counter.svg"))] pub template_svg: String, + /// Filter records match time pattern (e.g. `%d/%b/%Y`) + #[arg(short, long)] + pub match_time: Option, + /// Expected memory index capacity #[arg(short, long, default_value_t = 100)] pub capacity: usize, diff --git a/src/debug.rs b/src/debug.rs index 69cf562..43847c8 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,4 +1,4 @@ -pub fn info(message: String) { +pub fn info(message: &str) { println!("[{}] [info] {message}", now()) } diff --git a/src/main.rs b/src/main.rs index f434539..8aa36e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,10 @@ fn main() -> anyhow::Result<()> { argument::Argument::parse() }; + let match_time = argument + .match_time + .map(|ref t| chrono::Local::now().format(t).to_string()); + // parse some arguments once let is_debug_i = argument.debug.contains("i"); let is_debug_d = argument.debug.contains("d"); @@ -24,12 +28,12 @@ fn main() -> anyhow::Result<()> { } if is_debug_i { - debug::info("Crawler started".into()); + debug::info("Crawler started"); } loop { if is_debug_i { - debug::info("Index queue begin...".into()); + debug::info("Index queue begin..."); } let file = File::open(&argument.source)?; @@ -38,7 +42,18 @@ fn main() -> anyhow::Result<()> { let mut index: HashMap = HashMap::with_capacity(argument.capacity); 'l: for line in reader.lines() { - let host = line? + let l = line?; + + if let Some(ref t) = match_time { + if !l.contains(t) { + if is_debug_d { + debug::info(&format!("Record time mismatch time filter {t}")) + } + continue; + } + } + + let host = l .split_whitespace() .next() .map(|s| s.into()) @@ -47,7 +62,7 @@ fn main() -> anyhow::Result<()> { for h in &argument.ignore_host { if h == &host { if is_debug_d { - debug::info(format!("Host `{h}` ignored by settings")) + debug::info(&format!("Host `{h}` ignored by settings")) } continue 'l; } @@ -60,7 +75,7 @@ fn main() -> anyhow::Result<()> { let hits: usize = index.values().sum(); if is_debug_i { - debug::info(format!( + debug::info(&format!( "Index queue completed:\n{}\n\thosts: {} / hits: {}, await {} seconds to continue...", if is_debug_d { let mut b = Vec::with_capacity(hosts);