axum/tower tracing - spans and parent spans do not appear to be set properly #1261
-
I am attempting to use near-default tracing configuration with an echo server in order to demonstrate a fully instrumented HTTP server. I have
But what I'm getting is that the spans are only set on a few of the traces and parent spans are only non-default values on traces inside of a function decorated with Here is my code: use std::collections::HashMap;
use axum::{
body::Body,
http::Request,
routing::{get, post},
Json, Router,
};
use opentelemetry::global;
use opentelemetry::sdk::export::trace::stdout;
use serde::Serialize;
use serde_json::{json, Value};
use tower_http::classify::StatusInRangeAsFailures;
use tower_http::trace::TraceLayer;
use tracing::level_filters::LevelFilter;
use tracing::{info, instrument};
use tracing_subscriber::{prelude::*, Registry};
#[tokio::main]
async fn main() {
// use a file writer layer to collect everything for debugging
let file_appender = tracing_appender::rolling::minutely("./logs", "trace");
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
let file_writer_layer = tracing_subscriber::fmt::layer()
.json()
.with_writer(file_writer);
// global::set_text_map_propagator(opentelemetry_jaeger::Propagator::new());
// let tracer = opentelemetry_jaeger::new_pipeline()
// .with_collector_endpoint("http://localhost:4318")
// .install_simple()
// .unwrap();
let tracer = stdout::new_pipeline().install_simple();
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
// just for stdout non-tracing logs to be collected into ElasticSearch or similar
// let stdout_log_layer = tracing_subscriber::fmt::layer()
// .json()
// .with_filter(LevelFilter::DEBUG);
let subscriber = Registry::default()
.with(file_writer_layer)
// .with(stdout_log_layer)
.with(telemetry);
tracing::subscriber::set_global_default(subscriber).unwrap();
let app = Router::new()
.route("/", get(echo))
.route("/", post(echo))
.layer(TraceLayer::new(
// by default the tower http trace layer only classifies 5xx errors as failures
StatusInRangeAsFailures::new(400..=599).into_make_classifier(),
));
axum::Server::bind(&"127.0.0.1:8080".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
#[derive(Serialize, Debug)]
struct EchoResponse {
method: String,
headers: HashMap<String, String>,
body: String,
}
#[instrument]
async fn echo(request: Request<Body>) -> Json<Value> {
let (req_parts, req_body) = request.into_parts();
let req_method = req_parts.method.to_string();
let parsed_req_headers = req_parts
.headers
.iter()
.map(|(k, v)| (k.to_string(), v.to_str().unwrap_or_default().to_string()))
.collect::<HashMap<String, String>>();
let parsed_req_body = match hyper::body::to_bytes(req_body).await {
Ok(bytes) => match String::from_utf8(bytes.to_vec()) {
Ok(str) => str,
Err(_) => String::new(),
},
Err(_) => String::new(),
};
// example of info log in instrumented fn
info!("successfully parsed request body");
let resp_body = EchoResponse {
method: req_method,
headers: parsed_req_headers,
body: parsed_req_body,
};
Json(json!(resp_body))
} and when I do OpenTracing sent to stdout:
All levels of traces and logs sent to logfile:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
This is unlikely to be axum's fault since axum doesn't know anything about tracing. How |
Beta Was this translation helpful? Give feedback.
This is unlikely to be axum's fault since axum doesn't know anything about tracing. How
TraceLayer
creates the span is also pretty straight forward. I'd suggest you ask intracing-users
in the tokio discord.