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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#![deny(missing_docs, warnings)]
extern crate iron;
#[macro_use] extern crate log;
extern crate time;
use iron::{AfterMiddleware, BeforeMiddleware, IronResult, IronError, Request, Response};
use iron::typemap::Key;
use format::FormatText::{Str, Method, URI, Status, ResponseTime, RemoteAddr, RequestTime};
use format::{ContextDisplay, FormatText};
use std::fmt::{Display, Formatter};
mod format;
pub use format::Format;
pub struct Logger {
format: Format,
}
impl Logger {
pub fn new(format: Option<Format>) -> (Logger, Logger) {
let format = format.unwrap_or_default();
(Logger { format: format.clone() }, Logger { format: format })
}
}
struct StartTime;
impl Key for StartTime { type Value = time::Tm; }
impl Logger {
fn initialise(&self, req: &mut Request) {
req.extensions.insert::<StartTime>(time::now());
}
fn log(&self, req: &mut Request, res: &Response) -> IronResult<()> {
let entry_time = *req.extensions.get::<StartTime>().unwrap();
let response_time = time::now() - entry_time;
let response_time_ms = (response_time.num_seconds() * 1000) as f64 + (response_time.num_nanoseconds().unwrap_or(0) as f64) / 1000000.0;
{
let render = |fmt: &mut Formatter, text: &FormatText| {
match *text {
Str(ref string) => fmt.write_str(string),
Method => req.method.fmt(fmt),
URI => req.url.fmt(fmt),
Status => {
match res.status {
Some(status) => status.fmt(fmt),
None => fmt.write_str("<missing status code>"),
}
}
ResponseTime => fmt.write_fmt(format_args!("{} ms", response_time_ms)),
RemoteAddr => req.remote_addr.fmt(fmt),
RequestTime => {
entry_time.strftime("%Y-%m-%dT%H:%M:%S.%fZ%z")
.unwrap()
.fmt(fmt)
}
}
};
info!("{}", self.format.display_with(&render));
}
Ok(())
}
}
impl BeforeMiddleware for Logger {
fn before(&self, req: &mut Request) -> IronResult<()> {
self.initialise(req);
Ok(())
}
fn catch(&self, req: &mut Request, err: IronError) -> IronResult<()> {
self.initialise(req);
Err(err)
}
}
impl AfterMiddleware for Logger {
fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
try!(self.log(req, &res));
Ok(res)
}
fn catch(&self, req: &mut Request, err: IronError) -> IronResult<Response> {
try!(self.log(req, &err.response));
Err(err)
}
}