diff --git a/gradle.properties b/gradle.properties index 93507c6..b7702aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ id = syslogd group = biz.nellemann.syslogd -version = 1.0.2 +version = 1.0.3 diff --git a/src/main/java/biz/nellemann/syslogd/Facility.java b/src/main/java/biz/nellemann/syslogd/Facility.java index 4ffa473..9b4107b 100644 --- a/src/main/java/biz/nellemann/syslogd/Facility.java +++ b/src/main/java/biz/nellemann/syslogd/Facility.java @@ -73,7 +73,7 @@ public enum Facility { } private Integer facilityNumber; - private Facility(int facilityNumber) { + Facility(int facilityNumber) { this.facilityNumber = facilityNumber; } diff --git a/src/main/java/biz/nellemann/syslogd/LogListener.java b/src/main/java/biz/nellemann/syslogd/LogListener.java index 801dec8..a42b529 100644 --- a/src/main/java/biz/nellemann/syslogd/LogListener.java +++ b/src/main/java/biz/nellemann/syslogd/LogListener.java @@ -15,8 +15,6 @@ */ package biz.nellemann.syslogd; -import java.io.IOException; - public interface LogListener { void onLogEvent(LogEvent event); } diff --git a/src/main/java/biz/nellemann/syslogd/Severity.java b/src/main/java/biz/nellemann/syslogd/Severity.java index bbe56d1..ffb9a5d 100644 --- a/src/main/java/biz/nellemann/syslogd/Severity.java +++ b/src/main/java/biz/nellemann/syslogd/Severity.java @@ -41,7 +41,7 @@ public enum Severity { } private Integer severityNumber; - private Severity(int severityNumber) { + Severity(int severityNumber) { this.severityNumber = severityNumber; } diff --git a/src/main/java/biz/nellemann/syslogd/SyslogMessage.java b/src/main/java/biz/nellemann/syslogd/SyslogMessage.java index f703955..b67de08 100644 --- a/src/main/java/biz/nellemann/syslogd/SyslogMessage.java +++ b/src/main/java/biz/nellemann/syslogd/SyslogMessage.java @@ -19,32 +19,32 @@ import java.time.Instant; public class SyslogMessage { - Facility facility; - Severity severity; + protected Facility facility; + protected Severity severity; // The VERSION field denotes the version of the syslog protocol specification. - Integer version; + protected Integer version; // The TIMESTAMP field is a formalized timestamp derived from [RFC3339]. - Instant timestamp; + protected Instant timestamp; // The HOSTNAME field identifies the machine that originally sent the syslog message. - String hostname; + protected String hostname; // The APP-NAME field SHOULD identify the device or application that originated the message. - String application; + protected String application; // The PROCID field is often used to provide the process name or process ID associated with a syslog system. - String processId; + protected String processId; // The MSGID SHOULD identify the type of message. - String messageId; + protected String messageId; // STRUCTURED-DATA provides a mechanism to express information in a well defined, easily parseable and interpretable data format. - String structuredData; + protected String structuredData; // The MSG part contains a free-form message that provides information about the event. - final private String message; + protected final String message; SyslogMessage(final String message) { this.message = message; @@ -54,11 +54,11 @@ public class SyslogMessage { public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(timestamp.toString() + " "); - sb.append("[" + facility + "." + severity + "]"); - sb.append("\t" + hostname); - sb.append("\t" + application); - sb.append("\t" + message); + sb.append(timestamp.toString()); + sb.append(String.format(" [%6.6s.%-6.6s] ", facility, severity)); + sb.append(String.format(" %-24.24s ", hostname)); + sb.append(String.format(" %-32.43s ", application)); + sb.append(message); return sb.toString(); } @@ -66,7 +66,7 @@ public class SyslogMessage { public String toAnsiString() { StringBuilder sb = new StringBuilder(); - sb.append(timestamp.toString() + " "); + sb.append(timestamp.toString()); if(severity.toNumber() < 3 ) { sb.append(Ansi.RED); @@ -75,11 +75,11 @@ public class SyslogMessage { } else { sb.append(Ansi.GREEN); } - sb.append("[" + facility + "." + severity + "]"); sb.append(Ansi.RESET); - sb.append(Ansi.BLUE); sb.append("\t" + hostname); sb.append(Ansi.RESET); - sb.append(Ansi.CYAN); sb.append("\t" + application); sb.append(Ansi.RESET); - sb.append("\t" + message); + sb.append(String.format(" [%6.6s.%-6.6s] ", facility, severity)).append(Ansi.RESET); + sb.append(Ansi.BLUE).append(String.format(" %-24.24s ", hostname)).append(Ansi.RESET); + sb.append(Ansi.CYAN).append(String.format(" %-32.32s ", application)).append(Ansi.RESET); + sb.append(message); return sb.toString(); } diff --git a/src/main/java/biz/nellemann/syslogd/SyslogParser.java b/src/main/java/biz/nellemann/syslogd/SyslogParser.java index 372b516..ef02b2a 100644 --- a/src/main/java/biz/nellemann/syslogd/SyslogParser.java +++ b/src/main/java/biz/nellemann/syslogd/SyslogParser.java @@ -24,17 +24,18 @@ import java.time.format.DateTimeParseException; import java.util.regex.Matcher; import java.util.regex.Pattern; -/* - https://tools.ietf.org/html/rfc5424 - https://tools.ietf.org/html/rfc3164 - */ - - public class SyslogParser { private final static Logger log = LoggerFactory.getLogger(SyslogParser.class); + /** + * Parses [rfc3164](https://tools.ietf.org/html/rfc3164) syslog messages. + * + * @param input + * @return + * @throws NumberFormatException + */ public static SyslogMessage parseRfc3164(final String input) throws NumberFormatException { 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); @@ -50,7 +51,7 @@ public class SyslogParser { String date = matcher.group(2); String hostname = matcher.group(3); String application = matcher.group(4); - String message = matcher.group(5); + String msg = matcher.group(5); if(hostname.endsWith(":")) { String[] tmp = hostname.split(" "); @@ -61,7 +62,7 @@ public class SyslogParser { Integer facility = getFacility(pri); Integer severity = getSeverity(pri); - SyslogMessage syslogMessage = new SyslogMessage(message.trim()); + SyslogMessage syslogMessage = new SyslogMessage(msg.trim()); syslogMessage.facility = Facility.getByNumber(facility); syslogMessage.severity = Severity.getByNumber(severity); syslogMessage.timestamp = parseRfc3164Timestamp(date); @@ -72,6 +73,13 @@ public class SyslogParser { } + /** + * Parses [rfc5424](https://tools.ietf.org/html/rfc5424) syslog messages. + * + * @param input + * @return + * @throws NumberFormatException + */ public static SyslogMessage parseRfc5424(final String input) throws NumberFormatException { Pattern pattern = Pattern.compile("^<(\\d{1,3})>(\\d+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\[.*\\])\\s+(\\S+)", Pattern.CASE_INSENSITIVE); @@ -83,15 +91,15 @@ public class SyslogParser { return null; } - final String pri = matcher.group(1); - final String ver = matcher.group(2); - final String date = matcher.group(3); - final String host = matcher.group(4); - final String app = matcher.group(5); - final String procId = matcher.group(6); - final String msgId = matcher.group(7); - final String data = matcher.group(8); - final String msg = matcher.group(9); + 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); Integer facility = getFacility(pri); Integer severity = getSeverity(pri); @@ -114,6 +122,12 @@ public class SyslogParser { } + /** + * Parse rfc3164 TIMESTAMP field into Instant. + * + * @param dateString + * @return + */ static protected Instant parseRfc3164Timestamp(String dateString) { // We need to add year to parse date correctly @@ -132,6 +146,12 @@ public class SyslogParser { } + /** + * Parse rfc5424 TIMESTAMP field into Instant. + * + * @param dateString + * @return + */ static protected Instant parseRfc5424Timestamp(String dateString) { Instant instant = null; @@ -145,27 +165,35 @@ public class SyslogParser { return instant; } - /* - The priority value is calculated using the formula (Priority = Facility * 8 + Level). - For example, a kernel message (Facility=0) with a Severity of Emergency (Severity=0) would have a Priority value of 0. - Also, a "local use 4" message (Facility=20) with a Severity of Notice (Severity=5) would have a Priority value of 165. + + /** + * Converts syslog PRI field into Facility. + * + * @param pri + * @return */ + static protected int getFacility(String pri) { - static protected int getFacility(String prio) { - - int priority = Integer.parseInt(prio); + int priority = Integer.parseInt(pri); int facility = priority >> 3; - log.debug("getFacility() - " + prio + " => " + facility); + log.debug("getFacility() - " + pri + " => " + facility); return facility; } - static protected int getSeverity(String prio) { - int priority = Integer.parseInt(prio); + /** + * Converts syslog PRI field into Severity. + * + * @param pri + * @return + */ + static protected int getSeverity(String pri) { + + int priority = Integer.parseInt(pri); int severity = priority & 0x07; - log.debug("getSeverity() - " + prio + " => " + severity); + log.debug("getSeverity() - " + pri + " => " + severity); return severity; } diff --git a/src/test/groovy/biz/nellemann/syslogd/SyslogParserTest.groovy b/src/test/groovy/biz/nellemann/syslogd/SyslogParserTest.groovy index 403337e..d738076 100644 --- a/src/test/groovy/biz/nellemann/syslogd/SyslogParserTest.groovy +++ b/src/test/groovy/biz/nellemann/syslogd/SyslogParserTest.groovy @@ -36,7 +36,6 @@ class SyslogParserTest extends Specification { setup: def input = "<13>Sep 23 08:53:28 xps13 mark: adfdfdf3432434" - //def input = "<13>Sep 3 08:53:28 xps13 mark: adfdfdf3432434" when: SyslogMessage msg = SyslogParser.parseRfc3164(input)