diff --git a/README.md b/README.md index 18d6786..e777fe9 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,9 @@ messageSender.setDefaultSeverity(Severity.INFORMATIONAL); messageSender.setSyslogServerHostname("127.0.0.1"); messageSender.setSyslogServerPort(1234); messageSender.setMessageFormat(MessageFormat.RFC_3164); // optional, default is RFC 3164 +// onSend is the default value, other value is onClose which has higher throughput but +// risks dataloss if the syslog server address dynamically changes +messageSender.setSocketFlush(TcpSyslogMessageSender.SocketFlush.onSend); messageSender.setSsl(false); // send a Syslog message @@ -119,6 +122,9 @@ messageSender.setDefaultSeverity(Severity.INFORMATIONAL); messageSender.setSyslogServerHostname("127.0.0.1"); messageSender.setSyslogServerPort(1234); messageSender.setMessageFormat(MessageFormat.RFC_3164); // optional, default is RFC 3164 +// onSend is the default value, other value is onClose which has higher throughput but +// risks dataloss if the syslog server address dynamically changes +messageSender.setSocketFlush(TcpSyslogMessageSender.SocketFlush.onSend); messageSender.setSsl(true); // send a Syslog message @@ -145,6 +151,9 @@ messageSender.setSyslogServerHostname("127.0.0.1"); // syslog-tls usually uses port 6514 as per https://tools.ietf.org/html/rfc5425#page-11 messageSender.setSyslogServerPort(6514); messageSender.setMessageFormat(MessageFormat.RFC_5425); +// onSend is the default value, other value is onClose which has higher throughput but +// risks dataloss if the syslog server address dynamically changes +messageSender.setSocketFlush(TcpSyslogMessageSender.SocketFlush.onSend); messageSender.setSsl(true); // send a Syslog message diff --git a/src/main/java/com/cloudbees/syslog/sender/TcpSyslogMessageSender.java b/src/main/java/com/cloudbees/syslog/sender/TcpSyslogMessageSender.java index 30859c6..fb06ca7 100644 --- a/src/main/java/com/cloudbees/syslog/sender/TcpSyslogMessageSender.java +++ b/src/main/java/com/cloudbees/syslog/sender/TcpSyslogMessageSender.java @@ -47,8 +47,14 @@ */ @ThreadSafe public class TcpSyslogMessageSender extends AbstractSyslogMessageSender implements Closeable { + public enum SocketFlush { + onSend, // default, + onClose // higher throughput, but at a risk of data-loss if the syslog server address dynamically changes + }; + public final static int SETTING_SOCKET_CONNECT_TIMEOUT_IN_MILLIS_DEFAULT_VALUE = 500; public final static int SETTING_MAX_RETRY = 2; + public final static SocketFlush DEFAULT_SOCKET_FLUSH = SocketFlush.onSend; /** * {@link java.net.InetAddress InetAddress} of the remote Syslog Server. @@ -74,6 +80,9 @@ public class TcpSyslogMessageSender extends AbstractSyslogMessageSender implemen * Number of retries to send a message before throwing an exception. */ private int maxRetryCount = SETTING_MAX_RETRY; + + private SocketFlush socketFlush = DEFAULT_SOCKET_FLUSH; + /** * Number of exceptions trying to send message. */ @@ -97,7 +106,9 @@ public synchronized void sendMessage(@Nonnull SyslogMessage message) throws IOEx ensureSyslogServerConnection(); message.toSyslogMessage(messageFormat, writer); writer.write(postfix); - writer.flush(); + if (socketFlush == SocketFlush.onSend) { + writer.flush(); + } return; } catch (IOException e) { lastException = e; @@ -265,6 +276,14 @@ public synchronized void setPostfix(String postfix) { this.postfix = postfix; } + public SocketFlush getSocketFlush() { + return socketFlush; + } + + public void setSocketFlush(SocketFlush socketFlush) { + this.socketFlush = socketFlush; + } + @Override public String toString() { return getClass().getName() + "{" + @@ -282,11 +301,17 @@ public String toString() { ", sendDurationInNanosCounter=" + sendDurationInNanosCounter + ", sendErrorCounter=" + sendErrorCounter + ", trySendErrorCounter=" + trySendErrorCounter + + ", socketFlush=" + socketFlush + '}'; } @Override public void close() throws IOException { - this.socket.close(); + if ((socketFlush == SocketFlush.onClose) && (writer != null)) { + // close will flush first, so if an exception ocurrs, data will still be passed to socket + writer.close(); + } + socket.close(); + } } diff --git a/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderLoadTest.java b/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderLoadTest.java index efb3f8d..30543b1 100644 --- a/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderLoadTest.java +++ b/src/test/java/com/cloudbees/syslog/sender/TcpSyslogMessageSenderLoadTest.java @@ -45,6 +45,7 @@ public static void main(String[] args) throws Exception { // messageSender.setSyslogServerHostname("127.0.0.1"); messageSender.setSyslogServerPort(46022); messageSender.setSsl(true); + messageSender.setSocketFlush(TcpSyslogMessageSender.SocketFlush.onSend); final AtomicInteger count = new AtomicInteger();