slog_gelf/
lib.rs

1mod chunked;
2mod level;
3mod message;
4mod udp;
5
6extern crate chrono;
7extern crate flate2;
8extern crate rand;
9extern crate serde;
10extern crate serde_json;
11extern crate slog;
12
13use flate2::{write::GzEncoder, Compression};
14use slog::{Drain, Key, OwnedKVList, Record, KV};
15use std::io;
16use std::io::prelude::*;
17
18use chunked::ChunkSize;
19use message::Message;
20use udp::UdpDestination;
21
22static VERSION: &'static str = "1.1";
23
24pub struct Gelf {
25    source: String,
26    destination: UdpDestination,
27}
28
29impl Gelf {
30    pub fn new(source: &str, destination: &str) -> Result<Self, io::Error> {
31        let destination = UdpDestination::new(destination, ChunkSize::LAN)?;
32
33        Ok(Gelf {
34            source: source.to_owned(),
35            destination,
36        })
37    }
38}
39
40pub struct KeyValueList(pub Vec<(Key, String)>);
41
42impl slog::Serializer for KeyValueList {
43    fn emit_arguments(&mut self, key: Key, val: &std::fmt::Arguments) -> slog::Result {
44        self.0.push((key, format!("{}", val)));
45        Ok(())
46    }
47}
48
49impl Drain for Gelf {
50    type Ok = ();
51    type Err = io::Error;
52
53    fn log(&self, record: &Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
54        let mut additional = KeyValueList(Vec::with_capacity(16));
55        record.kv().serialize(record, &mut additional)?;
56        values.serialize(record, &mut additional)?;
57
58        let message = Message {
59            version: VERSION,
60            host: &self.source,
61            short_message: record.msg().to_string(),
62            full_message: None,
63            timestamp: Some(timestamp()),
64            level: Some(record.level().into()),
65            module: Some(record.location().module),
66            file: Some(record.location().file),
67            line: Some(record.location().line),
68            column: None,
69            additional: additional.0,
70        };
71
72        let serialized = serde_json::to_vec(&message)?;
73
74        let mut e = GzEncoder::new(Vec::new(), Compression::default());
75        e.write_all(&serialized)?;
76        let compressed = e.finish()?;
77        let _ = self.destination.log(compressed);
78
79        Ok(())
80    }
81}
82
83fn timestamp() -> f64 {
84    let now = chrono::Utc::now();
85    let milliseconds = (now.timestamp() as f64) + (now.timestamp_subsec_millis() as f64) / 1E3;
86    milliseconds
87}