Log as JSON when IPX_LOG_FORMAT=json (#91)
The log was text, so the Grafana dashboard picked lines apart with regular expressions, and a change of wording would have blanked its panels. With IPX_LOG_FORMAT=json each line is one JSON object: the access log carries method, path, route, status and ms as fields (the route passed from the routing layer in the response's extensions), and each wire event its ev, feed, new, downloaded, failed, bytes, msg and the rest (log_wire), beside the old message. The two startup lines that were println! are logged, so no line breaks the JSON. Text stays the default, for a terminal. The dashboard reads the fields with Loki's json parser, and groups requests by route rather than path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
14
src/web.rs
14
src/web.rs
@@ -1941,7 +1941,10 @@ async fn name_span(route: MatchedPath, req: Request, next: Next) -> Response {
|
||||
let span = tracing::Span::current();
|
||||
span.context().span().update_name(format!("{} {}", req.method(), route.as_str()));
|
||||
span.record("http.route", route.as_str());
|
||||
next.run(req).await
|
||||
let mut resp = next.run(req).await;
|
||||
// For access_log, which runs outside routing and cannot see it otherwise.
|
||||
resp.extensions_mut().insert(route);
|
||||
resp
|
||||
}
|
||||
|
||||
/// One line per HTTP request, so the web side shows up in the same log as the daemon.
|
||||
@@ -1971,12 +1974,15 @@ async fn access_log(req: Request, next: Next) -> Response {
|
||||
let resp = tracing::Instrument::instrument(next.run(req), span.clone()).await;
|
||||
span.record("http.response.status_code", resp.status().as_u16());
|
||||
if !quiet {
|
||||
let ms = started.elapsed().as_millis();
|
||||
let ms = started.elapsed().as_millis() as u64;
|
||||
let status = resp.status().as_u16();
|
||||
// The same as fields, for the JSON log (#91). Unrouted, a request has no route.
|
||||
let route = resp.extensions().get::<MatchedPath>().map(|r| r.as_str().to_owned());
|
||||
let method = method.as_str();
|
||||
if resp.status().is_success() || resp.status().is_redirection() {
|
||||
tracing::info!(target: "ipx::http", "{method} {path} -> {status} in {ms}ms");
|
||||
tracing::info!(target: "ipx::http", method, path, route, status, ms, "{method} {path} -> {status} in {ms}ms");
|
||||
} else {
|
||||
tracing::warn!(target: "ipx::http", "{method} {path} -> {status} in {ms}ms");
|
||||
tracing::warn!(target: "ipx::http", method, path, route, status, ms, "{method} {path} -> {status} in {ms}ms");
|
||||
}
|
||||
}
|
||||
resp
|
||||
|
||||
Reference in New Issue
Block a user