#![allow(
clippy::arbitrary_source_item_ordering,
clippy::tests_outside_test_module,
clippy::unwrap_used,
clippy::expect_used,
clippy::panic
)]
mod common;
use axum::{body::Body, http::Request};
use tower::ServiceExt as _;
fn assert_metric_line(rendered: &str, expected_line: &str) {
let found = rendered.lines().any(|line| line == expected_line);
assert!(
found,
"Expected metric line not found.\n expected: {expected_line}\n rendered:\n{rendered}",
);
}
#[test]
fn success_increments_with_none_error_class() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("# Hello World")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="success",error_class="none",input_mime_type="text/markdown",output_mime_type="application/vnd.docspec.blocknote+json"} 1"#,
);
}
#[test]
fn empty_body_records_client_error() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="client_error",error_class="empty_body",input_mime_type="text/markdown",output_mime_type="none"} 1"#,
);
}
#[test]
fn invalid_utf8_records_client_error() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = common::accepted_markdown_request(Body::from(b"\xFF\xFE\x00".to_vec()));
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="client_error",error_class="body_not_utf8",input_mime_type="text/markdown",output_mime_type="none"} 1"#,
);
}
#[test]
fn unsupported_media_type_records_client_error() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = common::request(
"POST",
"/conversion",
&[
("content-type", "application/json"),
("accept", "application/vnd.docspec.blocknote+json"),
],
Body::from(r#"{"hello": "world"}"#),
);
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="client_error",error_class="unsupported_media_type",input_mime_type="unsupported",output_mime_type="none"} 1"#,
);
}
#[test]
fn not_acceptable_records_client_error() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = common::request(
"POST",
"/conversion",
&[
("content-type", "text/markdown"),
("accept", "application/json"),
],
Body::from("# Hello"),
);
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="client_error",error_class="not_acceptable",input_mime_type="text/markdown",output_mime_type="none"} 1"#,
);
}
#[test]
fn conversion_duration_recorded_on_success() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("# Hello")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversion_duration_seconds_count{result="success",input_mime_type="text/markdown",output_mime_type="application/vnd.docspec.blocknote+json"} 1"#,
);
}
#[test]
fn conversion_duration_recorded_on_error() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversion_duration_seconds_count{result="client_error",input_mime_type="text/markdown",output_mime_type="none"} 1"#,
);
}
#[test]
fn body_size_histogram_records_correct_byte_count() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("# Hello")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_http_request_body_bytes_sum{input_mime_type="text/markdown"} 7"#,
);
}
fn assert_metric_value_gt(rendered: &str, prefix: &str, threshold: f64) {
let line = rendered
.lines()
.find(|line| line.starts_with(prefix))
.unwrap_or_else(|| {
panic!(
"Metric line with prefix not found.\n prefix: {prefix}\n rendered:\n{rendered}"
)
});
let value_str = line.rsplit_once(' ').map_or_else(
|| panic!("Metric line has no space-separated value.\n line: {line}"),
|(_, v)| v,
);
let value: f64 = value_str
.parse()
.unwrap_or_else(|_| panic!("Metric value is not a float.\n value: {value_str}"));
assert!(
value > threshold,
"Expected metric value > {threshold}, got {value}.\n line: {line}"
);
}
#[test]
fn input_mime_unsupported_when_other_content_type() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = Request::builder()
.method("POST")
.uri("/conversion")
.header("content-type", "application/pdf")
.header("accept", "application/vnd.docspec.blocknote+json")
.body(Body::from("foo"))
.unwrap();
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="client_error",error_class="unsupported_media_type",input_mime_type="unsupported",output_mime_type="none"} 1"#,
);
}
#[test]
fn input_mime_none_when_no_content_type() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = Request::builder()
.method("POST")
.uri("/conversion")
.header("accept", "application/vnd.docspec.blocknote+json")
.body(Body::from("# x"))
.unwrap();
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="client_error",error_class="unsupported_media_type",input_mime_type="none",output_mime_type="none"} 1"#,
);
}
#[test]
fn output_bytes_recorded_on_success() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("# Hello")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversion_output_bytes_count{input_mime_type="text/markdown",output_mime_type="application/vnd.docspec.blocknote+json"} 1"#,
);
assert_metric_value_gt(
&rendered,
r#"docspec_conversion_output_bytes_sum{input_mime_type="text/markdown",output_mime_type="application/vnd.docspec.blocknote+json"}"#,
0.0,
);
}
#[test]
fn output_bytes_not_recorded_on_error() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
metrics::with_local_recorder(&recorder, || {
rt.block_on(router.oneshot(common::accepted_markdown_request("")))
})
.expect("oneshot succeeds");
let rendered = handle.render();
assert!(
!rendered
.lines()
.any(|l| l.starts_with("docspec_conversion_output_bytes")),
"Expected no docspec_conversion_output_bytes lines on error, but found some.\n rendered:\n{rendered}",
);
}
#[test]
fn output_bytes_not_recorded_on_unsupported_media() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = Request::builder()
.method("POST")
.uri("/conversion")
.header("content-type", "application/pdf")
.header("accept", "application/vnd.docspec.blocknote+json")
.body(Body::from("foo"))
.unwrap();
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert!(
!rendered
.lines()
.any(|l| l.starts_with("docspec_conversion_output_bytes")),
"Expected no docspec_conversion_output_bytes lines on error, but found some.\n rendered:\n{rendered}",
);
}
#[test]
fn html_success_records_html_output_mime() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = Request::builder()
.method("POST")
.uri("/conversion")
.header("content-type", "text/markdown")
.header("accept", "text/html")
.body(Body::from("Hello"))
.unwrap();
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="success",error_class="none",input_mime_type="text/markdown",output_mime_type="text/html"} 1"#,
);
}
#[test]
fn oxa_success_records_oxa_output_mime() {
let rt = common::runtime();
let (recorder, handle) = docspec_http::metrics::build_recorder().expect("builds");
let router = docspec_http::router::router_with_metrics(handle.clone());
let request = Request::builder()
.method("POST")
.uri("/conversion")
.header("content-type", "text/markdown")
.header("accept", "application/vnd.oxa+json")
.body(Body::from("Hello"))
.unwrap();
metrics::with_local_recorder(&recorder, || rt.block_on(router.oneshot(request)))
.expect("oneshot succeeds");
let rendered = handle.render();
assert_metric_line(
&rendered,
r#"docspec_conversions_total{result="success",error_class="none",input_mime_type="text/markdown",output_mime_type="application/vnd.oxa+json"} 1"#,
);
}