cool_core/middleware/
log.rs1use super::DepotExt;
6use salvo::prelude::*;
7use std::time::Instant;
8use tracing::{info, warn};
9
10pub struct RequestLogMiddleware {
12 log_body: bool,
14 ignore_paths: Vec<String>,
16}
17
18impl RequestLogMiddleware {
19 pub fn new() -> Self {
20 Self {
21 log_body: false,
22 ignore_paths: vec![],
23 }
24 }
25
26 pub fn log_body(mut self, enable: bool) -> Self {
28 self.log_body = enable;
29 self
30 }
31
32 pub fn ignore_path(mut self, path: impl Into<String>) -> Self {
34 self.ignore_paths.push(path.into());
35 self
36 }
37}
38
39impl Default for RequestLogMiddleware {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45#[async_trait]
46impl Handler for RequestLogMiddleware {
47 async fn handle(
48 &self,
49 req: &mut Request,
50 depot: &mut Depot,
51 res: &mut Response,
52 ctrl: &mut FlowCtrl,
53 ) {
54 let path = req.uri().path().to_string();
55
56 for ignore_path in &self.ignore_paths {
58 if path.starts_with(ignore_path) {
59 ctrl.call_next(req, depot, res).await;
60 return;
61 }
62 }
63
64 let method = req.method().to_string();
65 let start = Instant::now();
66
67 let client_ip = req
69 .remote_addr()
70 .as_ipv4()
71 .map(|addr| addr.to_string())
72 .or_else(|| req.remote_addr().as_ipv6().map(|addr| addr.to_string()))
73 .unwrap_or_else(|| "unknown".to_string());
74
75 let user_id = depot
77 .admin()
78 .map(|admin| admin.user_id.to_string())
79 .unwrap_or_else(|| "anonymous".to_string());
80
81 ctrl.call_next(req, depot, res).await;
83
84 let duration = start.elapsed();
86 let status = res.status_code.unwrap_or(StatusCode::OK);
87
88 if status.is_success() {
90 info!(
91 method = %method,
92 path = %path,
93 status = %status.as_u16(),
94 duration_ms = %duration.as_millis(),
95 ip = %client_ip,
96 user_id = %user_id,
97 "request completed"
98 );
99 } else {
100 warn!(
101 method = %method,
102 path = %path,
103 status = %status.as_u16(),
104 duration_ms = %duration.as_millis(),
105 ip = %client_ip,
106 user_id = %user_id,
107 "request failed"
108 );
109 }
110 }
111}
112
113pub fn request_log() -> RequestLogMiddleware {
115 RequestLogMiddleware::new()
116}