slog_stream/
lib.rs

1//! `io::Write` streamer for slog-rs
2//!
3//! One of the main drains not included in the core `slog-rs` create.
4//! `Streamer` drain serializes logging records into stream of bytes
5//! using given `Format` and writes it to a given `io::Write`.
6#![warn(missing_docs)]
7
8#[macro_use]
9extern crate slog;
10extern crate slog_extra;
11extern crate thread_local;
12
13use slog::{Drain, DrainExt};
14
15use std::cell::RefCell;
16
17use std::sync::Mutex;
18use std::io;
19use slog::Record;
20
21use slog_extra::Async;
22use slog::OwnedKeyValueList;
23
24include!("format.rs");
25
26thread_local! {
27    static TL_BUF: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(128))
28}
29
30/// Drain formating records and writing them to a byte-stream (`io::Write`)
31///
32/// Uses mutex to serialize writes to `io`. Use `AsyncStreamer` for better
33/// performance, but without guarantee of immediate output.
34pub struct Streamer<W: io::Write, F: Format> {
35    io: Mutex<W>,
36    format: F,
37}
38
39impl<W: io::Write, F: Format> Streamer<W, F> {
40    /// Create new `Streamer` writing to `io` using `format`
41    pub fn new(io: W, format: F) -> Self {
42        Streamer {
43            io: Mutex::new(io),
44            format: format,
45        }
46    }
47}
48
49impl<W: 'static + io::Write + Send, F: Format + Send> Drain for Streamer<W, F> {
50    type Error = io::Error;
51
52    fn log(&self, info: &Record, logger_values: &OwnedKeyValueList) -> io::Result<()> {
53
54        TL_BUF.with(|buf| {
55            let mut buf = buf.borrow_mut();
56            let res = {
57                || {
58                    try!(self.format.format(&mut *buf, info, logger_values));
59                    {
60                        let mut io = try!(self.io
61                            .lock()
62                            .map_err(|_| io::Error::new(io::ErrorKind::Other, "lock error")));
63                        try!(io.write_all(&buf));
64                    }
65                    Ok(())
66                }
67            }();
68            buf.clear();
69            res
70        })
71    }
72}
73
74/// Stream logging records to IO
75///
76/// Create `Streamer` drain
77pub fn stream<W: io::Write + Send, F: Format>(io: W, format: F) -> Streamer<W, F> {
78    Streamer::new(io, format)
79}
80
81/// Stream logging records to IO asynchronously
82///
83/// Create `AsyncStreamer` drain
84pub fn async_stream<W: io::Write + Send + 'static, F: Format + Send + 'static>(io: W,
85                                                                               format: F)
86                                                                               -> Async {
87    Async::new(Streamer::new(io, format).fuse())
88}