Skip to content

Commit ef69c80

Browse files
committed
chore: add http-body-util dependency for enhanced body handling in axum-otel
1 parent 9be5f8e commit ef69c80

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ axum-otel = { path = "crates/axum-otel", version = "0.31.5" }
4040
config = { version = "0.14.0", default-features = false }
4141
dotenvy = { version = "0.15.7" }
4242
http = { version = "1.3.1" }
43+
http-body-util = { version = "0.1" }
4344
opentelemetry = { version = "0.31.0", default-features = false }
4445
opentelemetry-appender-tracing = { version = "0.31.0" }
4546
opentelemetry-http = { version = "0.31.0", default-features = false }

crates/axum-otel/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ tracing = { workspace = true }
1919
tracing-otel-extra = { workspace = true, features = ["macros"] }
2020

2121
[dev-dependencies]
22+
http-body-util = { workspace = true }
2223
opentelemetry_sdk = { workspace = true, features = ["testing"] }
2324
reqwest = { workspace = true }
2425
tokio = { workspace = true }

crates/axum-otel/tests/integration.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use axum::{
55
routing::get,
66
};
77
use axum_otel::{AxumOtelOnFailure, AxumOtelOnResponse, AxumOtelSpanCreator, Level};
8+
use http_body_util::BodyExt;
89
use opentelemetry::{global, trace::TracerProvider};
910
use opentelemetry_sdk::{
1011
Resource,
@@ -52,8 +53,7 @@ async fn test_axum_otel_middleware() {
5253

5354
let app = app();
5455

55-
// `Router` implements `tower::Service<Request<Body>>` so we can
56-
// call it like any tower service, no need to run an HTTP server.
56+
// Send request using oneshot
5757
let response = app
5858
.oneshot(
5959
Request::builder()
@@ -67,19 +67,55 @@ async fn test_axum_otel_middleware() {
6767

6868
assert_eq!(response.status(), StatusCode::OK);
6969

70+
let body = response
71+
.into_body()
72+
.collect()
73+
.await
74+
.expect("Failed to read body");
75+
76+
assert_eq!(body.to_bytes(), "Hello, world!".as_bytes());
77+
7078
// Force flush to ensure spans are exported
7179
let _ = provider.force_flush();
7280

7381
// Verify spans were created
7482
let spans = exporter
7583
.get_finished_spans()
7684
.expect("Failed to get finished spans");
85+
7786
assert!(
7887
!spans.is_empty(),
7988
"Expected at least one span to be created"
8089
);
8190

82-
assert!(!spans.is_empty());
83-
let span = &spans[0];
84-
assert_eq!(span.name, "hello");
91+
// With oneshot(), there's no MatchedPath, so span name is just "GET"
92+
// When using a real server, it would be "GET /"
93+
let request_span = spans
94+
.iter()
95+
.find(|s| s.name == "GET" || s.name == "GET /")
96+
.expect("Request span not found");
97+
98+
let hello_span = spans
99+
.iter()
100+
.find(|s| s.name == "hello")
101+
.expect("Handler span not found");
102+
103+
assert_eq!(
104+
hello_span.parent_span_id,
105+
request_span.span_context.span_id(),
106+
"Handler span should be a child of the request span"
107+
);
108+
109+
// Check http.status_code attribute
110+
let status_code_attr = request_span
111+
.attributes
112+
.iter()
113+
.find(|kv| kv.key.as_str() == "http.status_code")
114+
.map(|kv| kv.value.to_string());
115+
116+
assert_eq!(
117+
status_code_attr,
118+
Some("200".to_string()),
119+
"Expected http.status_code to be 200"
120+
);
85121
}

0 commit comments

Comments
 (0)