1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
/*!
Monitor back-end performance using Server-Timing the HTTP header.
```
use simple_server_timing_header::Timer;
fn handle_request() {
let mut timer = Timer::new();
// ... do some stuff
timer.add("parse_headers");
// ... do some more stuff
timer.add("get_db_data");
// Generate the header value
assert_eq!(timer.header_value(), "parse_headers;dur=0, get_db_data;dur=0");
}
```
*/
use std::time::Instant;
/// Timer used to share performance metrics to the client using the HTTP Server-Timing header
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing
pub struct Timer {
last: Instant,
timings: Vec<Timing>,
}
struct Timing {
name: String,
/// Time in milliseconds
duration: u128,
}
impl Timer {
pub fn new() -> Self {
Timer {
last: Instant::now(),
timings: Vec::new(),
}
}
/// Adds a named measurement, counting from the last one
pub fn add(&mut self, name: &str) {
let now = Instant::now();
let duration = now.duration_since(self.last).as_millis();
self.last = now;
self.timings.push(Timing {
name: name.into(),
duration,
});
}
// Header key for `Server-Timing`
pub fn header_key() -> &'static str {
"Server-Timing"
}
/// Returns the value for a Server-Timings header.
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing
pub fn header_value(&self) -> String {
let mut out = String::new();
use std::fmt::Write;
for timing in self.timings.iter() {
_ = write!(out, "{};dur={}, ", timing.name, timing.duration);
}
// remove the trailing ", "
out.pop();
out.pop();
out
}
}
impl Default for Timer {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let mut timer = Timer::new();
// ... do some stuff
timer.add("parse_headers");
// ... do some more stuff
timer.add("get_db_data");
// Generate the header value
assert_eq!(
timer.header_value(),
"parse_headers;dur=0, get_db_data;dur=0"
);
}
}