-
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.
Merge pull request #60 from gotham-rs/catch-panics
Catch synchronous panics in `NewHandlerService`
- Loading branch information
Showing
15 changed files
with
363 additions
and
135 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
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 |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//! Defines types for timing requests and emitting timing information into logs and responses. | ||
|
||
use std::fmt::{self, Display, Formatter}; | ||
|
||
use chrono::prelude::*; | ||
use hyper::Response; | ||
|
||
use state::{State, request_id}; | ||
use http::header::XRuntimeMicroseconds; | ||
|
||
/// Used by `NewHandlerService` to time requests. The `elapsed` function returns the elapsed time | ||
/// in a way that can be used for logging and adding the `X-Runtime-Microseconds` header to | ||
/// responses. | ||
#[derive(Clone, Copy)] | ||
pub(super) struct Timer { | ||
start: DateTime<Utc>, | ||
} | ||
|
||
impl Timer { | ||
/// Begins measuring from the current time. | ||
pub(super) fn new() -> Timer { | ||
Timer { start: Utc::now() } | ||
} | ||
|
||
/// Finishes measuring, and returns the elapsed time as a `Timing` value. | ||
pub(super) fn elapsed(self, state: &State) -> Timing { | ||
let timing = self.elapsed_no_logging(); | ||
|
||
if let Timing::Invalid = timing { | ||
error!( | ||
"[{}] Unable to measure timing of request, num_microseconds was None", | ||
request_id(state) | ||
); | ||
} | ||
|
||
timing | ||
} | ||
|
||
pub(super) fn elapsed_no_logging(self) -> Timing { | ||
let Timer { start } = self; | ||
match Utc::now().signed_duration_since(start).num_microseconds() { | ||
Some(dur) => Timing::Microseconds(dur), | ||
None => Timing::Invalid, | ||
} | ||
} | ||
} | ||
|
||
/// Represents an elapsed time measured by `Timer`. | ||
#[derive(Clone, Copy)] | ||
pub(super) 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, | ||
} | ||
|
||
impl Timing { | ||
/// Converts a `Response` into a new `Response` with the `X-Runtime-Microseconds` header | ||
/// included (assuming the time elapsed was able to be measured). | ||
pub(super) fn add_to_response(&self, response: Response) -> Response { | ||
match *self { | ||
Timing::Microseconds(i) => response.with_header(XRuntimeMicroseconds(i)), | ||
Timing::Invalid => response, | ||
} | ||
} | ||
} | ||
|
||
impl Display for Timing { | ||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
match *self { | ||
Timing::Microseconds(i) => { | ||
i.fmt(f)?; | ||
f.write_str("µs") | ||
} | ||
Timing::Invalid => f.write_str("invalid"), | ||
} | ||
} | ||
} |
Oops, something went wrong.