diff --git a/docs/parsers/syslog_bsd.md b/docs/parsers/syslog_bsd.md index a3f9ecb0..824d62c6 100644 --- a/docs/parsers/syslog_bsd.md +++ b/docs/parsers/syslog_bsd.md @@ -5,15 +5,13 @@ jc - JSON Convert Syslog RFC 3164 string parser -<> +This parser accepts a single syslog line string or multiple syslog lines +separated by newlines. A warning message to `STDERR` will be printed if an +unparsable line is found. Usage (cli): - $ syslogstring | jc --syslog-bsd - -or - - $ jc syslog-3164 + $ echo '<34>Oct 11 22:14:15 mymachine su: su root...' | jc --syslog-bsd Usage (module): @@ -24,19 +22,41 @@ Schema: [ { - "syslog-3164": string, - "bar": boolean, - "baz": integer + "priority": integer/null, + "date": string, + "hostname": string, + "tag": string, + "content": string, + "unparsable": string, # [0] } ] + [0] this field exists if the syslog line is not parsable. The value + is the original syslog line. + Examples: - $ syslog-3164 | jc --syslog-3164 -p - [] + $ cat syslog.txt | jc --syslog-bsd -p + [ + { + "priority": 34, + "date": "Oct 11 22:14:15", + "hostname": "mymachine", + "tag": "su", + "content": "'su root' failed for lonvick on /dev/pts/8" + } + ] - $ syslog-3164 | jc --syslog-3164 -p -r - [] + $ cat syslog.txt | jc --syslog-bsd -p -r + [ + { + "priority": "34", + "date": "Oct 11 22:14:15", + "hostname": "mymachine", + "tag": "su", + "content": "'su root' failed for lonvick on /dev/pts/8" + } + ] diff --git a/jc/parsers/syslog_bsd.py b/jc/parsers/syslog_bsd.py index 32ad55a1..2a4406b9 100644 --- a/jc/parsers/syslog_bsd.py +++ b/jc/parsers/syslog_bsd.py @@ -1,14 +1,12 @@ """jc - JSON Convert Syslog RFC 3164 string parser -<> +This parser accepts a single syslog line string or multiple syslog lines +separated by newlines. A warning message to `STDERR` will be printed if an +unparsable line is found. Usage (cli): - $ syslogstring | jc --syslog-bsd - -or - - $ jc syslog-3164 + $ echo '<34>Oct 11 22:14:15 mymachine su: su root...' | jc --syslog-bsd Usage (module): @@ -19,19 +17,41 @@ Schema: [ { - "syslog-3164": string, - "bar": boolean, - "baz": integer + "priority": integer/null, + "date": string, + "hostname": string, + "tag": string, + "content": string, + "unparsable": string, # [0] } ] + [0] this field exists if the syslog line is not parsable. The value + is the original syslog line. + Examples: - $ syslog-3164 | jc --syslog-3164 -p - [] + $ cat syslog.txt | jc --syslog-bsd -p + [ + { + "priority": 34, + "date": "Oct 11 22:14:15", + "hostname": "mymachine", + "tag": "su", + "content": "'su root' failed for lonvick on /dev/pts/8" + } + ] - $ syslog-3164 | jc --syslog-3164 -p -r - [] + $ cat syslog.txt | jc --syslog-bsd -p -r + [ + { + "priority": "34", + "date": "Oct 11 22:14:15", + "hostname": "mymachine", + "tag": "su", + "content": "'su root' failed for lonvick on /dev/pts/8" + } + ] """ import re from typing import List, Dict @@ -61,11 +81,12 @@ def _process(proc_data: List[Dict]) -> List[Dict]: List of Dictionaries. Structured to conform to the schema. """ + int_list = {'priority'} - # process the data here - # rebuild output for added semantic information - # use helper functions in jc.utils for int, float, bool - # conversions and timestamps + for item in proc_data: + for key in item: + if key in int_list: + item[key] = jc.utils.convert_to_int(item[key]) return proc_data @@ -92,14 +113,17 @@ def parse( jc.utils.input_type_check(data) raw_output: List = [] + syslog_dict = {} # inspired by https://gist.github.com/miticojo/b16bb13e78572c2d2fac82d9516d5c32 syslog = re.compile(r''' (?P<\d*>)? - (?P[A-Z][a-z][a-z]\s{1,2}\d{1,2}\s\d{2}?:\d{2}:\d{2})\s - (?P[\w][\w\d\.@-]*)\s - (?P[\w\d\[\]\.@-]+):?\s - (?P.*) + (?P[A-Z][a-z][a-z]\s{1,2}\d{1,2}\s\d{2}?:\d{2}:\d{2})?\s + (?P[\w][\w\d\.:@-]*)?\s + (?P + (?P\w+)? + (?P.*) + ) ''', re.VERBOSE ) @@ -116,10 +140,21 @@ def parse( 'priority': priority, 'date': syslog_match.group('date'), 'hostname': syslog_match.group('host'), + # 'raw_msg': syslog_match.group('msg'), 'tag': syslog_match.group('tag'), - 'message': syslog_match.group('message') + 'content': syslog_match.group('content').lstrip(' :').rstrip() } + else: + syslog_dict = { + 'unparsable': line + } + + if not quiet: + jc.utils.warning_message( + [f'Unparsable line found: {line}'] + ) + if syslog_dict: raw_output.append(syslog_dict)