Best pratices for tracing data in spans? #3480
-
SummaryHi, I write a macro like this: macro_rules! prepare_data {
($model:ident, $cached: expr, $($trace:tt),*) => {
| mut req: axum::extract::Request, next: axum::middleware::Next | async move {
let id = crate::middleware::data::get_path_param_i64!(stringify!($model), ¶ms);
let data = { ... };
let traced: Vec<&str> = vec![$(stringify!($trace)),*];
let traced = traced.len() > 0;
req
.extensions_mut()
.insert::<r2s_database::$model::Model>(data.clone());
if traced {
$(
tracing::Span::current().record(concat!("data-", stringify!($model), "-", stringify!($trace)), &data.$trace);
)*
}
Ok(next.run(req).await)
}
}
};
} then, i could use it as a middleware, such as: Router::new()
.route("/", get(get_notification).delete(delete_notification))
.route_layer(middleware::from_fn_with_state(
state.clone(),
data::prepare_data!(notification, false, id, title),
)), the data will be queried and inserted into extensions as expect, and I want to record it in the default tracing span, but I found the fields disappeared. to make it working, I need to pre-define all fields in span declarition like this: .layer(
TraceLayer::new_for_http()
.make_span_with(|request: &Request<Body>| {
let trace = request.extensions().get::<RequestId>();
let request_id = trace
.map(|id| id.header_value().to_str().unwrap_or("unknown"))
.unwrap_or_else(|| "UNKNOWN");
error_span!(
"request",
method=%request.method(), uri=%request.uri().path(), trace=%request_id,
"user-id"=tracing::field::Empty,
"user-account"=tracing::field::Empty,
"user-nickname"=tracing::field::Empty,
"team-id"=tracing::field::Empty,
"team-name"=tracing::field::Empty,
"data-challenge-id"=tracing::field::Empty,
"data-challenge-name"=tracing::field::Empty,
"data-game-id"=tracing::field::Empty,
"data-game-name"=tracing::field::Empty,
"data-team-id"=tracing::field::Empty,
"data-team-name"=tracing::field::Empty,
"data-user-id"=tracing::field::Empty,
"data-user-account"=tracing::field::Empty,
"data-user-nickname"=tracing::field::Empty,
"data-notification-id"=tracing::field::Empty,
"data-notification-title"=tracing::field::Empty,
"data-audit-id"=tracing::field::Empty,
"data-institute-id"=tracing::field::Empty,
"data-institute-name"=tracing::field::Empty,
)
})
.on_request(())
.on_response(|response: &Response, latency: Duration, _span: &Span| {
debug!(response = ?response.status(), latency = ?format!("{}ms", latency.as_millis()));
}),
) that is very ugly. do we have a more elegant way to do this? axum version0.8.4 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I'm using the same approach as you are. |
Beta Was this translation helpful? Give feedback.
I'm using the same approach as you are.
It's a limitation of the tracing crates that each new span must define all its fields at creation time.
Nothing axum can influence ;)