1#![deny(missing_docs, warnings)]
6
7#[macro_use]
8extern crate slog;
9extern crate chrono;
10extern crate iron;
11
12mod format;
13pub use format::{LogContext, LogFormatter, DefaultLogFormatter};
14
15use std::fmt;
16use iron::{Request, Response, IronResult, Handler};
17use slog::Logger;
18
19
20struct Format<'req, 'res, 'a: 'req, 'b: 'a, 's, 'e, 'f, F: ?Sized + LogFormatter> {
21 context: LogContext<'req, 'res, 'a, 'b, 's, 'e>,
22 formatter: &'f F,
23}
24
25impl<'req, 'res, 'a: 'req, 'b: 'a, 's, 'e, 'f, F: ?Sized + LogFormatter> fmt::Display
26 for Format<'req, 'res, 'a, 'b, 's, 'e, 'f, F> {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 self.formatter.format(f, &self.context)
29 }
30}
31
32
33pub struct LoggerMiddleware<H: Handler, F: LogFormatter> {
35 formatter: F,
36 handler: H,
37 logger: Logger,
38}
39
40impl<H: Handler, F: LogFormatter> LoggerMiddleware<H, F> {
41 pub fn new(handler: H, logger: Logger, formatter: F) -> Self {
50 LoggerMiddleware {
51 handler,
52 logger,
53 formatter,
54 }
55 }
56}
57
58impl<H: Handler, F: LogFormatter> Handler for LoggerMiddleware<H, F> {
59 fn handle(&self, req: &mut Request) -> IronResult<Response> {
60 let start_time = chrono::Local::now();
61 let result = self.handler.handle(req);
62 let end_time = chrono::Local::now();
63
64 match result {
65 Ok(res) => {
66 info!(self.logger,
67 "{}",
68 Format {
69 context: LogContext {
70 req,
71 res: &res,
72 start_time: &start_time,
73 end_time: &end_time,
74 },
75 formatter: &self.formatter,
76 });
77 Ok(res)
78 }
79 Err(err) => {
80 error!(self.logger,
81 "{}",
82 Format {
83 context: LogContext {
84 req,
85 res: &err.response,
86 start_time: &start_time,
87 end_time: &end_time,
88 },
89 formatter: &self.formatter,
90 });
91 Err(err)
92 }
93 }
94 }
95}