-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace chrono dependency by time (#578)
[chrono](https://crates.io/crates/chrono) has not releases for very long time. Also, it has security error: https://rustsec.org/advisories/RUSTSEC-2020-0159.html Also, this would reduce dependencies because chrono uses very old time version so many binaries which use gotham ends with 2 versions of time linked. Co-authored-by: msrd0 <msrd0@users.noreply.github.com>
- Loading branch information
1 parent
097822e
commit ca0f906
Showing
3 changed files
with
62 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,85 @@ | ||
//! Defines types for timing requests and emitting timing information. | ||
use chrono::prelude::*; | ||
use std::fmt::{self, Display, Formatter}; | ||
use std::time::{Duration, Instant}; | ||
|
||
use time::OffsetDateTime; | ||
|
||
/// Timer struct used to record execution times of requests. | ||
/// | ||
/// The `elapsed` function returns the elapsed time in an easy to format way, | ||
/// suitable for use with requset logging middlewares. | ||
#[derive(Clone, Copy)] | ||
pub(crate) struct Timer { | ||
start: DateTime<Utc>, | ||
// We use 2 start fields | ||
// because we want formattable time to print start time | ||
// but we cannot use it to calculate duration because it is not monotonic. | ||
// | ||
// It is possible that we spent a lot of time between initialization of fields, | ||
// for example, if current thread unscheduled by OS but it should be very rare. | ||
// On the other hand, adjusting system clock by NTP is much more possible. | ||
start_monotonic: Instant, | ||
start_formattable: OffsetDateTime, | ||
} | ||
|
||
impl Timer { | ||
/// Begins measuring from the current time. | ||
pub(crate) fn new() -> Timer { | ||
Timer { start: Utc::now() } | ||
Timer { | ||
start_monotonic: Instant::now(), | ||
start_formattable: OffsetDateTime::now_utc(), | ||
} | ||
} | ||
|
||
/// Finishes measuring, and returns the elapsed time as a `Timing` value. | ||
pub(crate) fn elapsed(&self) -> Timing { | ||
let duration = Utc::now() | ||
.signed_duration_since(self.start) | ||
.num_microseconds(); | ||
|
||
match duration { | ||
Some(dur) => Timing::Microseconds(dur), | ||
None => Timing::Invalid, | ||
} | ||
let duration = self.start_monotonic.elapsed(); | ||
Timing(duration) | ||
} | ||
|
||
/// Retrieves the start time of this timer. | ||
pub(crate) fn start_time(&self) -> &DateTime<Utc> { | ||
&self.start | ||
pub(crate) fn start_time(&self) -> &OffsetDateTime { | ||
&self.start_formattable | ||
} | ||
} | ||
|
||
/// Represents an elapsed time measured by `Timer`. | ||
#[derive(Clone, Copy)] | ||
pub(crate) enum Timing { | ||
/// A number of microseconds measured by `Timer`. | ||
Microseconds(i64), | ||
|
||
/// An invalid state, where the amount of time elapsed was unable to be measured. | ||
Invalid, | ||
} | ||
pub(crate) struct Timing(Duration); | ||
|
||
impl Display for Timing { | ||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
match *self { | ||
Timing::Microseconds(i) => { | ||
if i < 1000 { | ||
write!(f, "{}µs", i) | ||
} else if i < 1_000_000 { | ||
write!(f, "{:.2}ms", (i as f32) / 1000.0) | ||
} else { | ||
write!(f, "{:.2}s", (i as f32) / 1_000_000.0) | ||
} | ||
let duration = self.0; | ||
match duration.as_micros() { | ||
i if i < 1000 => { | ||
write!(f, "{}µs", i) | ||
} | ||
i if i < 1_000_000 => { | ||
write!(f, "{:.2}ms", (i as f64) / 1000.0) | ||
} | ||
_ => { | ||
write!(f, "{:.2}s", duration.as_secs_f32()) | ||
} | ||
Timing::Invalid => f.write_str("invalid"), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::time::Duration; | ||
|
||
use super::Timing; | ||
|
||
#[test] | ||
fn test_durations() { | ||
let microsecond = Duration::from_micros(1); | ||
|
||
let t0 = Timing(microsecond * 555); | ||
assert_eq!(t0.to_string(), "555µs"); | ||
|
||
let t1 = Timing(microsecond * 666_444); | ||
assert_eq!(t1.to_string(), "666.44ms"); | ||
|
||
let t2 = Timing(microsecond * 777_444_333); | ||
assert_eq!(t2.to_string(), "777.44s"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters