1 ///! Parsers for rfc 5424 specific formats.
2 use crate::{
3 message::{Protocol, Message},
4 parsers::{appname, digits, hostname, msgid, procid},
5 pri::pri,
6 timestamp::timestamp_3339,
7 structured_data::structured_data,
8 };
9 use nom::{
10 character::complete::{space0, space1},
11 combinator::{rest, map},
12 sequence::tuple,
13 IResult,
14 };
15
16 /// Parse the version number - just a simple integer.
version(input: &str) -> IResult<&str, u32>17 fn version(input: &str) -> IResult<&str, u32> {
18 digits(input)
19 }
20
21 /// Parse the message as per RFC5424
parse(input: &str) -> IResult<&str, Message<&str>>22 pub(crate) fn parse(input: &str) -> IResult<&str, Message<&str>> {
23 map(
24 tuple((
25 pri, version, space1, timestamp_3339, space1, hostname, space1, appname, space1, procid,
26 space1, msgid, space0, structured_data, space0, rest,
27 )),
28 |(pri, version, _, timestamp, _, hostname, _, appname, _, procid, _, msgid, _, structured_data, _, msg)| Message {
29 protocol: Protocol::RFC5424(version),
30 facility: pri.0,
31 severity: pri.1,
32 timestamp: Some(timestamp),
33 hostname,
34 appname,
35 procid: procid.map(|p| p.into()),
36 msgid,
37 structured_data,
38 msg
39 },
40 )(input)
41 }
42
43 #[cfg(test)]
44 mod tests {
45 use super::*;
46 use crate::pri::{SyslogFacility, SyslogSeverity};
47 use chrono::prelude::*;
48
49 #[test]
parse_5424()50 fn parse_5424() {
51 assert_eq!(
52 parse("<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - message").unwrap(),
53 (
54 "",
55 Message {
56 protocol: Protocol::RFC5424(1),
57 facility: Some(SyslogFacility::LOG_AUTH),
58 severity: Some(SyslogSeverity::SEV_CRIT),
59 timestamp: Some(
60 FixedOffset::west(0)
61 .ymd(2003, 10, 11)
62 .and_hms_milli(22, 14, 15, 3)
63 ),
64 hostname: Some("mymachine.example.com"),
65 appname: Some("su"),
66 procid: None,
67 msgid: Some("ID47"),
68 structured_data: vec![],
69 msg: "message",
70 }
71 )
72 )
73 }
74 }
75