#![allow(unused_imports)]
#[macro_use]
mod common;
use std::net::SocketAddr;
use apollo_http_client::{HttpBody, HttpClient, HttpClientConfig};
use apollo_opentelemetry::metrics::Clock;
use apollo_opentelemetry_test::{TelemetryContext, assert_spans_snapshot};
use axum::Router;
use axum::routing::{get, post};
use bytes::Bytes;
use http_body_util::{BodyExt as _, Full};
use indoc::indoc;
use tower::ServiceExt as _;
use common::*;
#[tokio::test]
async fn h1_records_client_span() {
let ctx = integration_context();
let addr = spawn_server(Router::new().route("/", get(|| async { "hello" }))).await;
let req = http::Request::builder()
.method(http::Method::GET)
.uri(format!("http://{addr}/"))
.body(empty_body())
.unwrap();
let _ = new_client(&default_config())
.oneshot(req)
.await
.expect("ok");
span_snapshot!(ctx, @r#"
- name: GET
span_kind: Client
is_sampled: true
attributes:
http.request.method: GET
http.response.status_code: "200"
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
url.full: "http://127.0.0.1:<port>/"
"#);
}
#[tokio::test]
async fn h1_4xx_sets_span_error_status() {
let ctx = integration_context();
let addr =
spawn_server(Router::new().route("/", get(|| async { http::StatusCode::NOT_FOUND }))).await;
let req = http::Request::builder()
.method(http::Method::GET)
.uri(format!("http://{addr}/"))
.body(empty_body())
.unwrap();
let _ = new_client(&default_config())
.oneshot(req)
.await
.expect("ok");
span_snapshot!(ctx, @r#"
- name: GET
span_kind: Client
is_sampled: true
attributes:
error.type: "404"
http.request.method: GET
http.response.status_code: "404"
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
url.full: "http://127.0.0.1:<port>/"
status: Error
"#);
}
#[tokio::test]
async fn h1_span_records_opt_in_body_sizes() {
let ctx = integration_context();
let addr =
spawn_server(Router::new().route("/", post(|_body: axum::body::Bytes| async { "hello" })))
.await;
let config = parse_config(indoc! {"
telemetry:
spans:
request_body_size: true
response_body_size: true
"});
let req = http::Request::builder()
.method(http::Method::POST)
.uri(format!("http://{addr}/"))
.body(bytes_body(Bytes::from(vec![0u8; 10])))
.unwrap();
let resp = new_client(&config).oneshot(req).await.expect("ok");
resp.into_body().collect().await.unwrap();
span_snapshot!(ctx, @r#"
- name: POST
span_kind: Client
is_sampled: true
attributes:
http.request.body.size: "10"
http.request.method: POST
http.response.body.size: "5"
http.response.status_code: "200"
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
url.full: "http://127.0.0.1:<port>/"
"#);
}
#[tokio::test]
async fn h1_captures_request_and_response_headers() {
let ctx = integration_context();
let addr = spawn_server(Router::new().route(
"/",
get(|| async {
let mut resp = axum::response::Response::new(axum::body::Body::empty());
resp.headers_mut()
.insert("x-trace-id", "trace-abc".parse().unwrap());
resp
}),
))
.await;
let config = parse_config(indoc! {"
telemetry:
spans:
request_headers:
- x-request-id
response_headers:
- x-trace-id
"});
let req = http::Request::builder()
.method(http::Method::GET)
.uri(format!("http://{addr}/"))
.header("x-request-id", "req-123")
.body(empty_body())
.unwrap();
let _ = new_client(&config).oneshot(req).await.expect("ok");
span_snapshot!(ctx, @r#"
- name: GET
span_kind: Client
is_sampled: true
attributes:
http.request.header.x-request-id: "[\"req-123\"]"
http.request.method: GET
http.response.header.x-trace-id: "[\"trace-abc\"]"
http.response.status_code: "200"
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
url.full: "http://127.0.0.1:<port>/"
"#);
}