From 23c8b74058d5c8b2cc98cae5b4a9dd653019e661 Mon Sep 17 00:00:00 2001 From: "glm-5.1" Date: Fri, 12 Jun 2026 04:43:59 +0000 Subject: [PATCH] Wire up access logging in proxy handler Add log_request! calls for every proxied request (success, 4xx/5xx from upstream, 502/504 errors) and log_upstream_error! calls for upstream connection failures and timeouts. Duration is tracked from request entry to response using std::time::Instant. --- src/proxy/handler.rs | 82 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/src/proxy/handler.rs b/src/proxy/handler.rs index 8fba3d8..3f7e687 100644 --- a/src/proxy/handler.rs +++ b/src/proxy/handler.rs @@ -1,6 +1,7 @@ use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; +use std::time::Instant; use arc_swap::ArcSwap; use axum::body::Body; @@ -15,6 +16,8 @@ use hyper_util::rt::TokioExecutor; use tracing::warn; use crate::config::dynamic_config::DynamicConfig; +use crate::log_request; +use crate::log_upstream_error; use crate::proxy::error::ProxyError; use crate::proxy::headers::{inject_proxy_headers, remove_hop_by_hop}; @@ -34,10 +37,16 @@ async fn proxy_handler( State(state): State>, mut req: Request, ) -> Response { + let start = Instant::now(); + if req.uri().path() == "/health" { return StatusCode::OK.into_response(); } + let client_ip = remote_addr.ip().to_string(); + let method = req.method().clone(); + let path = req.uri().path().to_string(); + let host = req .headers() .get(axum::http::header::HOST) @@ -60,12 +69,24 @@ async fn proxy_handler( let upstream_scheme = site.upstream_scheme.clone(); let upstream = site.upstream.clone(); + let upstream_addr = format!("{}://{}", upstream_scheme, upstream); let upstream_uri = build_upstream_uri(&upstream_scheme, &upstream, req.uri()); let upstream_req = match build_upstream_request(req, &upstream_uri) { Ok(r) => r, Err(e) => { warn!(error = %e, "failed to build upstream request"); + log_upstream_error!(&host_owned, &upstream_addr, &format!("{}", e)); + let duration_ms = start.elapsed().as_millis() as u64; + log_request!( + &client_ip, + &host_owned, + &method, + &path, + 502u16, + &upstream, + duration_ms + ); return StatusCode::BAD_GATEWAY.into_response(); } }; @@ -80,6 +101,17 @@ async fn proxy_handler( match result { Ok(Ok(upstream_resp)) => { + let status = upstream_resp.status().as_u16(); + let duration_ms = start.elapsed().as_millis() as u64; + log_request!( + &client_ip, + &host_owned, + &method, + &path, + status, + &upstream, + duration_ms + ); let (mut parts, body) = upstream_resp.into_parts(); remove_hop_by_hop(&mut parts.headers); parts.headers.remove("server"); @@ -87,18 +119,54 @@ async fn proxy_handler( Response::from_parts(parts, body) } Ok(Err(e)) => { + let duration_ms = start.elapsed().as_millis() as u64; if e.is_connect() { - ProxyError::UpstreamConnection(e).into_response() + log_upstream_error!(&host_owned, &upstream_addr, &format!("{}", e)); + let resp = ProxyError::UpstreamConnection(e).into_response(); + log_request!( + &client_ip, + &host_owned, + &method, + &path, + 502u16, + &upstream, + duration_ms + ); + resp } else { - let upstream_addr = format!("{}://{}", upstream_scheme, upstream); - ProxyError::BadGateway { - host: host_owned, - upstream: upstream_addr, + log_upstream_error!(&host_owned, &upstream_addr, "bad gateway"); + let resp = ProxyError::BadGateway { + host: host_owned.clone(), + upstream: upstream_addr.clone(), } - .into_response() + .into_response(); + log_request!( + &client_ip, + &host_owned, + &method, + &path, + 502u16, + &upstream, + duration_ms + ); + resp } } - Err(_) => ProxyError::UpstreamTimeout.into_response(), + Err(_) => { + let duration_ms = start.elapsed().as_millis() as u64; + log_upstream_error!(&host_owned, &upstream_addr, "upstream timeout"); + let resp = ProxyError::UpstreamTimeout.into_response(); + log_request!( + &client_ip, + &host_owned, + &method, + &path, + 504u16, + &upstream, + duration_ms + ); + resp + } } }