Skip to content

Commit 39594b3

Browse files
authored
Normalize HTTP routes when recording HTTP latencies (#3781)
Fixes #3780
1 parent 92467bd commit 39594b3

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

oximeter/instruments/src/http.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use dropshot::{
1111
};
1212
use futures::Future;
1313
use http::StatusCode;
14+
use http::Uri;
1415
use oximeter::histogram::Histogram;
1516
use oximeter::{Metric, MetricsError, Producer, Sample, Target};
1617
use std::collections::BTreeMap;
@@ -36,6 +37,12 @@ pub struct RequestLatencyHistogram {
3637
pub latency: Histogram<f64>,
3738
}
3839

40+
// Return the route portion of the request, normalized to include a single
41+
// leading slash and no trailing slashes.
42+
fn normalized_uri_path(uri: &Uri) -> String {
43+
format!("/{}", uri.path().trim_end_matches('/').trim_start_matches('/'))
44+
}
45+
3946
impl RequestLatencyHistogram {
4047
/// Build a new `RequestLatencyHistogram` with a specified histogram.
4148
///
@@ -46,7 +53,7 @@ impl RequestLatencyHistogram {
4653
histogram: Histogram<f64>,
4754
) -> Self {
4855
Self {
49-
route: request.uri().path().to_string(),
56+
route: normalized_uri_path(request.uri()),
5057
method: request.method().to_string(),
5158
status_code: status_code.as_u16().into(),
5259
latency: histogram,
@@ -77,7 +84,7 @@ impl RequestLatencyHistogram {
7784
fn key_for(request: &RequestInfo, status_code: StatusCode) -> String {
7885
format!(
7986
"{}:{}:{}",
80-
request.uri().path(),
87+
normalized_uri_path(request.uri()),
8188
request.method(),
8289
status_code.as_u16()
8390
)
@@ -240,4 +247,21 @@ mod tests {
240247
let bins = actual_hist.iter().collect::<Vec<_>>();
241248
assert_eq!(bins[1].count, 1);
242249
}
250+
251+
#[test]
252+
fn test_normalize_uri_path() {
253+
const EXPECTED: &str = "/foo/bar";
254+
const TESTS: &[&str] = &[
255+
"/foo/bar",
256+
"/foo/bar/",
257+
"//foo/bar",
258+
"//foo/bar/",
259+
"/foo/bar//",
260+
"////foo/bar/////",
261+
];
262+
for test in TESTS.iter() {
263+
println!("{test}");
264+
assert_eq!(normalized_uri_path(&test.parse().unwrap()), EXPECTED);
265+
}
266+
}
243267
}

0 commit comments

Comments
 (0)