Correct parsing of PRI to facility and severity + ansi colors in output.
This commit is contained in:
parent
7a019c5c18
commit
4106453a68
87
src/main/java/biz/nellemann/syslogd/Color.java
Normal file
87
src/main/java/biz/nellemann/syslogd/Color.java
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
|
public enum Color {
|
||||||
|
//Color end string, color reset
|
||||||
|
RESET("\033[0m"),
|
||||||
|
|
||||||
|
// Regular Colors. Normal color, no bold, background color etc.
|
||||||
|
BLACK("\033[0;30m"), // BLACK
|
||||||
|
RED("\033[0;31m"), // RED
|
||||||
|
GREEN("\033[0;32m"), // GREEN
|
||||||
|
YELLOW("\033[0;33m"), // YELLOW
|
||||||
|
BLUE("\033[0;34m"), // BLUE
|
||||||
|
MAGENTA("\033[0;35m"), // MAGENTA
|
||||||
|
CYAN("\033[0;36m"), // CYAN
|
||||||
|
WHITE("\033[0;37m"), // WHITE
|
||||||
|
|
||||||
|
// Bold
|
||||||
|
BLACK_BOLD("\033[1;30m"), // BLACK
|
||||||
|
RED_BOLD("\033[1;31m"), // RED
|
||||||
|
GREEN_BOLD("\033[1;32m"), // GREEN
|
||||||
|
YELLOW_BOLD("\033[1;33m"), // YELLOW
|
||||||
|
BLUE_BOLD("\033[1;34m"), // BLUE
|
||||||
|
MAGENTA_BOLD("\033[1;35m"), // MAGENTA
|
||||||
|
CYAN_BOLD("\033[1;36m"), // CYAN
|
||||||
|
WHITE_BOLD("\033[1;37m"), // WHITE
|
||||||
|
|
||||||
|
// Underline
|
||||||
|
BLACK_UNDERLINED("\033[4;30m"), // BLACK
|
||||||
|
RED_UNDERLINED("\033[4;31m"), // RED
|
||||||
|
GREEN_UNDERLINED("\033[4;32m"), // GREEN
|
||||||
|
YELLOW_UNDERLINED("\033[4;33m"), // YELLOW
|
||||||
|
BLUE_UNDERLINED("\033[4;34m"), // BLUE
|
||||||
|
MAGENTA_UNDERLINED("\033[4;35m"), // MAGENTA
|
||||||
|
CYAN_UNDERLINED("\033[4;36m"), // CYAN
|
||||||
|
WHITE_UNDERLINED("\033[4;37m"), // WHITE
|
||||||
|
|
||||||
|
// Background
|
||||||
|
BLACK_BACKGROUND("\033[40m"), // BLACK
|
||||||
|
RED_BACKGROUND("\033[41m"), // RED
|
||||||
|
GREEN_BACKGROUND("\033[42m"), // GREEN
|
||||||
|
YELLOW_BACKGROUND("\033[43m"), // YELLOW
|
||||||
|
BLUE_BACKGROUND("\033[44m"), // BLUE
|
||||||
|
MAGENTA_BACKGROUND("\033[45m"), // MAGENTA
|
||||||
|
CYAN_BACKGROUND("\033[46m"), // CYAN
|
||||||
|
WHITE_BACKGROUND("\033[47m"), // WHITE
|
||||||
|
|
||||||
|
// High Intensity
|
||||||
|
BLACK_BRIGHT("\033[0;90m"), // BLACK
|
||||||
|
RED_BRIGHT("\033[0;91m"), // RED
|
||||||
|
GREEN_BRIGHT("\033[0;92m"), // GREEN
|
||||||
|
YELLOW_BRIGHT("\033[0;93m"), // YELLOW
|
||||||
|
BLUE_BRIGHT("\033[0;94m"), // BLUE
|
||||||
|
MAGENTA_BRIGHT("\033[0;95m"), // MAGENTA
|
||||||
|
CYAN_BRIGHT("\033[0;96m"), // CYAN
|
||||||
|
WHITE_BRIGHT("\033[0;97m"), // WHITE
|
||||||
|
|
||||||
|
// Bold High Intensity
|
||||||
|
BLACK_BOLD_BRIGHT("\033[1;90m"), // BLACK
|
||||||
|
RED_BOLD_BRIGHT("\033[1;91m"), // RED
|
||||||
|
GREEN_BOLD_BRIGHT("\033[1;92m"), // GREEN
|
||||||
|
YELLOW_BOLD_BRIGHT("\033[1;93m"), // YELLOW
|
||||||
|
BLUE_BOLD_BRIGHT("\033[1;94m"), // BLUE
|
||||||
|
MAGENTA_BOLD_BRIGHT("\033[1;95m"), // MAGENTA
|
||||||
|
CYAN_BOLD_BRIGHT("\033[1;96m"), // CYAN
|
||||||
|
WHITE_BOLD_BRIGHT("\033[1;97m"), // WHITE
|
||||||
|
|
||||||
|
// High Intensity backgrounds
|
||||||
|
BLACK_BACKGROUND_BRIGHT("\033[0;100m"), // BLACK
|
||||||
|
RED_BACKGROUND_BRIGHT("\033[0;101m"), // RED
|
||||||
|
GREEN_BACKGROUND_BRIGHT("\033[0;102m"), // GREEN
|
||||||
|
YELLOW_BACKGROUND_BRIGHT("\033[0;103m"), // YELLOW
|
||||||
|
BLUE_BACKGROUND_BRIGHT("\033[0;104m"), // BLUE
|
||||||
|
MAGENTA_BACKGROUND_BRIGHT("\033[0;105m"), // MAGENTA
|
||||||
|
CYAN_BACKGROUND_BRIGHT("\033[0;106m"), // CYAN
|
||||||
|
WHITE_BACKGROUND_BRIGHT("\033[0;107m"); // WHITE
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
Color(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
80
src/main/java/biz/nellemann/syslogd/Facility.java
Normal file
80
src/main/java/biz/nellemann/syslogd/Facility.java
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 kernel messages
|
||||||
|
1 user-level messages
|
||||||
|
2 mail system
|
||||||
|
3 system daemons
|
||||||
|
4 security/authorization messages
|
||||||
|
5 messages generated internally by syslogd
|
||||||
|
6 line printer subsystem
|
||||||
|
7 network news subsystem
|
||||||
|
8 UUCP subsystem
|
||||||
|
9 clock daemon
|
||||||
|
10 security/authorization messages
|
||||||
|
11 FTP daemon
|
||||||
|
12 NTP subsystem
|
||||||
|
13 log audit
|
||||||
|
14 log alert
|
||||||
|
15 clock daemon (note 2)
|
||||||
|
16 local use 0 (local0)
|
||||||
|
17 local use 1 (local1)
|
||||||
|
18 local use 2 (local2)
|
||||||
|
19 local use 3 (local3)
|
||||||
|
20 local use 4 (local4)
|
||||||
|
21 local use 5 (local5)
|
||||||
|
22 local use 6 (local6)
|
||||||
|
23 local use 7 (local7)
|
||||||
|
*/
|
||||||
|
public enum Facility {
|
||||||
|
|
||||||
|
KERNEL(0),
|
||||||
|
USER(1),
|
||||||
|
MAIL(2),
|
||||||
|
DAEMON(3),
|
||||||
|
AUTH(4),
|
||||||
|
SYSLOG(5),
|
||||||
|
PRINT(6),
|
||||||
|
NEWS(7),
|
||||||
|
UUCP(8),
|
||||||
|
CRON(9),
|
||||||
|
AUTHPRIV(10),
|
||||||
|
FTP(11),
|
||||||
|
NTP(12),
|
||||||
|
AUDIT(13),
|
||||||
|
ALERT(14),
|
||||||
|
TIME(15),
|
||||||
|
LOCAL0(16),
|
||||||
|
LOCAL1(17),
|
||||||
|
LOCAL2(18),
|
||||||
|
LOCAL3(19),
|
||||||
|
LOCAL4(20),
|
||||||
|
LOCAL5(21),
|
||||||
|
LOCAL6(22),
|
||||||
|
LOCAL7(23);
|
||||||
|
|
||||||
|
// Cache lookups
|
||||||
|
private static final Map<Integer, Facility> BY_NUMBER = new HashMap<>();
|
||||||
|
static {
|
||||||
|
for (Facility f: values()) {
|
||||||
|
BY_NUMBER.put(f.facilityNumber, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Facility getByNumber(Integer number) {
|
||||||
|
return BY_NUMBER.get(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer toNumber() {
|
||||||
|
return this.facilityNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer facilityNumber;
|
||||||
|
private Facility(int facilityNumber) {
|
||||||
|
this.facilityNumber = facilityNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
48
src/main/java/biz/nellemann/syslogd/Severity.java
Normal file
48
src/main/java/biz/nellemann/syslogd/Severity.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 Emergency: system is unusable
|
||||||
|
1 Alert: action must be taken immediately
|
||||||
|
2 Critical: critical conditions
|
||||||
|
3 Error: error conditions
|
||||||
|
4 Warning: warning conditions
|
||||||
|
5 Notice: normal but significant condition
|
||||||
|
6 Informational: informational messages
|
||||||
|
7 Debug: debug-level messages
|
||||||
|
*/
|
||||||
|
public enum Severity {
|
||||||
|
|
||||||
|
EMERG(0),
|
||||||
|
ALERT(1),
|
||||||
|
CRIT(2),
|
||||||
|
ERROR(3),
|
||||||
|
WARN(4),
|
||||||
|
NOTICE(5),
|
||||||
|
INFO(6),
|
||||||
|
DEBUG(7);
|
||||||
|
|
||||||
|
// Cache lookups
|
||||||
|
private static final Map<Integer, Severity> BY_NUMBER = new HashMap<>();
|
||||||
|
static {
|
||||||
|
for (Severity s: values()) {
|
||||||
|
BY_NUMBER.put(s.severityNumber, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Severity getByNumber(Integer number) {
|
||||||
|
return BY_NUMBER.get(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer toNumber() {
|
||||||
|
return this.severityNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer severityNumber;
|
||||||
|
private Severity(int severityNumber) {
|
||||||
|
this.severityNumber = severityNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,46 +19,8 @@ import java.time.Instant;
|
||||||
|
|
||||||
public class SyslogMessage {
|
public class SyslogMessage {
|
||||||
|
|
||||||
/*
|
Facility facility;
|
||||||
0 kernel messages
|
Severity severity;
|
||||||
1 user-level messages
|
|
||||||
2 mail system
|
|
||||||
3 system daemons
|
|
||||||
4 security/authorization messages
|
|
||||||
5 messages generated internally by syslogd
|
|
||||||
6 line printer subsystem
|
|
||||||
7 network news subsystem
|
|
||||||
8 UUCP subsystem
|
|
||||||
9 clock daemon
|
|
||||||
10 security/authorization messages
|
|
||||||
11 FTP daemon
|
|
||||||
12 NTP subsystem
|
|
||||||
13 log audit
|
|
||||||
14 log alert
|
|
||||||
15 clock daemon (note 2)
|
|
||||||
16 local use 0 (local0)
|
|
||||||
17 local use 1 (local1)
|
|
||||||
18 local use 2 (local2)
|
|
||||||
19 local use 3 (local3)
|
|
||||||
20 local use 4 (local4)
|
|
||||||
21 local use 5 (local5)
|
|
||||||
22 local use 6 (local6)
|
|
||||||
23 local use 7 (local7)
|
|
||||||
*/
|
|
||||||
protected Integer facility;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
0 Emergency: system is unusable
|
|
||||||
1 Alert: action must be taken immediately
|
|
||||||
2 Critical: critical conditions
|
|
||||||
3 Error: error conditions
|
|
||||||
4 Warning: warning conditions
|
|
||||||
5 Notice: normal but significant condition
|
|
||||||
6 Informational: informational messages
|
|
||||||
7 Debug: debug-level messages
|
|
||||||
*/
|
|
||||||
Integer severity;
|
|
||||||
|
|
||||||
// The VERSION field denotes the version of the syslog protocol specification.
|
// The VERSION field denotes the version of the syslog protocol specification.
|
||||||
Integer version;
|
Integer version;
|
||||||
|
@ -86,7 +48,26 @@ public class SyslogMessage {
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("%s %s %s: %s", timestamp.toString(), hostname, application, message);
|
//return String.format("%s %s %s: %s", timestamp.toString(), hostname, application, message);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append(Color.WHITE); sb.append(timestamp.toString() + " "); sb.append(Color.RESET);
|
||||||
|
|
||||||
|
if(severity.toNumber() < 3 ) {
|
||||||
|
sb.append(Color.RED);
|
||||||
|
} else if(severity.toNumber() < 5) {
|
||||||
|
sb.append(Color.YELLOW);
|
||||||
|
} else {
|
||||||
|
sb.append(Color.GREEN);
|
||||||
|
}
|
||||||
|
sb.append("[" + facility + "." + severity + "]"); sb.append(Color.RESET);
|
||||||
|
|
||||||
|
sb.append(Color.BLUE); sb.append("\t" + hostname); sb.append(Color.RESET);
|
||||||
|
sb.append(Color.CYAN); sb.append("\t" + application); sb.append(Color.RESET);
|
||||||
|
sb.append("\t" + message);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ public class SyslogParser {
|
||||||
|
|
||||||
public static SyslogMessage parseRfc3164(String input) throws NumberFormatException {
|
public static SyslogMessage parseRfc3164(String input) throws NumberFormatException {
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile("^<(\\d{1,3})>(\\D{3} \\d{2} \\d{2}:\\d{2}:\\d{2})\\s+(\\S+)\\s+(\\S+): (.*)", Pattern.CASE_INSENSITIVE);
|
Pattern pattern = Pattern.compile("^<(\\d{1,3})>(\\D{3} \\d{2} \\d{2}:\\d{2}:\\d{2})\\s+(?:Message forwarded from )?([^\\s:]+):?\\s+(\\S+): (.*)", Pattern.CASE_INSENSITIVE);
|
||||||
Matcher matcher = pattern.matcher(input);
|
Matcher matcher = pattern.matcher(input);
|
||||||
boolean matchFound = matcher.find();
|
boolean matchFound = matcher.find();
|
||||||
if(!matchFound) {
|
if(!matchFound) {
|
||||||
|
@ -58,14 +57,14 @@ public class SyslogParser {
|
||||||
log.debug("APP: " + application);
|
log.debug("APP: " + application);
|
||||||
log.debug("MSG: " + message);
|
log.debug("MSG: " + message);
|
||||||
|
|
||||||
Integer facility = Integer.parseInt(pri.substring(0, pri.length()-1));
|
Integer facility = getFacility(pri);
|
||||||
Integer severity = Integer.parseInt(pri.substring(pri.length()-1));
|
Integer severity = getSeverity(pri);
|
||||||
log.debug("facility: " + facility);
|
log.debug("facility: " + facility);
|
||||||
log.debug("severity: " + severity);
|
log.debug("severity: " + severity);
|
||||||
|
|
||||||
SyslogMessage syslogMessage = new SyslogMessage();
|
SyslogMessage syslogMessage = new SyslogMessage();
|
||||||
syslogMessage.facility = facility;
|
syslogMessage.facility = Facility.getByNumber(facility);
|
||||||
syslogMessage.severity = severity;
|
syslogMessage.severity = Severity.getByNumber(severity);
|
||||||
syslogMessage.timestamp = parseRfc3164Timestamp(date);
|
syslogMessage.timestamp = parseRfc3164Timestamp(date);
|
||||||
syslogMessage.hostname = hostname;
|
syslogMessage.hostname = hostname;
|
||||||
syslogMessage.application = application;
|
syslogMessage.application = application;
|
||||||
|
@ -105,14 +104,14 @@ public class SyslogParser {
|
||||||
log.debug("DATA: " + data);
|
log.debug("DATA: " + data);
|
||||||
log.debug("MSG: " + msg);
|
log.debug("MSG: " + msg);
|
||||||
|
|
||||||
Integer facility = Integer.parseInt(pri.substring(0, pri.length()-1));
|
Integer facility = getFacility(pri);
|
||||||
Integer severity = Integer.parseInt(pri.substring(pri.length()-1));
|
Integer severity = getSeverity(pri);
|
||||||
log.debug("facility: " + facility);
|
log.debug("facility: " + facility);
|
||||||
log.debug("severity: " + severity);
|
log.debug("severity: " + severity);
|
||||||
|
|
||||||
SyslogMessage syslogMessage = new SyslogMessage();
|
SyslogMessage syslogMessage = new SyslogMessage();
|
||||||
syslogMessage.facility = facility;
|
syslogMessage.facility = Facility.getByNumber(facility);
|
||||||
syslogMessage.severity = severity;
|
syslogMessage.severity = Severity.getByNumber(severity);
|
||||||
syslogMessage.version = Integer.parseInt(ver);
|
syslogMessage.version = Integer.parseInt(ver);
|
||||||
syslogMessage.timestamp = parseRfc5424Timestamp(date);
|
syslogMessage.timestamp = parseRfc5424Timestamp(date);
|
||||||
syslogMessage.hostname = host;
|
syslogMessage.hostname = host;
|
||||||
|
@ -160,4 +159,28 @@ public class SyslogParser {
|
||||||
return instant;
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static protected int getFacility(String prio) {
|
||||||
|
|
||||||
|
int priority = Integer.parseInt(prio);
|
||||||
|
int facility = priority >> 3;
|
||||||
|
|
||||||
|
log.debug("getFacility() - " + prio + " => " + facility);
|
||||||
|
return facility;
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected int getSeverity(String prio) {
|
||||||
|
|
||||||
|
int priority = Integer.parseInt(prio);
|
||||||
|
int severity = priority & 0x07;
|
||||||
|
|
||||||
|
log.debug("getSeverity() - " + prio + " => " + severity);
|
||||||
|
return severity;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,47 @@ import java.time.OffsetDateTime;
|
||||||
|
|
||||||
class SyslogParserTest extends Specification {
|
class SyslogParserTest extends Specification {
|
||||||
|
|
||||||
|
void "test rfc5424 message"() {
|
||||||
|
|
||||||
|
setup:
|
||||||
|
def input = "<13>1 2020-09-23T08:57:30.950699+02:00 xps13 mark - - [timeQuality tzKnown=\"1\" isSynced=\"1\" syncAccuracy=\"125500\"] adfdfdf3432434565656"
|
||||||
|
|
||||||
|
when:
|
||||||
|
SyslogMessage msg = SyslogParser.parseRfc5424(input)
|
||||||
|
|
||||||
|
then:
|
||||||
|
msg.message == "adfdfdf3432434565656"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void "test rfc3164 aix/vios message"() {
|
||||||
|
|
||||||
|
setup:
|
||||||
|
def input = "<13>Sep 23 08:37:09 Message forwarded from p924vio1: padmin: test"
|
||||||
|
|
||||||
|
when:
|
||||||
|
SyslogMessage msg = SyslogParser.parseRfc3164(input)
|
||||||
|
|
||||||
|
then:
|
||||||
|
msg.message == "test"
|
||||||
|
msg.hostname == "p924vio1"
|
||||||
|
msg.application == "padmin"
|
||||||
|
}
|
||||||
|
|
||||||
|
void "test rfc3164 normal message"() {
|
||||||
|
|
||||||
|
setup:
|
||||||
|
def input = "<13>Sep 23 08:53:28 xps13 mark: adfdfdf3432434"
|
||||||
|
|
||||||
|
when:
|
||||||
|
SyslogMessage msg = SyslogParser.parseRfc3164(input)
|
||||||
|
|
||||||
|
then:
|
||||||
|
msg.message == "adfdfdf3432434"
|
||||||
|
msg.hostname == "xps13"
|
||||||
|
msg.application == "mark"
|
||||||
|
}
|
||||||
|
|
||||||
void "test parseRfc3164Timestamp"() {
|
void "test parseRfc3164Timestamp"() {
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
|
|
Loading…
Reference in a new issue