Enable forwarding of received syslog messaged.
This commit is contained in:
parent
0e73aa8321
commit
f2b64383cc
|
@ -4,7 +4,7 @@ plugins {
|
||||||
id 'application'
|
id 'application'
|
||||||
id "com.github.johnrengelman.shadow" version "6.1.0"
|
id "com.github.johnrengelman.shadow" version "6.1.0"
|
||||||
id "net.nemerosa.versioning" version "2.14.0"
|
id "net.nemerosa.versioning" version "2.14.0"
|
||||||
id "nebula.ospackage" version "8.4.1"
|
id "nebula.ospackage" version "8.4.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -12,10 +12,10 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
annotationProcessor 'info.picocli:picocli-codegen:4.6.0'
|
annotationProcessor 'info.picocli:picocli-codegen:4.6.1'
|
||||||
implementation 'info.picocli:picocli:4.6.0'
|
implementation 'info.picocli:picocli:4.6.1'
|
||||||
implementation 'org.slf4j:slf4j-api:1.7.30'
|
implementation 'org.slf4j:slf4j-api:1.7.30'
|
||||||
runtimeOnly 'org.slf4j:slf4j-simple:1.7.30'
|
implementation 'org.slf4j:slf4j-simple:1.7.30'
|
||||||
|
|
||||||
testImplementation('org.spockframework:spock-core:2.0-M4-groovy-3.0')
|
testImplementation('org.spockframework:spock-core:2.0-M4-groovy-3.0')
|
||||||
testImplementation("org.slf4j:slf4j-simple:1.7.+")
|
testImplementation("org.slf4j:slf4j-simple:1.7.+")
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
id = syslogd
|
id = syslogd
|
||||||
group = biz.nellemann.syslogd
|
group = biz.nellemann.syslogd
|
||||||
version = 1.0.7
|
version = 1.0.8
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -25,37 +25,48 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
@Command(name = "syslogd",
|
@Command(name = "syslogd",
|
||||||
mixinStandardHelpOptions = true,
|
mixinStandardHelpOptions = true,
|
||||||
description = "Basic syslog server.",
|
description = "Syslog Daemon.",
|
||||||
versionProvider = biz.nellemann.syslogd.VersionProvider.class)
|
versionProvider = biz.nellemann.syslogd.VersionProvider.class)
|
||||||
public class Application implements Callable<Integer>, LogListener {
|
public class Application implements Callable<Integer>, LogListener {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(Application.class);
|
private final static Logger log = LoggerFactory.getLogger(Application.class);
|
||||||
|
|
||||||
@CommandLine.Option(names = {"-p", "--port"}, description = "Listening port [default: 514].")
|
@CommandLine.Option(names = {"-p", "--port"}, description = "Listening port [default: 514].", defaultValue = "514")
|
||||||
private int port = 514;
|
private int port;
|
||||||
|
|
||||||
@CommandLine.Option(names = "--no-udp", negatable = true, description = "Listen on UDP [default: true].")
|
@CommandLine.Option(names = "--no-udp", negatable = true, description = "Listen on UDP [default: true].", defaultValue = "true")
|
||||||
boolean udpServer = true;
|
private boolean udpServer;
|
||||||
|
|
||||||
@CommandLine.Option(names = "--no-tcp", negatable = true, description = "Listen on TCP [default: true].")
|
@CommandLine.Option(names = "--no-tcp", negatable = true, description = "Listen on TCP [default: true].", defaultValue = "true")
|
||||||
boolean tcpServer = true;
|
private boolean tcpServer;
|
||||||
|
|
||||||
@CommandLine.Option(names = "--no-ansi", negatable = true, description = "Output ANSI colors [default: true].")
|
@CommandLine.Option(names = "--no-ansi", negatable = true, description = "Output ANSI colors [default: true].", defaultValue = "true")
|
||||||
boolean ansiOutput = true;
|
private boolean ansiOutput;
|
||||||
|
|
||||||
@CommandLine.Option(names = "--rfc5424", description = "Parse RFC-5424 messages [default: RFC-3164].")
|
@CommandLine.Option(names = "--no-stdout", negatable = true, description = "Output messages to stdout [default: true].", defaultValue = "true")
|
||||||
boolean rfc5424 = false;
|
private boolean stdout;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = "--rfc5424", description = "Parse RFC-5424 messages [default: RFC-3164].", defaultValue = "false")
|
||||||
|
private boolean rfc5424;
|
||||||
|
|
||||||
public static void main(String... args) {
|
@CommandLine.Option(names = { "-f", "--forward"}, description = "Forward messages (UDP RFC-3164) [default: false].", defaultValue = "false")
|
||||||
int exitCode = new CommandLine(new Application()).execute(args);
|
private boolean forward;
|
||||||
System.exit(exitCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@CommandLine.Option(names = "--forward-host", description = "Forward to host [default: localhost].", paramLabel = "<hostname>", defaultValue = "localhost")
|
||||||
|
private String forwardHost;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = "--forward-port", description = "Forward to port [default: 1514].", paramLabel = "<port>", defaultValue = "1514")
|
||||||
|
private int forwardPort;
|
||||||
|
|
||||||
|
private UdpClient udpClient;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer call() throws IOException {
|
public Integer call() throws IOException {
|
||||||
|
|
||||||
|
if(forward) {
|
||||||
|
udpClient = new UdpClient(forwardHost, forwardPort);
|
||||||
|
}
|
||||||
|
|
||||||
if(udpServer) {
|
if(udpServer) {
|
||||||
UdpServer udpServer = new UdpServer(port);
|
UdpServer udpServer = new UdpServer(port);
|
||||||
udpServer.addEventListener(this);
|
udpServer.addEventListener(this);
|
||||||
|
@ -85,17 +96,34 @@ public class Application implements Callable<Integer>, LogListener {
|
||||||
msg = SyslogParser.parseRfc3164(message);
|
msg = SyslogParser.parseRfc3164(message);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
log.error("Problem parsing message: ", e);
|
log.error("onLogEvent() - Error parsing message: ", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(msg != null) {
|
if(msg != null) {
|
||||||
|
|
||||||
|
if(stdout) {
|
||||||
if(ansiOutput) {
|
if(ansiOutput) {
|
||||||
System.out.println(msg.toAnsiString());
|
System.out.println(SyslogPrinter.toAnsiString(msg));
|
||||||
} else {
|
} else {
|
||||||
System.out.println(msg);
|
System.out.println(SyslogPrinter.toString(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(forward) {
|
||||||
|
try {
|
||||||
|
udpClient.send(SyslogPrinter.toRfc3164(msg));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("onLogEvent()", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
int exitCode = new CommandLine(new Application()).execute(args);
|
||||||
|
System.exit(exitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,38 +50,4 @@ public class SyslogMessage {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(timestamp.toString());
|
|
||||||
sb.append(String.format(" [%8.8s.%-6.6s] ", facility, severity));
|
|
||||||
sb.append(String.format(" %-16.16s ", hostname));
|
|
||||||
sb.append(String.format(" %-32.32s ", application));
|
|
||||||
sb.append(message);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toAnsiString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
sb.append(timestamp.toString());
|
|
||||||
|
|
||||||
if(severity.toNumber() < 3 ) {
|
|
||||||
sb.append(Ansi.RED);
|
|
||||||
} else if(severity.toNumber() < 5) {
|
|
||||||
sb.append(Ansi.YELLOW);
|
|
||||||
} else {
|
|
||||||
sb.append(Ansi.GREEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append(String.format(" [%8.8s.%-6.6s] ", facility, severity)).append(Ansi.RESET);
|
|
||||||
sb.append(Ansi.BLUE).append(String.format(" %-16.16s ", hostname)).append(Ansi.RESET);
|
|
||||||
sb.append(Ansi.CYAN).append(String.format(" %-32.32s ", application)).append(Ansi.RESET);
|
|
||||||
sb.append(message);
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,4 +197,5 @@ public class SyslogParser {
|
||||||
return severity;
|
return severity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
74
src/main/java/biz/nellemann/syslogd/SyslogPrinter.java
Normal file
74
src/main/java/biz/nellemann/syslogd/SyslogPrinter.java
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
public class SyslogPrinter {
|
||||||
|
|
||||||
|
public static String toString(SyslogMessage msg) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(msg.timestamp.toString());
|
||||||
|
sb.append(String.format(" [%8.8s.%-6.6s] ", msg.facility, msg.severity));
|
||||||
|
sb.append(String.format(" %-16.16s ", msg.hostname));
|
||||||
|
sb.append(String.format(" %-32.32s ", msg.application));
|
||||||
|
sb.append(msg.message);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String toAnsiString(SyslogMessage msg) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append(msg.timestamp.toString());
|
||||||
|
|
||||||
|
if (msg.severity.toNumber() < 3) {
|
||||||
|
sb.append(Ansi.RED);
|
||||||
|
} else if (msg.severity.toNumber() < 5) {
|
||||||
|
sb.append(Ansi.YELLOW);
|
||||||
|
} else {
|
||||||
|
sb.append(Ansi.GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(String.format(" [%8.8s.%-6.6s] ", msg.facility, msg.severity)).append(Ansi.RESET);
|
||||||
|
sb.append(Ansi.BLUE).append(String.format(" %-16.16s ", msg.hostname)).append(Ansi.RESET);
|
||||||
|
sb.append(Ansi.CYAN).append(String.format(" %-32.32s ", msg.application)).append(Ansi.RESET);
|
||||||
|
sb.append(msg.message);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// <13>Sep 23 08:53:28 xps13 mark: adfdfdf3432434
|
||||||
|
public static String toRfc3164(SyslogMessage msg) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getPri(msg.facility, msg.severity));
|
||||||
|
sb.append(" " + new java.text.SimpleDateFormat("MMM dd HH:mm:ss").format(new java.util.Date(msg.timestamp.toEpochMilli())));
|
||||||
|
sb.append(" " + msg.hostname);
|
||||||
|
sb.append(" " + msg.application);
|
||||||
|
sb.append(": " + msg.message);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// <13>1 2020-09-23T08:57:30.950699+02:00 xps13 mark - - [timeQuality tzKnown="1" isSynced="1" syncAccuracy="125500"] adfdfdf3432434565656
|
||||||
|
public static String toRfc5424(SyslogMessage msg) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getPri(msg.facility, msg.severity));
|
||||||
|
sb.append("1"); // Version
|
||||||
|
sb.append(" " + new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new java.util.Date(msg.timestamp.toEpochMilli())));
|
||||||
|
sb.append(" " + msg.hostname);
|
||||||
|
sb.append(" " + msg.application);
|
||||||
|
sb.append(": " + msg.message);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Facility+Severity to PRI field
|
||||||
|
static private String getPri(Facility facility, Severity severity) {
|
||||||
|
return "<13>";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
30
src/main/java/biz/nellemann/syslogd/UdpClient.java
Normal file
30
src/main/java/biz/nellemann/syslogd/UdpClient.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package biz.nellemann.syslogd;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
|
public class UdpClient {
|
||||||
|
|
||||||
|
private DatagramSocket socket;
|
||||||
|
private InetAddress address;
|
||||||
|
private Integer port;
|
||||||
|
|
||||||
|
private byte[] buf;
|
||||||
|
|
||||||
|
public UdpClient(String host, Integer port) throws UnknownHostException, SocketException {
|
||||||
|
socket = new DatagramSocket();
|
||||||
|
address = InetAddress.getByName(host);
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(String msg) throws IOException {
|
||||||
|
buf = msg.getBytes();
|
||||||
|
DatagramPacket packet
|
||||||
|
= new DatagramPacket(buf, buf.length, address, port);
|
||||||
|
socket.send(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue