struct_log_self/
struct-log-self.rs

1//! Example of how to implement `KV` for a struct
2//! to conveniently log data associated with it.
3#[macro_use]
4extern crate slog;
5use slog::*;
6
7mod common;
8
9struct Peer {
10    host: String,
11    port: u32,
12}
13
14impl Peer {
15    fn new(host: String, port: u32) -> Self {
16        Peer {
17            host: host,
18            port: port,
19        }
20    }
21}
22
23// `KV` can be implemented for a struct
24impl KV for Peer {
25    fn serialize(&self, _record: &Record, serializer: &mut Serializer) -> Result {
26        serializer.emit_u32(Key::from("peer-port"), self.port)?;
27        serializer.emit_str(Key::from("peer-host"), &self.host)?;
28        Ok(())
29    }
30}
31
32struct Server {
33    _host: String,
34    _port: u32,
35    // One approach is to create new `Logger` with struct data
36    // and embedded it into struct itself.  This works when struct is mostly
37    // immutable.
38    log: Logger,
39}
40
41impl Server {
42    fn new(host: String, port: u32, log: Logger) -> Server {
43        let log = log.new(o!("server-host" => host.clone(), "server-port" => port));
44        Server {
45            _host: host,
46            _port: port,
47            log: log,
48        }
49    }
50
51    fn connection(&self, peer: &Peer) {
52        // Another approach is to add struct to a logging message when it's
53        // necessary. This might be necessary when struct data can change
54        // between different logging statements (not the case here for `Peer`).
55        info!(self.log, "new connection"; peer);
56    }
57}
58
59struct PeerCounter {
60    count: usize,
61    log: Logger,
62}
63
64impl PeerCounter {
65    fn new(log: Logger) -> Self {
66        PeerCounter { count: 0, log: log }
67    }
68
69    // A hybrid approach with `Logger` with parent logging-context embedded into
70    // a `struct` and a helper function adding mutable fields.
71    fn log_info(&self, msg: &str, kv: BorrowedKV) {
72        info!(self.log, "{}", msg; "current-count" => self.count, kv);
73    }
74
75    fn count(&mut self, peer: &Peer) {
76        self.count += 1;
77        self.log_info("counted peer", b!(peer));
78    }
79}
80
81fn main() {
82    let log = Logger::root(Fuse(common::PrintlnDrain), o!("build-id" => "7.3.3-abcdef"));
83
84    let server = Server::new("localhost".into(), 12345, log.clone());
85
86    let peer = Peer::new("1.2.3.4".into(), 999);
87    server.connection(&peer);
88    let mut counter = PeerCounter::new(log);
89    counter.count(&peer);
90}