Improve UDP reception and add file output and ansi flag on/off.
This commit is contained in:
parent
a1599d0862
commit
8ae2ec7573
|
@ -59,7 +59,7 @@ ospackage {
|
|||
|
||||
buildRpm {
|
||||
dependsOn startShadowScripts
|
||||
requires('java-1.8.0-openjdk-headless')
|
||||
//requires('java-1.8.0-openjdk-headless')
|
||||
os = LINUX
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
id = syslogd
|
||||
group = biz.nellemann.syslogd
|
||||
version = 1.0.0
|
||||
version = 1.0.1
|
||||
|
|
|
@ -20,9 +20,9 @@ import java.util.EventObject;
|
|||
|
||||
public class LogEvent extends EventObject {
|
||||
|
||||
private String message;
|
||||
private final String message;
|
||||
|
||||
public LogEvent(Object source, String message ) {
|
||||
public LogEvent(final Object source, final String message ) {
|
||||
super( source );
|
||||
this.message = message;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package biz.nellemann.syslogd;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface LogListener {
|
||||
void onLogEvent(LogEvent event);
|
||||
}
|
||||
|
|
|
@ -44,12 +44,26 @@ public class SyslogMessage {
|
|||
String structuredData;
|
||||
|
||||
// The MSG part contains a free-form message that provides information about the event.
|
||||
String message;
|
||||
final private String message;
|
||||
|
||||
SyslogMessage(final String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String toString() {
|
||||
//return String.format("%s %s %s: %s", timestamp.toString(), hostname, application, message);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(timestamp.toString() + " ");
|
||||
sb.append("[" + facility + "." + severity + "]");
|
||||
sb.append("\t" + hostname);
|
||||
sb.append("\t" + application);
|
||||
sb.append("\t" + message);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public String toAnsiString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(timestamp.toString() + " ");
|
||||
|
@ -65,7 +79,7 @@ public class SyslogMessage {
|
|||
|
||||
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(Ansi.CLEAR_LINE);
|
||||
sb.append("\t" + message);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public class SyslogParser {
|
|||
private final static Logger log = LoggerFactory.getLogger(SyslogParser.class);
|
||||
|
||||
|
||||
public static SyslogMessage parseRfc3164(String input) throws NumberFormatException {
|
||||
public static SyslogMessage parseRfc3164(final String input) throws NumberFormatException {
|
||||
|
||||
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);
|
||||
|
@ -45,11 +45,11 @@ public class SyslogParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
String pri = matcher.group(1);
|
||||
String date = matcher.group(2);
|
||||
String hostname = matcher.group(3);
|
||||
String application = matcher.group(4);
|
||||
String message = matcher.group(5);
|
||||
final String pri = matcher.group(1);
|
||||
final String date = matcher.group(2);
|
||||
final String hostname = matcher.group(3);
|
||||
final String application = matcher.group(4);
|
||||
final String message = matcher.group(5);
|
||||
|
||||
log.debug("PRI: " + pri);
|
||||
log.debug("DATE: " + date);
|
||||
|
@ -62,19 +62,18 @@ public class SyslogParser {
|
|||
log.debug("facility: " + facility);
|
||||
log.debug("severity: " + severity);
|
||||
|
||||
SyslogMessage syslogMessage = new SyslogMessage();
|
||||
SyslogMessage syslogMessage = new SyslogMessage(message);
|
||||
syslogMessage.facility = Facility.getByNumber(facility);
|
||||
syslogMessage.severity = Severity.getByNumber(severity);
|
||||
syslogMessage.timestamp = parseRfc3164Timestamp(date);
|
||||
syslogMessage.hostname = hostname;
|
||||
syslogMessage.application = application;
|
||||
syslogMessage.message = message;
|
||||
|
||||
return syslogMessage;
|
||||
}
|
||||
|
||||
|
||||
public static SyslogMessage parseRfc5424(String input) 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);
|
||||
Matcher matcher = pattern.matcher(input);
|
||||
|
@ -84,15 +83,15 @@ public class SyslogParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
log.debug("PRI: " + pri);
|
||||
log.debug("VER: " + ver);
|
||||
|
@ -109,7 +108,7 @@ public class SyslogParser {
|
|||
log.debug("facility: " + facility);
|
||||
log.debug("severity: " + severity);
|
||||
|
||||
SyslogMessage syslogMessage = new SyslogMessage();
|
||||
SyslogMessage syslogMessage = new SyslogMessage(msg);
|
||||
syslogMessage.facility = Facility.getByNumber(facility);
|
||||
syslogMessage.severity = Severity.getByNumber(severity);
|
||||
syslogMessage.version = Integer.parseInt(ver);
|
||||
|
@ -122,7 +121,6 @@ public class SyslogParser {
|
|||
if(msgId != null && !msgId.equals("-"))
|
||||
syslogMessage.messageId = msgId;
|
||||
syslogMessage.structuredData = data;
|
||||
syslogMessage.message = msg;
|
||||
|
||||
return syslogMessage;
|
||||
}
|
||||
|
|
|
@ -19,26 +19,37 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@Command(name = "syslogd", mixinStandardHelpOptions = true, version = "syslogd 1.0",
|
||||
description = "Simple syslog server that prints messages to stdout.")
|
||||
@Command(name = "syslogd",
|
||||
mixinStandardHelpOptions = true,
|
||||
description = "Basic syslog server.",
|
||||
versionProvider = biz.nellemann.syslogd.VersionProvider.class)
|
||||
public class SyslogServer implements Callable<Integer>, LogListener {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(SyslogServer.class);
|
||||
private BufferedWriter bw;
|
||||
|
||||
@CommandLine.Option(names = {"-p", "--port"}, description = "Listening port, 514 (privileged) by default.")
|
||||
@CommandLine.Option(names = {"-p", "--port"}, description = "Listening port [default: 514]")
|
||||
private int port = 514;
|
||||
|
||||
@CommandLine.Option(names = "--no-udp", negatable = true, description = "Listen on UDP, true by default.")
|
||||
@CommandLine.Option(names = "--no-udp", negatable = true, description = "Listen on UDP [default: true]")
|
||||
boolean udpServer = true;
|
||||
|
||||
@CommandLine.Option(names = "--no-tcp", negatable = true, description = "Listen on TCP, true by default.")
|
||||
@CommandLine.Option(names = "--no-tcp", negatable = true, description = "Listen on TCP [default: true]")
|
||||
boolean tcpServer = true;
|
||||
|
||||
@CommandLine.Option(names = "--rfc3164", negatable = false, description = "Parse RFC3164 syslog message, RFC5424 by default.")
|
||||
@CommandLine.Option(names = "--rfc3164", negatable = false, description = "Parse RFC3164 messages [default: RFC5424]")
|
||||
boolean rfc3164 = false;
|
||||
|
||||
@CommandLine.Option(names = "--no-ansi", negatable = true, description = "ANSI in output [default: true]")
|
||||
boolean ansiOutput = true;
|
||||
|
||||
@CommandLine.Option(names = {"-f", "--file"}, description = "Write output to file [default: STDOUT]")
|
||||
File outputFile;
|
||||
|
||||
public static void main(String... args) {
|
||||
int exitCode = new CommandLine(new SyslogServer()).execute(args);
|
||||
System.exit(exitCode);
|
||||
|
@ -48,6 +59,15 @@ public class SyslogServer implements Callable<Integer>, LogListener {
|
|||
@Override
|
||||
public Integer call() throws Exception {
|
||||
|
||||
FileOutputStream fos = null;
|
||||
OutputStreamWriter w;
|
||||
|
||||
if(outputFile != null) {
|
||||
fos = new FileOutputStream(outputFile);
|
||||
w = new OutputStreamWriter(fos, "UTF-8");
|
||||
bw = new BufferedWriter(w);
|
||||
}
|
||||
|
||||
if(udpServer) {
|
||||
UdpServer udpServer = new UdpServer(port);
|
||||
udpServer.addEventListener(this);
|
||||
|
@ -60,6 +80,11 @@ public class SyslogServer implements Callable<Integer>, LogListener {
|
|||
tcpServer.start();
|
||||
}
|
||||
|
||||
if(outputFile != null) {
|
||||
bw.close();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -67,6 +92,7 @@ public class SyslogServer implements Callable<Integer>, LogListener {
|
|||
@Override
|
||||
public void onLogEvent(LogEvent event) {
|
||||
|
||||
// Parse message
|
||||
String message = event.getMessage();
|
||||
SyslogMessage msg = null;
|
||||
try {
|
||||
|
@ -80,9 +106,37 @@ public class SyslogServer implements Callable<Integer>, LogListener {
|
|||
}
|
||||
|
||||
if(msg != null) {
|
||||
System.out.println(msg);
|
||||
if(bw != null) {
|
||||
writeToFile(msg);
|
||||
} else {
|
||||
writeToStdout(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void writeToFile(SyslogMessage msg) {
|
||||
try {
|
||||
if(ansiOutput) {
|
||||
bw.append(msg.toAnsiString());
|
||||
} else {
|
||||
bw.append(msg.toString());
|
||||
}
|
||||
bw.newLine();
|
||||
bw.flush();
|
||||
} catch (IOException e) {
|
||||
log.error("file error", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeToStdout(SyslogMessage msg) {
|
||||
if(ansiOutput) {
|
||||
System.out.println(msg.toAnsiString());
|
||||
} else {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ public class UdpServer extends Thread {
|
|||
|
||||
public void run() {
|
||||
|
||||
byte[] buf = new byte[10000];
|
||||
byte[] buf = new byte[4096];
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
|
||||
while (listen) {
|
||||
try {
|
||||
socket.receive(packet);
|
||||
String packetData = new String(packet.getData(), "UTF8");
|
||||
String packetData = new String(packet.getData(), packet.getOffset(), packet.getLength(), "UTF8");
|
||||
sendEvent(packetData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
22
src/main/java/biz/nellemann/syslogd/VersionProvider.java
Normal file
22
src/main/java/biz/nellemann/syslogd/VersionProvider.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
package biz.nellemann.syslogd;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
class VersionProvider implements CommandLine.IVersionProvider {
|
||||
|
||||
public String[] getVersion() throws IOException {
|
||||
|
||||
URL url = getClass().getResource("/version.properties");
|
||||
if (url == null) {
|
||||
return new String[] { "No version.txt file found in the classpath." };
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
properties.load(url.openStream());
|
||||
return new String[] { "${COMMAND-FULL-NAME} " + properties.getProperty("VERSION_GRADLE") + "-" + properties.getProperty("VERSION_BUILD") };
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue