diff --git a/README.md b/README.md index 0e5fbbb..6c5f730 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,15 @@ Some of my other related projects are: - Install the syslogd package (*.deb* or *.rpm*) from [packages](https://git.data.coop/nellemann/-/packages/generic/syslogd/) or build from source. ```text -Usage: syslogd [-dhV] [--[no-]ansi] [--[no-]stdout] [--[no-]tcp] [--[no-]udp] - [-f=] [-p=] [--to-gelf=] [--to-loki=] - [--to-syslog=] +Usage: syslogd [-dhV] [--[no-]ansi] [--[no-]stdin] [--[no-]stdout] [--[no-]tcp] + [--[no-]udp] [-f=] [-p=] [--to-gelf=] + [--to-loki=] [--to-syslog=] -d, --debug Enable debugging [default: 'false']. -f, --format= Input format: RFC-5424, RFC-3164 or GELF [default: RFC-3164]. -h, --help Show this help message and exit. --[no-]ansi Output in ANSI colors [default: true]. + --[no-]stdin Forward messages from stdin [default: true]. --[no-]stdout Output messages to stdout [default: true]. --[no-]tcp Listen on TCP [default: true]. --[no-]udp Listen on UDP [default: true]. diff --git a/build.gradle b/build.gradle index c272bb7..27b1cca 100644 --- a/build.gradle +++ b/build.gradle @@ -13,12 +13,12 @@ repositories { } dependencies { - annotationProcessor 'info.picocli:picocli-codegen:4.7.0' - implementation 'info.picocli:picocli:4.7.0' + annotationProcessor 'info.picocli:picocli-codegen:4.7.1' + implementation 'info.picocli:picocli:4.7.1' implementation 'org.slf4j:slf4j-api:2.0.6' implementation 'org.slf4j:slf4j-simple:2.0.6' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.1' - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' implementation 'org.apache.commons:commons-collections4:4.4' testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0' diff --git a/doc/syslogd.drawio b/doc/syslogd.drawio index 321134c..da01cc4 100644 --- a/doc/syslogd.drawio +++ b/doc/syslogd.drawio @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/doc/syslogd.png b/doc/syslogd.png index ee2a01b..adbea52 100644 Binary files a/doc/syslogd.png and b/doc/syslogd.png differ diff --git a/gradle.properties b/gradle.properties index 0b748d6..4d7af63 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ id = syslogd name = syslogd group = biz.nellemann.syslogd -version = 1.3.3 +version = 1.3.4 description = "Syslog Director" diff --git a/src/main/java/biz/nellemann/syslogd/Application.java b/src/main/java/biz/nellemann/syslogd/Application.java index f264dae..86d0d3a 100644 --- a/src/main/java/biz/nellemann/syslogd/Application.java +++ b/src/main/java/biz/nellemann/syslogd/Application.java @@ -58,6 +58,9 @@ public class Application implements Callable, LogReceiveListener { @CommandLine.Option(names = "--no-stdout", negatable = true, description = "Output messages to stdout [default: true].", defaultValue = "true") private boolean stdout; + @CommandLine.Option(names = "--no-stdin", negatable = true, description = "Forward messages from stdin [default: true].", defaultValue = "true") + private boolean stdin; + @CommandLine.Option(names = {"-f", "--format"}, description = "Input format: RFC-5424, RFC-3164 or GELF [default: RFC-3164].", defaultValue = "RFC-3164") private String protocol; @@ -77,7 +80,6 @@ public class Application implements Callable, LogReceiveListener { @Override public Integer call() throws IOException { - if(enableDebug) { System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG"); } @@ -115,6 +117,12 @@ public class Application implements Callable, LogReceiveListener { t.start(); } + if(stdin) { + InputReader inputReader = new InputReader(System.in, protocol); + inputReader.addEventListener(this); + inputReader.start(); + } + if(udpServer) { UdpServer udpServer = new UdpServer(port); udpServer.addEventListener(this); diff --git a/src/main/java/biz/nellemann/syslogd/InputReader.java b/src/main/java/biz/nellemann/syslogd/InputReader.java new file mode 100644 index 0000000..c7b5e61 --- /dev/null +++ b/src/main/java/biz/nellemann/syslogd/InputReader.java @@ -0,0 +1,69 @@ +package biz.nellemann.syslogd; + +import biz.nellemann.syslogd.msg.SyslogMessage; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class InputReader extends Thread { + + private final Scanner input; + private final String protocol; + + public InputReader(InputStream inputStream, String protocol) { + input = new Scanner(inputStream); + this.protocol = protocol; + } + + public void run() { + + while(input.hasNextLine()) { + SyslogMessage msg = new SyslogMessage(input.nextLine()); + msg.hostname = "localhost"; + msg.application = "syslogd"; + + String payload; + if(protocol.equalsIgnoreCase("GELF")) + payload = SyslogPrinter.toGelf(msg); + else if (protocol.equalsIgnoreCase("RFC-5424")) { + payload = SyslogPrinter.toRfc5424(msg); + } else { + payload = SyslogPrinter.toRfc3164(msg); + } + + sendEvent(payload); + } + input.close(); + } + + + private synchronized void sendEvent(String text) { + LogReceiveEvent event = new LogReceiveEvent( this, text); + for (LogReceiveListener eventListener : eventListeners) { + eventListener.onLogEvent(event); + } + } + + + /** + * Event Listener Configuration + */ + + protected List eventListeners = new ArrayList<>(); + + public synchronized void addEventListener(LogReceiveListener listener ) { + eventListeners.add( listener ); + } + + public synchronized void addEventListener(List listeners ) { + eventListeners.addAll(listeners); + } + + public synchronized void removeEventListener( LogReceiveListener l ) { + eventListeners.remove( l ); + } + + +} diff --git a/src/main/java/biz/nellemann/syslogd/LogReceiveEvent.java b/src/main/java/biz/nellemann/syslogd/LogReceiveEvent.java index 432245b..807fc05 100644 --- a/src/main/java/biz/nellemann/syslogd/LogReceiveEvent.java +++ b/src/main/java/biz/nellemann/syslogd/LogReceiveEvent.java @@ -23,15 +23,13 @@ import java.util.EventObject; public class LogReceiveEvent extends EventObject { private static final long serialVersionUID = 1L; - //private final String message; private final DatagramPacket packet; - /* public LogReceiveEvent(final Object source, final String message ) { super( source ); - this.message = message; + byte[] bytes = message.getBytes(); + this.packet = new DatagramPacket(bytes, bytes.length); } - */ public LogReceiveEvent(final Object source, final DatagramPacket packet) { super( source ); diff --git a/src/main/java/biz/nellemann/syslogd/msg/SyslogMessage.java b/src/main/java/biz/nellemann/syslogd/msg/SyslogMessage.java index 3f1df98..fca8ef4 100644 --- a/src/main/java/biz/nellemann/syslogd/msg/SyslogMessage.java +++ b/src/main/java/biz/nellemann/syslogd/msg/SyslogMessage.java @@ -36,7 +36,7 @@ public class SyslogMessage { // The TIMESTAMP field is a formalized timestamp derived from [RFC3339]. @JsonProperty("timestamp") // 1670357783.694 - in GELF: seconds since UNIX epoch with optional decimal places for milliseconds - public Instant timestamp; + public Instant timestamp = Instant.now(); // The HOSTNAME field identifies the machine that originally sent the syslog message. @JsonProperty("host") diff --git a/src/main/java/biz/nellemann/syslogd/parser/JsonUtil.java b/src/main/java/biz/nellemann/syslogd/parser/JsonUtil.java index 71e86ef..d29fdee 100644 --- a/src/main/java/biz/nellemann/syslogd/parser/JsonUtil.java +++ b/src/main/java/biz/nellemann/syslogd/parser/JsonUtil.java @@ -8,6 +8,10 @@ public class JsonUtil { public static String encode(String input) { + if(input == null) { + return ""; + } + StringBuilder output = new StringBuilder(); for (int i = 0; i < input.length(); i++) { diff --git a/src/main/java/biz/nellemann/syslogd/parser/SyslogParser.java b/src/main/java/biz/nellemann/syslogd/parser/SyslogParser.java index 432a9f1..a873bdf 100644 --- a/src/main/java/biz/nellemann/syslogd/parser/SyslogParser.java +++ b/src/main/java/biz/nellemann/syslogd/parser/SyslogParser.java @@ -73,7 +73,7 @@ public abstract class SyslogParser { Inflater decompressor = new Inflater(); decompressor.setInput(data, 0, data.length); //byte[] result = new byte[data.length * 2]; - int resultLength = decompressor.inflate(result); + decompressor.inflate(result); decompressor.end(); // Decode the bytes into a String