1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![deny(unsafe_code, missing_docs)]
extern crate chrono;
extern crate slog;
extern crate syslog5424;
pub use syslog5424::iana::{Origin, TimeQuality};
pub use syslog5424::types::Facility;
pub use syslog5424::{Error, Rfc5424, Rfc5424Builder, WriteFormat};
use chrono::{SecondsFormat, Utc};
use slog::{Drain, Level, OwnedKVList, Record, Serializer, KV};
use syslog5424::types::{Message, Severity};
use syslog5424::{Rfc5424Data, StructuredData};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Arguments;
use std::io::{self, Write};
#[derive(Debug)]
pub struct Rfc5424Writer<W: Write> {
writer: RefCell<W>,
formatter: Rfc5424,
}
impl<W: Write> Rfc5424Writer<W> {
pub fn new(writer: W, formatter: Rfc5424) -> Rfc5424Writer<W> {
Rfc5424Writer {
writer: RefCell::new(writer),
formatter,
}
}
}
struct CompleteLogEntry<'a> {
record: &'a Record<'a>,
values: &'a OwnedKVList,
}
struct StructuredWrapper(Vec<(String, String)>);
impl<'a> Serializer for StructuredWrapper {
fn emit_arguments(&mut self, key: slog::Key, val: &Arguments) -> slog::Result {
self.0.push((key.to_string(), format!("{}", val)));
Ok(())
}
}
impl<'a> Rfc5424Data for CompleteLogEntry<'a> {
fn severity(&self) -> Severity {
match self.record.level() {
Level::Critical => Severity::Critical,
Level::Error => Severity::Error,
Level::Warning => Severity::Warning,
Level::Info => Severity::Informational,
Level::Debug => Severity::Debug,
Level::Trace => Severity::Debug,
}
}
fn timestamp(&self) -> Option<String> {
Some(Utc::now().to_rfc3339_opts(SecondsFormat::Micros, false))
}
fn structured_data(&self) -> Option<StructuredData> {
let mut data: StructuredData = HashMap::new();
let mut buf = StructuredWrapper(Vec::new());
self.record.kv().serialize(self.record, &mut buf).unwrap();
self.values.serialize(self.record, &mut buf).unwrap();
data.insert("slog", buf.0);
Some(data)
}
fn message(&self) -> Option<Message> {
Some(Message::Text(format!("{}", self.record.msg())))
}
}
impl<W: Write> Drain for Rfc5424Writer<W> {
type Ok = ();
type Err = io::Error;
fn log(&self, record: &Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
let msg = CompleteLogEntry { record, values };
let mut writer = self.writer.borrow_mut();
self.formatter.format(&mut *writer, &msg)
}
}