2020-09-22 18:45:16 +00:00
/ *
Copyright 2020 mark . nellemann @gmail.com
Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an " AS IS " BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
2020-09-22 18:33:22 +00:00
package biz.nellemann.syslogd ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import java.time.* ;
import java.time.format.DateTimeFormatter ;
import java.time.format.DateTimeParseException ;
import java.util.regex.Matcher ;
import java.util.regex.Pattern ;
public class SyslogParser {
private final static Logger log = LoggerFactory . getLogger ( SyslogParser . class ) ;
2020-10-07 09:53:16 +00:00
/ * *
* Parses [ rfc3164 ] ( https : //tools.ietf.org/html/rfc3164) syslog messages.
*
* @param input
* @return
* @throws NumberFormatException
* /
2020-10-05 08:40:42 +00:00
public static SyslogMessage parseRfc3164 ( final String input ) throws NumberFormatException {
2020-09-22 18:33:22 +00:00
2020-10-06 03:33:08 +00:00
Pattern pattern = Pattern . compile ( " ^<( \\ d{1,3})>( \\ D{3} \\ s+ \\ d{1,2} \\ d{2}: \\ d{2}: \\ d{2}) \\ s+(Message forwarded from \\ S+:| \\ S+) \\ s+([^ \\ s:]+):? \\ s+(.*) " , Pattern . CASE_INSENSITIVE ) ;
2020-09-22 18:33:22 +00:00
Matcher matcher = pattern . matcher ( input ) ;
boolean matchFound = matcher . find ( ) ;
if ( ! matchFound ) {
2020-10-06 03:10:19 +00:00
//log.warn("parseRfc3164() - Match not found in: ");
System . err . println ( " ! " + input ) ;
2020-09-22 18:33:22 +00:00
return null ;
}
2020-10-06 03:10:19 +00:00
String pri = matcher . group ( 1 ) ;
String date = matcher . group ( 2 ) ;
String hostname = matcher . group ( 3 ) ;
String application = matcher . group ( 4 ) ;
2020-10-07 09:53:16 +00:00
String msg = matcher . group ( 5 ) ;
2020-09-22 18:33:22 +00:00
2020-10-06 03:10:19 +00:00
if ( hostname . endsWith ( " : " ) ) {
String [ ] tmp = hostname . split ( " " ) ;
hostname = tmp [ tmp . length - 1 ] ;
hostname = hostname . substring ( 0 , hostname . length ( ) - 1 ) ;
}
2020-09-22 18:33:22 +00:00
2020-09-23 08:52:52 +00:00
Integer facility = getFacility ( pri ) ;
Integer severity = getSeverity ( pri ) ;
2020-09-22 18:33:22 +00:00
2020-10-07 09:53:16 +00:00
SyslogMessage syslogMessage = new SyslogMessage ( msg . trim ( ) ) ;
2020-09-23 08:52:52 +00:00
syslogMessage . facility = Facility . getByNumber ( facility ) ;
syslogMessage . severity = Severity . getByNumber ( severity ) ;
2020-09-22 18:33:22 +00:00
syslogMessage . timestamp = parseRfc3164Timestamp ( date ) ;
syslogMessage . hostname = hostname ;
syslogMessage . application = application ;
return syslogMessage ;
}
2020-10-07 09:53:16 +00:00
/ * *
* Parses [ rfc5424 ] ( https : //tools.ietf.org/html/rfc5424) syslog messages.
*
* @param input
* @return
* @throws NumberFormatException
* /
2020-10-05 08:40:42 +00:00
public static SyslogMessage parseRfc5424 ( final String input ) throws NumberFormatException {
2020-09-22 18:33:22 +00:00
Pattern pattern = Pattern . compile ( " ^<( \\ d{1,3})>( \\ d+) \\ s+( \\ S+) \\ s+( \\ S+) \\ s+( \\ S+) \\ s+( \\ S+) \\ s+( \\ S+) \\ s+( \\ [.* \\ ]) \\ s+( \\ S+) " , Pattern . CASE_INSENSITIVE ) ;
Matcher matcher = pattern . matcher ( input ) ;
boolean matchFound = matcher . find ( ) ;
if ( ! matchFound ) {
2020-10-06 03:10:19 +00:00
//log.warn("parseRfc5424() - Match not found in: " + input);
System . err . println ( " ! " + input ) ;
2020-09-22 18:33:22 +00:00
return null ;
}
2020-10-07 09:53:16 +00:00
String pri = matcher . group ( 1 ) ;
String ver = matcher . group ( 2 ) ;
String date = matcher . group ( 3 ) ;
String host = matcher . group ( 4 ) ;
String app = matcher . group ( 5 ) ;
String procId = matcher . group ( 6 ) ;
String msgId = matcher . group ( 7 ) ;
String data = matcher . group ( 8 ) ;
String msg = matcher . group ( 9 ) ;
2020-09-22 18:33:22 +00:00
2020-09-23 08:52:52 +00:00
Integer facility = getFacility ( pri ) ;
Integer severity = getSeverity ( pri ) ;
2020-09-22 18:33:22 +00:00
2020-10-05 15:59:31 +00:00
SyslogMessage syslogMessage = new SyslogMessage ( msg . trim ( ) ) ;
2020-09-23 08:52:52 +00:00
syslogMessage . facility = Facility . getByNumber ( facility ) ;
syslogMessage . severity = Severity . getByNumber ( severity ) ;
2020-09-22 18:33:22 +00:00
syslogMessage . version = Integer . parseInt ( ver ) ;
syslogMessage . timestamp = parseRfc5424Timestamp ( date ) ;
syslogMessage . hostname = host ;
if ( app ! = null & & ! app . equals ( " - " ) )
syslogMessage . application = app ;
if ( procId ! = null & & ! procId . equals ( " - " ) )
syslogMessage . processId = procId ;
if ( msgId ! = null & & ! msgId . equals ( " - " ) )
syslogMessage . messageId = msgId ;
syslogMessage . structuredData = data ;
return syslogMessage ;
}
2020-10-07 09:53:16 +00:00
/ * *
* Parse rfc3164 TIMESTAMP field into Instant .
*
* @param dateString
* @return
* /
2020-09-22 18:33:22 +00:00
static protected Instant parseRfc3164Timestamp ( String dateString ) {
// We need to add year to parse date correctly
2020-09-23 05:01:55 +00:00
OffsetDateTime odt = OffsetDateTime . now ( ) ;
2020-09-22 18:33:22 +00:00
// Date: Mmm dd hh:mm:ss
Instant instant = null ;
try {
2020-10-05 15:59:31 +00:00
DateTimeFormatter dateTimeFormatter = DateTimeFormatter . ofPattern ( " yyyy MMM [ ]d HH:mm:ss " ) . withZone ( ZoneOffset . UTC ) ;
2020-09-23 05:01:55 +00:00
instant = Instant . from ( dateTimeFormatter . parse ( odt . getYear ( ) + " " + dateString ) ) ;
2020-09-22 18:33:22 +00:00
} catch ( DateTimeParseException e ) {
log . error ( " parseDate() " , e ) ;
}
return instant ;
}
2020-10-07 09:53:16 +00:00
/ * *
* Parse rfc5424 TIMESTAMP field into Instant .
*
* @param dateString
* @return
* /
2020-09-22 18:33:22 +00:00
static protected Instant parseRfc5424Timestamp ( String dateString ) {
Instant instant = null ;
try {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter . ISO_OFFSET_DATE_TIME ;
instant = Instant . from ( dateTimeFormatter . parse ( dateString ) ) ;
} catch ( DateTimeParseException e ) {
log . error ( " parseTimestamp() " , e ) ;
}
return instant ;
}
2020-09-23 08:52:52 +00:00
2020-10-07 09:53:16 +00:00
/ * *
* Converts syslog PRI field into Facility .
*
* @param pri
* @return
* /
static protected int getFacility ( String pri ) {
2020-09-23 08:52:52 +00:00
2020-10-07 09:53:16 +00:00
int priority = Integer . parseInt ( pri ) ;
2020-09-23 08:52:52 +00:00
int facility = priority > > 3 ;
2021-01-26 20:44:23 +00:00
//log.debug("getFacility() - " + pri + " => " + facility);
2020-09-23 08:52:52 +00:00
return facility ;
}
2020-10-07 09:53:16 +00:00
/ * *
* Converts syslog PRI field into Severity .
*
* @param pri
* @return
* /
static protected int getSeverity ( String pri ) {
int priority = Integer . parseInt ( pri ) ;
2020-09-23 08:52:52 +00:00
int severity = priority & 0x07 ;
2021-01-26 20:44:23 +00:00
//log.debug("getSeverity() - " + pri + " => " + severity);
2020-09-23 08:52:52 +00:00
return severity ;
}
2021-01-26 14:24:23 +00:00
2020-09-22 18:33:22 +00:00
}