refactor to async tokio with modular architecture
- Replace synchronous std::net::UdpSocket with tokio async runtime - Spawn concurrent task per incoming DNS query via tokio::spawn - Extract monolithic main.rs into modules: buffer, header, question, record, packet, config, cache, forward, stats - Share state across tasks via Arc<ServerCtx> with scoped Mutex locks - Add TOML config loading, TTL-aware cache, structured logging, stats - Add CLAUDE.md, README, dns_fun.toml config, and design docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
79
src/stats.rs
Normal file
79
src/stats.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use std::time::Instant;
|
||||
|
||||
pub struct ServerStats {
|
||||
queries_total: u64,
|
||||
queries_forwarded: u64,
|
||||
queries_cached: u64,
|
||||
queries_blocked: u64,
|
||||
queries_local: u64,
|
||||
upstream_errors: u64,
|
||||
started_at: Instant,
|
||||
}
|
||||
|
||||
pub enum QueryPath {
|
||||
Local,
|
||||
Cached,
|
||||
Forwarded,
|
||||
Blocked,
|
||||
UpstreamError,
|
||||
}
|
||||
|
||||
impl QueryPath {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
QueryPath::Local => "LOCAL",
|
||||
QueryPath::Cached => "CACHED",
|
||||
QueryPath::Forwarded => "FORWARD",
|
||||
QueryPath::Blocked => "BLOCKED",
|
||||
QueryPath::UpstreamError => "SERVFAIL",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ServerStats {
|
||||
pub fn new() -> Self {
|
||||
ServerStats {
|
||||
queries_total: 0,
|
||||
queries_forwarded: 0,
|
||||
queries_cached: 0,
|
||||
queries_blocked: 0,
|
||||
queries_local: 0,
|
||||
upstream_errors: 0,
|
||||
started_at: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record(&mut self, path: QueryPath) -> u64 {
|
||||
self.queries_total += 1;
|
||||
match path {
|
||||
QueryPath::Local => self.queries_local += 1,
|
||||
QueryPath::Cached => self.queries_cached += 1,
|
||||
QueryPath::Forwarded => self.queries_forwarded += 1,
|
||||
QueryPath::Blocked => self.queries_blocked += 1,
|
||||
QueryPath::UpstreamError => self.upstream_errors += 1,
|
||||
}
|
||||
self.queries_total
|
||||
}
|
||||
|
||||
pub fn total(&self) -> u64 {
|
||||
self.queries_total
|
||||
}
|
||||
|
||||
pub fn log_summary(&self) {
|
||||
let uptime = self.started_at.elapsed();
|
||||
let hours = uptime.as_secs() / 3600;
|
||||
let mins = (uptime.as_secs() % 3600) / 60;
|
||||
let secs = uptime.as_secs() % 60;
|
||||
|
||||
log::info!(
|
||||
"STATS | uptime {}h{}m{}s | total {} | fwd {} | cached {} | local {} | blocked {} | errors {}",
|
||||
hours, mins, secs,
|
||||
self.queries_total,
|
||||
self.queries_forwarded,
|
||||
self.queries_cached,
|
||||
self.queries_local,
|
||||
self.queries_blocked,
|
||||
self.upstream_errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user