slog_json/
lib.rs

1// {{{ Crate docs
2//! JSON `Drain` for `slog-rs`
3//!
4//! ```
5//! #[macro_use]
6//! extern crate slog;
7//!
8//! use slog::Drain;
9//! use std::sync::Mutex;
10//!
11//! fn main() {
12//!     let root = slog::Logger::root(
13//!         Mutex::new(slog_json::Json::default(std::io::stderr())).map(slog::Fuse),
14//!         o!("version" => env!("CARGO_PKG_VERSION"))
15//!     );
16//! }
17//! ```
18// }}}
19
20// {{{ Imports & meta
21#![warn(missing_docs)]
22#[macro_use]
23extern crate slog;
24
25use serde::ser::SerializeMap;
26use serde::serde_if_integer128;
27use slog::Key;
28use slog::Record;
29use slog::{FnValue, PushFnValue};
30use slog::{OwnedKVList, SendSyncRefUnwindSafeKV, KV};
31use std::{fmt, io, result};
32
33use std::cell::RefCell;
34use std::fmt::Write;
35
36// }}}
37
38// {{{ Serialize
39thread_local! {
40    static TL_BUF: RefCell<String> = RefCell::new(String::with_capacity(128))
41}
42
43/// `slog::Serializer` adapter for `serde::Serializer`
44///
45/// Newtype to wrap serde Serializer, so that `Serialize` can be implemented
46/// for it
47struct SerdeSerializer<S: serde::Serializer> {
48    /// Current state of map serializing: `serde::Serializer::MapState`
49    ser_map: S::SerializeMap,
50}
51
52impl<S: serde::Serializer> SerdeSerializer<S> {
53    /// Start serializing map of values
54    fn start(ser: S, len: Option<usize>) -> result::Result<Self, slog::Error> {
55        let ser_map = ser.serialize_map(len).map_err(|e| {
56            io::Error::new(
57                io::ErrorKind::Other,
58                format!("serde serialization error: {}", e),
59            )
60        })?;
61        Ok(SerdeSerializer { ser_map })
62    }
63
64    /// Finish serialization, and return the serializer
65    fn end(self) -> result::Result<S::Ok, S::Error> {
66        self.ser_map.end()
67    }
68}
69
70macro_rules! impl_m(
71    ($s:expr, $key:expr, $val:expr) => ({
72        let k_s:  &str = $key.as_ref();
73        $s.ser_map.serialize_entry(k_s, $val)
74             .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("serde serialization error: {}", e)))?;
75        Ok(())
76    });
77);
78
79impl<S> slog::Serializer for SerdeSerializer<S>
80where
81    S: serde::Serializer,
82{
83    fn emit_bool(&mut self, key: Key, val: bool) -> slog::Result {
84        impl_m!(self, key, &val)
85    }
86
87    fn emit_unit(&mut self, key: Key) -> slog::Result {
88        impl_m!(self, key, &())
89    }
90
91    fn emit_char(&mut self, key: Key, val: char) -> slog::Result {
92        impl_m!(self, key, &val)
93    }
94
95    fn emit_none(&mut self, key: Key) -> slog::Result {
96        let val: Option<()> = None;
97        impl_m!(self, key, &val)
98    }
99    fn emit_u8(&mut self, key: Key, val: u8) -> slog::Result {
100        impl_m!(self, key, &val)
101    }
102    fn emit_i8(&mut self, key: Key, val: i8) -> slog::Result {
103        impl_m!(self, key, &val)
104    }
105    fn emit_u16(&mut self, key: Key, val: u16) -> slog::Result {
106        impl_m!(self, key, &val)
107    }
108    fn emit_i16(&mut self, key: Key, val: i16) -> slog::Result {
109        impl_m!(self, key, &val)
110    }
111    fn emit_usize(&mut self, key: Key, val: usize) -> slog::Result {
112        impl_m!(self, key, &val)
113    }
114    fn emit_isize(&mut self, key: Key, val: isize) -> slog::Result {
115        impl_m!(self, key, &val)
116    }
117    fn emit_u32(&mut self, key: Key, val: u32) -> slog::Result {
118        impl_m!(self, key, &val)
119    }
120    fn emit_i32(&mut self, key: Key, val: i32) -> slog::Result {
121        impl_m!(self, key, &val)
122    }
123    fn emit_f32(&mut self, key: Key, val: f32) -> slog::Result {
124        impl_m!(self, key, &val)
125    }
126    fn emit_u64(&mut self, key: Key, val: u64) -> slog::Result {
127        impl_m!(self, key, &val)
128    }
129    fn emit_i64(&mut self, key: Key, val: i64) -> slog::Result {
130        impl_m!(self, key, &val)
131    }
132    fn emit_f64(&mut self, key: Key, val: f64) -> slog::Result {
133        impl_m!(self, key, &val)
134    }
135    serde_if_integer128! {
136        fn emit_u128(&mut self, key: Key, val: u128) -> slog::Result {
137            impl_m!(self, key, &val)
138        }
139        fn emit_i128(&mut self, key: Key, val: i128) -> slog::Result {
140            impl_m!(self, key, &val)
141        }
142    }
143    fn emit_str(&mut self, key: Key, val: &str) -> slog::Result {
144        impl_m!(self, key, &val)
145    }
146    fn emit_arguments(
147        &mut self,
148        key: Key,
149        val: &fmt::Arguments,
150    ) -> slog::Result {
151        TL_BUF.with(|buf| {
152            let mut buf = buf.borrow_mut();
153
154            buf.write_fmt(*val).unwrap();
155
156            let res = { || impl_m!(self, key, &*buf) }();
157            buf.clear();
158            res
159        })
160    }
161
162    #[cfg(feature = "nested-values")]
163    fn emit_serde(
164        &mut self,
165        key: Key,
166        value: &dyn slog::SerdeValue,
167    ) -> slog::Result {
168        impl_m!(self, key, value.as_serde())
169    }
170}
171// }}}
172
173// {{{ Json
174/// Json `Drain`
175///
176/// Each record will be printed as a Json map
177/// to a given `io`
178pub struct Json<W: io::Write> {
179    newlines: bool,
180    flush: bool,
181    values: Vec<OwnedKVList>,
182    io: RefCell<W>,
183    pretty: bool,
184}
185
186impl<W> Json<W>
187where
188    W: io::Write,
189{
190    /// New `Json` `Drain` with default key-value pairs added
191    pub fn default(io: W) -> Json<W> {
192        JsonBuilder::new(io).add_default_keys().build()
193    }
194
195    /// Build custom `Json` `Drain`
196    #[cfg_attr(feature = "cargo-clippy", allow(clippy::new_ret_no_self))]
197    pub fn new(io: W) -> JsonBuilder<W> {
198        JsonBuilder::new(io)
199    }
200
201    fn log_impl<F>(
202        &self,
203        serializer: &mut serde_json::ser::Serializer<&mut W, F>,
204        rinfo: &Record,
205        logger_values: &OwnedKVList,
206    ) -> io::Result<()>
207    where
208        F: serde_json::ser::Formatter,
209    {
210        let mut serializer = SerdeSerializer::start(&mut *serializer, None)?;
211
212        for kv in &self.values {
213            kv.serialize(rinfo, &mut serializer)?;
214        }
215
216        logger_values.serialize(rinfo, &mut serializer)?;
217
218        rinfo.kv().serialize(rinfo, &mut serializer)?;
219
220        let res = serializer.end();
221
222        res.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
223
224        Ok(())
225    }
226}
227
228impl<W> slog::Drain for Json<W>
229where
230    W: io::Write,
231{
232    type Ok = ();
233    type Err = io::Error;
234    fn log(
235        &self,
236        rinfo: &Record,
237        logger_values: &OwnedKVList,
238    ) -> io::Result<()> {
239        let mut io = self.io.borrow_mut();
240        let io = if self.pretty {
241            let mut serializer = serde_json::Serializer::pretty(&mut *io);
242            self.log_impl(&mut serializer, rinfo, logger_values)?;
243            serializer.into_inner()
244        } else {
245            let mut serializer = serde_json::Serializer::new(&mut *io);
246            self.log_impl(&mut serializer, rinfo, logger_values)?;
247            serializer.into_inner()
248        };
249        if self.newlines {
250            io.write_all("\n".as_bytes())?;
251        }
252        if self.flush {
253            io.flush()?;
254        }
255        Ok(())
256    }
257}
258
259// }}}
260
261// {{{ JsonBuilder
262/// Json `Drain` builder
263///
264/// Create with `Json::new`.
265pub struct JsonBuilder<W: io::Write> {
266    newlines: bool,
267    flush: bool,
268    values: Vec<OwnedKVList>,
269    io: W,
270    pretty: bool,
271}
272
273impl<W> JsonBuilder<W>
274where
275    W: io::Write,
276{
277    fn new(io: W) -> Self {
278        JsonBuilder {
279            newlines: true,
280            flush: false,
281            values: vec![],
282            io,
283            pretty: false,
284        }
285    }
286
287    /// Build `Json` `Drain`
288    ///
289    /// This consumes the builder.
290    pub fn build(self) -> Json<W> {
291        Json {
292            values: self.values,
293            newlines: self.newlines,
294            flush: self.flush,
295            io: RefCell::new(self.io),
296            pretty: self.pretty,
297        }
298    }
299
300    /// Set writing a newline after every log record
301    pub fn set_newlines(mut self, enabled: bool) -> Self {
302        self.newlines = enabled;
303        self
304    }
305
306    /// Enable flushing of the `io::Write` after every log record
307    pub fn set_flush(mut self, enabled: bool) -> Self {
308        self.flush = enabled;
309        self
310    }
311
312    /// Set whether or not pretty formatted logging should be used
313    pub fn set_pretty(mut self, enabled: bool) -> Self {
314        self.pretty = enabled;
315        self
316    }
317
318    /// Add custom values to be printed with this formatter
319    pub fn add_key_value<T>(mut self, value: slog::OwnedKV<T>) -> Self
320    where
321        T: SendSyncRefUnwindSafeKV + 'static,
322    {
323        self.values.push(value.into());
324        self
325    }
326
327    /// Add default key-values:
328    ///
329    /// * `ts` - timestamp
330    /// * `level` - record logging level name
331    /// * `msg` - msg - formatted logging message
332    pub fn add_default_keys(self) -> Self {
333        self.add_key_value(o!(
334            "ts" => FnValue(move |_ : &Record| {
335                    time::OffsetDateTime::now_utc()
336                    .format(&time::format_description::well_known::Rfc3339)
337                    .ok()
338            }),
339            "level" => FnValue(move |rinfo : &Record| {
340                rinfo.level().as_short_str()
341            }),
342            "msg" => PushFnValue(move |record : &Record, ser| {
343                ser.emit(record.msg())
344            }),
345        ))
346    }
347}
348// }}}
349// vim: foldmethod=marker foldmarker={{{,}}}