Implement configurable logging with tracing
- Replace eprintln! with tracing macros for configurable log levels - Set up tracing_subscriber with level filtering from config - Log format: YYYY-MM-DDTHH:MM:SSZ LEVEL IP "request" STATUS "message" - Success logs: INFO level for 20 responses - Error logs: WARN for 41/51, ERROR for 59 - Rate limiting and file serving now properly logged - Remove unused RequestLogger::log_success method
This commit is contained in:
parent
33ae576b25
commit
3865211554
3 changed files with 50 additions and 13 deletions
|
|
@ -16,12 +16,20 @@ impl RequestLogger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_success(self, status_code: u8) {
|
|
||||||
println!("{} \"{}\" {}", self.client_ip, self.request_url, status_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn log_error(self, status_code: u8, error_message: &str) {
|
pub fn log_error(self, status_code: u8, error_message: &str) {
|
||||||
eprintln!("{} \"{}\" {} \"{}\"", self.client_ip, self.request_url, status_code, error_message);
|
let level = match status_code {
|
||||||
|
41 | 51 => tracing::Level::WARN,
|
||||||
|
59 => tracing::Level::ERROR,
|
||||||
|
_ => tracing::Level::ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
match level {
|
||||||
|
tracing::Level::WARN => tracing::warn!("{} \"{}\" {} \"{}\"", self.client_ip, self.request_url, status_code, error_message),
|
||||||
|
tracing::Level::ERROR => tracing::error!("{} \"{}\" {} \"{}\"", self.client_ip, self.request_url, status_code, error_message),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,8 +43,28 @@ fn extract_client_ip(stream: &TlsStream<TcpStream>) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_logging(_level: &str) {
|
pub fn init_logging(level: &str) {
|
||||||
// Simple logging using stdout/stderr - systemd will capture this
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
let level = match level.to_lowercase().as_str() {
|
||||||
|
"error" => tracing::Level::ERROR,
|
||||||
|
"warn" => tracing::Level::WARN,
|
||||||
|
"info" => tracing::Level::INFO,
|
||||||
|
"debug" => tracing::Level::DEBUG,
|
||||||
|
"trace" => tracing::Level::TRACE,
|
||||||
|
_ => {
|
||||||
|
eprintln!("Warning: Invalid log level '{}', defaulting to 'info'", level);
|
||||||
|
tracing::Level::INFO
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(tracing_subscriber::fmt::layer()
|
||||||
|
.compact()
|
||||||
|
.with_target(false)
|
||||||
|
.with_thread_ids(false))
|
||||||
|
.with(tracing_subscriber::filter::LevelFilter::from_level(level))
|
||||||
|
.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ async fn main() {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, _) = listener.accept().await.unwrap();
|
let (stream, _) = listener.accept().await.unwrap();
|
||||||
|
tracing::debug!("Accepted connection from {}", stream.peer_addr().unwrap_or_else(|_| "unknown".parse().unwrap()));
|
||||||
let acceptor = acceptor.clone();
|
let acceptor = acceptor.clone();
|
||||||
let dir = root.clone();
|
let dir = root.clone();
|
||||||
let expected_host = "localhost".to_string(); // Override for testing
|
let expected_host = "localhost".to_string(); // Override for testing
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,17 @@ pub async fn serve_file(
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
if file_path.exists() && file_path.is_file() {
|
if file_path.exists() && file_path.is_file() {
|
||||||
let mime_type = get_mime_type(file_path);
|
let mime_type = get_mime_type(file_path);
|
||||||
|
let header = format!("20 {}\r\n", mime_type);
|
||||||
|
stream.write_all(header.as_bytes()).await?;
|
||||||
|
// Log success after sending header
|
||||||
|
let client_ip = match stream.get_ref().0.peer_addr() {
|
||||||
|
Ok(addr) => addr.to_string(),
|
||||||
|
Err(_) => "unknown".to_string(),
|
||||||
|
};
|
||||||
|
tracing::info!("{} \"file:{}\" 20 \"Success\"", client_ip, file_path.display());
|
||||||
|
// Then send body
|
||||||
let content = fs::read(file_path)?;
|
let content = fs::read(file_path)?;
|
||||||
let mut response = format!("20 {}\r\n", mime_type).into_bytes();
|
stream.write_all(&content).await?;
|
||||||
response.extend(content);
|
|
||||||
stream.write_all(&response).await?;
|
|
||||||
stream.flush().await?;
|
stream.flush().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -118,10 +125,12 @@ pub async fn handle_connection(
|
||||||
|
|
||||||
// Serve the file
|
// Serve the file
|
||||||
match serve_file(&mut stream, &file_path).await {
|
match serve_file(&mut stream, &file_path).await {
|
||||||
Ok(_) => logger.log_success(20),
|
Ok(_) => {
|
||||||
|
// Success already logged in serve_file
|
||||||
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// This shouldn't happen since we check existence, but handle gracefully
|
// File transmission failed
|
||||||
logger.log_error(51, "File not found");
|
logger.log_error(51, "File transmission failed");
|
||||||
let _ = send_response(&mut stream, "51 Not found\r\n").await;
|
let _ = send_response(&mut stream, "51 Not found\r\n").await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +164,6 @@ pub async fn handle_connection(
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTIVE_REQUESTS.fetch_sub(1, Ordering::Relaxed);
|
ACTIVE_REQUESTS.fetch_sub(1, Ordering::Relaxed);
|
||||||
eprintln!("DEBUG: Request completed, count decremented");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue