# tide-tracing-middleware A middleware for tide using the tracing crate for logging. è¿ç§»äº† actix-web 自带的 log ä¸é—´ä»¶ï¼Œä»¥åº”用于 tide 框架。 ## 开始使用 代ç 在 examples/basic.rs。 ```rs use tide::{Request, Response, StatusCode}; use tide_tracing_middleware::TracingMiddleware; use tracing::Level; use tracing_subscriber::FmtSubscriber; #[async_std::main] async fn main() -> tide::Result<()> { FmtSubscriber::builder().with_max_level(Level::DEBUG).init(); let mut app = tide::new(); app.with(TracingMiddleware::default()); app.at("/index").get(index); app.listen("127.0.0.1:8080").await?; Ok(()) } async fn index(_req: Request<()>) -> tide::Result { let res = Response::builder(StatusCode::Ok) .body("hello world!") .build(); Ok(res) } ``` 输出示例: ``` Sep 16 21:12:39.988 INFO tide_tracing_middleware: 127.0.0.1:56205 "GET /index?a=1&b=2 HTTP/1.1" 200 12 "-" "curl/7.64.1" 0.000278 ``` ## è‡ªå®šä¹‰è¾“å‡ºæ ¼å¼ ä¸‹é¢çš„示例将输出大部分的信æ¯ï¼ŒåŒ…括所有的请求头和å“应头。 ```rs let tracing_middleware = TracingMiddleware::new( "%t %a(%{r}a) %r(%M %U %Q %V) %s %b(bytes) %T(seconds) %D(milliseconds) REQ_HEADERS:%{ALL_REQ_HEADERS}xi RES_HEADERS:%{ALL_RES_HEADERS}xo", ).custom_request_replace("ALL_REQ_HEADERS", |req| { let pairs = req.iter().map(|(k, v)| format!("{}:{}", k, v)).collect::<Vec<String>>(); "{".to_owned() + &pairs.join(",") + "}" }).custom_response_replace("ALL_RES_HEADERS", |res| { let pairs = res.iter().map(|(k, v)| format!("{}:{}", k, v)).collect::<Vec<String>>(); "{".to_owned() + &pairs.join(",") + "}" }); ``` 输出示例: ``` Sep 16 21:18:15.174 INFO tide_tracing_middleware: 2021-09-16T13:18:15 127.0.0.1:56234(127.0.0.1:56234) GET /index?a=1&b=2 HTTP/1.1(GET /index a=1&b=2 HTTP/1.1) 200 12(bytes) 0.000437(seconds) 0.461000(milliseconds) REQ_HEADERS:{accept:["*/*"],user-agent:["curl/7.64.1"],host:["127.0.0.1:8080"]} RES_HEADERS:{content-type:["text/plain;charset=utf-8"]} ``` 支æŒçš„æ ‡ç¾å’Œ actix-web çš„ log ä¸é—´ä»¶ä¸€æ ·ï¼Œä½†å¤šæ·»åŠ äº†å‡ ä¸ªæ ‡ç¾ï¼š - `%%`: The percent sign - `%a`: Remote IP-address (IP-address of proxy if using reverse proxy) - `%t`: Time when the request was started to process (in rfc3339 format) - `%r`: First line of request - `%s`: Response status code - `%b`: Size of response body in bytes, not including HTTP headers - `%T`: Time taken to serve the request, in seconds with floating fraction in .06f format - `%D`: Time taken to serve the request, in milliseconds - `%U`: Request URL - `%M`: Request method - `%V`: Request HTTP version - `%Q`: Request URL's query string - `%{r}a`: Real IP remote address - `%{FOO}i`: request.headers['FOO'] - `%{FOO}o`: response.headers['FOO'] - `%{FOO}e`: os.environ['FOO'] - `%{FOO}xi`: custom request replacement labelled "FOO" - `%{FOO}xo`: custom response replacement labelled "FOO" ## ç”Ÿæˆ tracing span 下é¢çš„示例ä¸ä½¿ç”¨ uuid 为æ¯ä¸ªè¯·æ±‚生æˆä¸€ä¸ª id,以便将该请求相关的日志关è”èµ·æ¥ã€‚ ```rs #[async_std::main] async fn main() -> tide::Result<()> { FmtSubscriber::builder().with_max_level(Level::DEBUG).init(); let tracing_middleware = TracingMiddleware::new( "%t %a(%{r}a) %r(%M %U %Q %V) %s %b(bytes) %T(seconds) %D(milliseconds) REQ_HEADERS:%{ALL_REQ_HEADERS}xi RES_HEADERS:%{ALL_RES_HEADERS}xo", ).custom_request_replace("ALL_REQ_HEADERS", |req| { let pairs = req.iter().map(|(k, v)| format!("{}:{}", k, v)).collect::<Vec<String>>(); "{".to_owned() + &pairs.join(",") + "}" }).custom_response_replace("ALL_RES_HEADERS", |res| { let pairs = res.iter().map(|(k, v)| format!("{}:{}", k, v)).collect::<Vec<String>>(); "{".to_owned() + &pairs.join(",") + "}" }).gen_tracing_span(|_req| { tracing::info_span!("R", "{}", uuid::Uuid::new_v4().to_simple().to_string()) }); let mut app = tide::new(); app.with(tracing_middleware); app.at("/index").get(index); app.listen("127.0.0.1:8080").await?; Ok(()) } async fn index(_req: Request<()>) -> tide::Result { info!(a = "123", "index"); let res = Response::builder(StatusCode::Ok) .body("hello world!") .build(); Ok(res) } ``` 输出示例: ``` Sep 16 21:22:29.564 INFO R{c7abce9aba3c4a2c9161c3df20a4141b}: trace_span: index a="123" Sep 16 21:22:29.564 INFO R{c7abce9aba3c4a2c9161c3df20a4141b}: tide_tracing_middleware: 2021-09-16T13:22:29 127.0.0.1:56260(127.0.0.1:56260) GET /index?a=1&b=2 HTTP/1.1(GET /index a=1&b=2 HTTP/1.1) 200 12(bytes) 0.000613(seconds) 0.626000(milliseconds) REQ_HEADERS:{user-agent:["curl/7.64.1"],accept:["*/*"],host:["127.0.0.1:8080"]} RES_HEADERS:{content-type:["text/plain;charset=utf-8"]} ```