#![allow(unused_imports)]
#[macro_use]
mod common;
use std::net::SocketAddr;
use std::sync::Arc;
use apollo_http_client::{HttpBody, HttpClient, HttpClientConfig};
use apollo_opentelemetry::metrics::Clock;
use apollo_opentelemetry_test::{TelemetryContext, assert_metrics_snapshot};
use axum::Router;
use axum::routing::get;
use bytes::Bytes;
use http_body_util::{BodyExt as _, Full};
use hyper_util::rt::{TokioExecutor, TokioIo};
use indoc::indoc;
use opentelemetry_sdk::metrics::{Aggregation, Instrument, StreamBuilder};
use tower::ServiceExt as _;
use common::*;
fn auto_config() -> HttpClientConfig {
parse_config("protocol: alpn\ntls:\n danger_accept_invalid_certs: true")
}
#[tokio::test]
async fn auto_connection_refused_records_error() {
let ctx = TelemetryContext::new();
let config = parse_config("protocol: alpn\nconnect_timeout: 1s");
let req = http::Request::builder()
.method(http::Method::GET)
.uri("http://127.0.0.1:1/")
.body(empty_body())
.unwrap();
let err = new_client(&config)
.oneshot(req)
.await
.expect_err("should fail");
assert!(matches!(
err,
apollo_http_client::HttpClientError::Transport { .. }
));
assert_metrics_snapshot!(ctx, @r#"
- name: http.client.active_requests
description: Number of HTTP requests currently in flight
unit: "{request}"
data:
type: Sum
data_points:
- attributes:
http.request.method: GET
server.address: 127.0.0.1
server.port: "1"
value: 0
is_monotonic: false
temporality: Cumulative
- name: http.client.open_connections
description: Number of open connections in the HTTP client pool
unit: "{connection}"
data:
type: Sum
data_points:
- attributes:
http.connection.state: connecting
server.address: 127.0.0.1
server.port: "1"
value: 0
is_monotonic: false
temporality: Cumulative
- name: http.client.request.duration
description: Duration of HTTP client requests
unit: s
data:
type: Histogram
data_points:
- attributes:
error.type: _OTHER
http.request.method: GET
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "1"
count: 1
sum: 0
min: 0
max: 0
bounds:
- 0.005
- 0.01
- 0.025
- 0.05
- 0.075
- 0.1
- 0.25
- 0.5
- 0.75
- 1
- 2.5
- 5
- 7.5
- 10
bucket_counts:
- 1
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
temporality: Cumulative
"#);
}
#[tokio::test]
async fn auto_plain_http_uses_h1() {
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 resp = new_client(&parse_config("protocol: alpn"))
.oneshot(req)
.await
.expect("request ok");
resp.into_body().collect().await.unwrap();
snapshot!(ctx, @r#"
- name: http.client.active_requests
description: Number of HTTP requests currently in flight
unit: "{request}"
data:
type: Sum
data_points:
- attributes:
http.request.method: GET
server.address: 127.0.0.1
server.port: "<port>"
value: 0
is_monotonic: false
temporality: Cumulative
- name: http.client.open_connections
description: Number of open connections in the HTTP client pool
unit: "{connection}"
data:
type: Sum
data_points:
- attributes:
http.connection.state: active
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
value: 0
- attributes:
http.connection.state: connecting
server.address: 127.0.0.1
server.port: "<port>"
value: 0
- attributes:
http.connection.state: idle
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
value: 0
is_monotonic: false
temporality: Cumulative
- name: http.client.request.duration
description: Duration of HTTP client requests
unit: s
data:
type: Histogram
data_points:
- attributes:
http.request.method: GET
http.response.status_code: "200"
network.protocol.version: "1.1"
server.address: 127.0.0.1
server.port: "<port>"
count: 1
sum: 0
min: 0
max: 0
bounds:
- 0.005
- 0.01
- 0.025
- 0.05
- 0.075
- 0.1
- 0.25
- 0.5
- 0.75
- 1
- 2.5
- 5
- 7.5
- 10
bucket_counts:
- 1
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
temporality: Cumulative
"#);
}
#[tokio::test]
async fn auto_negotiates_h2_over_tls() {
let ctx = integration_context();
let addr = spawn_tls_h2_server(Router::new().route("/", get(|| async { "hello" }))).await;
let req = http::Request::builder()
.method(http::Method::GET)
.uri(format!("https://{addr}/"))
.body(empty_body())
.unwrap();
let resp = new_client(&auto_config())
.oneshot(req)
.await
.expect("request ok");
resp.into_body().collect().await.unwrap();
snapshot!(ctx, @r#"
- name: http.client.active_requests
description: Number of HTTP requests currently in flight
unit: "{request}"
data:
type: Sum
data_points:
- attributes:
http.request.method: GET
server.address: 127.0.0.1
server.port: "<port>"
value: 0
is_monotonic: false
temporality: Cumulative
- name: http.client.open_connections
description: Number of open connections in the HTTP client pool
unit: "{connection}"
data:
type: Sum
data_points:
- attributes:
http.connection.state: active
network.protocol.version: "2"
server.address: 127.0.0.1
server.port: "<port>"
value: 0
- attributes:
http.connection.state: connecting
server.address: 127.0.0.1
server.port: "<port>"
value: 0
- attributes:
http.connection.state: idle
network.protocol.version: "2"
server.address: 127.0.0.1
server.port: "<port>"
value: 0
is_monotonic: false
temporality: Cumulative
- name: http.client.request.duration
description: Duration of HTTP client requests
unit: s
data:
type: Histogram
data_points:
- attributes:
http.request.method: GET
http.response.status_code: "200"
network.protocol.version: "2"
server.address: 127.0.0.1
server.port: "<port>"
count: 1
sum: 0
min: 0
max: 0
bounds:
- 0.005
- 0.01
- 0.025
- 0.05
- 0.075
- 0.1
- 0.25
- 0.5
- 0.75
- 1
- 2.5
- 5
- 7.5
- 10
bucket_counts:
- 1
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
temporality: Cumulative
"#);
}