1. RFC5424 compatibility in timestamp format and message length 2. Introduced a new log method which accepts Date as an argument to create a syslog with the original timestamp.

This commit is contained in:
Negar Safinianaini 2016-02-11 13:53:55 +01:00
parent e3c9709ee9
commit ec7df03bce
10 changed files with 208 additions and 55 deletions

@ -24,6 +24,9 @@ public interface SyslogConstants extends Serializable {
public static final String STRUCTURED_DATA_NILVALUE = "-";
public static final String STRUCTURED_DATA_EMPTY_VALUE = "[0@0]";
public static final String SYSLOG_DATEFORMAT_RFC5424 = "yyyy-MM-dd'T'HH:mm:ss'Z'";
public static final int MAX_MESSAGE_LENGTH_RFC5424 = 2048;
public static final int MIN_MESSAGE_LENGTH_RFC5424 = 480;
public static final String CHAR_SET_DEFAULT = "UTF-8";

@ -1,5 +1,7 @@
package org.graylog2.syslog4j;
import java.util.Date;
/**
* SyslogIF provides a common interface for all Syslog4j client implementations.
* <p/>
@ -20,9 +22,11 @@ public interface SyslogIF extends SyslogConstants {
public void backLog(int level, String message, Throwable reasonThrowable);
public void backLog(int level, String message, String reason);
public void log(int level, String message);
public void log(int level, String message, Date datetime);
public void debug(String message);
public void info(String message);

@ -1,6 +1,7 @@
package org.graylog2.syslog4j;
import java.io.Serializable;
import java.util.Date;
/**
* SyslogMessageProcessorIF provides an extensible interface for writing custom
@ -19,4 +20,6 @@ public interface SyslogMessageProcessorIF extends Serializable {
public byte[] createPacketData(byte[] header, byte[] message, int start, int length);
public byte[] createPacketData(byte[] header, byte[] message, int start, int length, byte[] splitBeginText, byte[] splitEndText);
public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalName, Date datetime);
}

@ -14,6 +14,7 @@ import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessageIF;
import org.graylog2.syslog4j.util.SyslogUtility;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@ -123,6 +124,17 @@ public abstract class AbstractSyslog implements SyslogIF {
log(getMessageProcessor(), level, message);
}
}
public void log(int level, String message, Date datetime) {
if (this.syslogConfig.isUseStructuredData()) {
StructuredSyslogMessageIF structuredMessage = new StructuredSyslogMessage(null, null, null, message);
log(getStructuredMessageProcessor(), level, structuredMessage.createMessage(), datetime);
} else {
log(getMessageProcessor(), level, message, datetime);
}
}
public void log(int level, SyslogMessageIF message) {
if (message instanceof StructuredSyslogMessageIF) {
@ -223,7 +235,8 @@ public abstract class AbstractSyslog implements SyslogIF {
}
try {
write(messageProcessor, level, _message);
String header = messageProcessor.createSyslogHeader(this.syslogConfig.getFacility(), level, this.syslogConfig.getLocalName(), this.syslogConfig.isSendLocalTimestamp(), this.syslogConfig.isSendLocalName());
write(messageProcessor, level, _message, header);
} catch (SyslogRuntimeException sre) {
if (sre.getCause() != null) {
@ -239,15 +252,50 @@ public abstract class AbstractSyslog implements SyslogIF {
}
}
protected void write(SyslogMessageProcessorIF messageProcessor, int level, String message) throws SyslogRuntimeException {
String header = messageProcessor.createSyslogHeader(this.syslogConfig.getFacility(), level, this.syslogConfig.getLocalName(), this.syslogConfig.isSendLocalTimestamp(), this.syslogConfig.isSendLocalName());
public void log(SyslogMessageProcessorIF messageProcessor, int level, String message, Date datetime) {
String _message = null;
if (this.syslogConfig.isIncludeIdentInMessageModifier()) {
_message = prefixMessage(message, IDENT_SUFFIX_DEFAULT);
_message = modifyMessage(level, _message);
} else {
_message = modifyMessage(level, message);
_message = prefixMessage(_message, IDENT_SUFFIX_DEFAULT);
}
try {
String header = messageProcessor.createSyslogHeader(this.syslogConfig.getFacility(), level, this.syslogConfig.getLocalName(), this.syslogConfig.isSendLocalName(), datetime);
write(messageProcessor, level, _message, header);
} catch (SyslogRuntimeException sre) {
if (sre.getCause() != null) {
backLog(level, _message, sre.getCause());
} else {
backLog(level, _message, sre);
}
if (this.syslogConfig.isThrowExceptionOnWrite()) {
throw sre;
}
}
}
protected void write(SyslogMessageProcessorIF messageProcessor, int level, String message, String header) throws SyslogRuntimeException {
byte[] h = SyslogUtility.getBytes(this.syslogConfig, header);
byte[] m = SyslogUtility.getBytes(this.syslogConfig, message);
int mLength = m.length;
int hLength = h.length;
int expectedMinLength = this.syslogConfig.getMinMessageLength();
if (mLength < expectedMinLength) {
throw new SyslogRuntimeException("Message length is: " + String.valueOf(mLength) + " but expected to be at least: " + String.valueOf(expectedMinLength));
}
int availableLen = this.syslogConfig.getMaxMessageLength() - h.length;
int availableLen = this.syslogConfig.getMaxMessageLength() - hLength;
if (this.syslogConfig.isTruncateMessage()) {
if (availableLen > 0 && mLength > availableLen) {

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.graylog2.syslog4j.SyslogBackLogHandlerIF;
import org.graylog2.syslog4j.SyslogConstants;
import org.graylog2.syslog4j.SyslogMessageModifierIF;
import org.graylog2.syslog4j.SyslogRuntimeException;
import org.graylog2.syslog4j.impl.backlog.printstream.SystemErrSyslogBackLogHandler;
@ -45,6 +46,7 @@ public abstract class AbstractSyslogConfig implements AbstractSyslogConfigIF {
protected boolean throwExceptionOnInitialize = THROW_EXCEPTION_ON_INITIALIZE_DEFAULT;
protected int maxMessageLength = MAX_MESSAGE_LENGTH_DEFAULT;
protected int minMessageLength = 0;
protected byte[] splitMessageBeginText = SPLIT_MESSAGE_BEGIN_TEXT_DEFAULT.getBytes();
protected byte[] splitMessageEndText = SPLIT_MESSAGE_END_TEXT_DEFAULT.getBytes();
@ -127,6 +129,14 @@ public abstract class AbstractSyslogConfig implements AbstractSyslogConfigIF {
public void setMaxMessageLength(int maxMessageLength) {
this.maxMessageLength = maxMessageLength;
}
public int getMinMessageLength() {
return this.minMessageLength;
}
public void setMinMessageLength(int minMessageLength) {
this.minMessageLength = minMessageLength;
}
public boolean isSendLocalTimestamp() {
return this.sendLocalTimestamp;
@ -370,6 +380,8 @@ public abstract class AbstractSyslogConfig implements AbstractSyslogConfigIF {
public void setUseStructuredData(boolean useStructuredData) {
this.useStructuredData = useStructuredData;
setMaxMessageLength(SyslogConstants.MAX_MESSAGE_LENGTH_RFC5424);
setMinMessageLength(SyslogConstants.MIN_MESSAGE_LENGTH_RFC5424);
}
public Class getSyslogWriterClass() {

@ -62,4 +62,8 @@ public interface AbstractSyslogConfigIF extends SyslogConfigIF {
* @param maxQueueSize
*/
public void setMaxQueueSize(int maxQueueSize);
public int getMinMessageLength();
public void setMinMessageLength(int minMessageLength);
}

@ -1,8 +1,6 @@
package org.graylog2.syslog4j.impl.message.processor;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.graylog2.syslog4j.SyslogConstants;
import org.graylog2.syslog4j.SyslogMessageProcessorIF;
@ -74,21 +72,6 @@ public abstract class AbstractSyslogMessageProcessor implements SyslogMessagePro
buffer.append(">");
}
protected void appendLocalTimestamp(StringBuffer buffer) {
SimpleDateFormat dateFormat = new SimpleDateFormat(SYSLOG_DATEFORMAT, Locale.ENGLISH);
String datePrefix = dateFormat.format(new Date());
int pos = buffer.length() + 4;
buffer.append(datePrefix);
// RFC 3164 requires leading space for days 1-9
if (buffer.charAt(pos) == '0') {
buffer.setCharAt(pos, ' ');
}
}
protected void appendLocalName(StringBuffer buffer, String localName) {
if (localName != null) {
buffer.append(localName);
@ -99,20 +82,7 @@ public abstract class AbstractSyslogMessageProcessor implements SyslogMessagePro
buffer.append(' ');
}
public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalTimestamp, boolean sendLocalName) {
StringBuffer buffer = new StringBuffer();
appendPriority(buffer, facility, level);
if (sendLocalTimestamp) {
appendLocalTimestamp(buffer);
}
if (sendLocalName) {
appendLocalName(buffer, localName);
}
return buffer.toString();
}
protected abstract void appendTimestamp(StringBuffer buffer, Date datetime);
}

@ -1,5 +1,9 @@
package org.graylog2.syslog4j.impl.message.processor;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* SyslogMessageProcessor wraps AbstractSyslogMessageProcessor.
@ -32,4 +36,67 @@ public class SyslogMessageProcessor extends AbstractSyslogMessageProcessor {
public static SyslogMessageProcessor getDefault() {
return defaultInstance;
}
/* (non-Javadoc)
* @see org.graylog2.syslog4j.impl.message.processor.AbstractSyslogMessageProcessor#appendTimestamp(java.lang.StringBuffer, java.util.Date)
*
* This is compatible with BSD protocol
*/
@Override
public void appendTimestamp(StringBuffer buffer, Date datetime) {
SimpleDateFormat dateFormat = new SimpleDateFormat(SYSLOG_DATEFORMAT, Locale.ENGLISH);
String datePrefix = dateFormat.format(datetime);
int pos = buffer.length() + 4;
buffer.append(datePrefix);
// RFC 3164 requires leading space for days 1-9
if (buffer.charAt(pos) == '0') {
buffer.setCharAt(pos, ' ');
}
}
/* (non-Javadoc)
* @see org.graylog2.syslog4j.SyslogMessageProcessorIF#createSyslogHeader(int, int, java.lang.String, boolean, boolean)
*
* This is compatible with BSD protocol
*/
public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalTimestamp, boolean sendLocalName) {
StringBuffer buffer = new StringBuffer();
appendPriority(buffer, facility, level);
if (sendLocalTimestamp) {
appendTimestamp(buffer, new Date());
}
if (sendLocalName) {
appendLocalName(buffer, localName);
}
return buffer.toString();
}
/* (non-Javadoc)
* @see org.graylog2.syslog4j.SyslogMessageProcessorIF#createSyslogHeader(int, int, java.lang.String, boolean, java.util.Date)
*
* This is compatible with BSD protocol
*/
public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalName, Date datetime) {
StringBuffer buffer = new StringBuffer();
appendPriority(buffer, facility, level);
appendTimestamp(buffer, datetime);
if (sendLocalName) {
appendLocalName(buffer, localName);
}
return buffer.toString();
}
}

@ -1,7 +1,12 @@
package org.graylog2.syslog4j.impl.message.processor.structured;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.graylog2.syslog4j.SyslogConstants;
import org.graylog2.syslog4j.impl.message.processor.AbstractSyslogMessageProcessor;
import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessage;
@ -29,16 +34,16 @@ import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessage;
* @version $Id: StructuredSyslogMessageProcessor.java,v 1.4 2011/01/11 05:11:13 cvs Exp $
*/
public class StructuredSyslogMessageProcessor extends AbstractSyslogMessageProcessor {
private static final long serialVersionUID = -1563777226913475257L;
private static final long serialVersionUID = -1563777226913475257L;
public static String VERSION = "1";
private static final StructuredSyslogMessageProcessor INSTANCE = new StructuredSyslogMessageProcessor();
private static final StructuredSyslogMessageProcessor INSTANCE = new StructuredSyslogMessageProcessor();
protected static StructuredSyslogMessageProcessor defaultInstance = INSTANCE;
private String applicationName = STRUCTURED_DATA_APP_NAME_DEFAULT_VALUE;
private String processId = STRUCTURED_DATA_PROCESS_ID_DEFAULT_VALUE;
private String applicationName = STRUCTURED_DATA_APP_NAME_DEFAULT_VALUE;
private String processId = STRUCTURED_DATA_PROCESS_ID_DEFAULT_VALUE;
private DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime();
public static void setDefault(StructuredSyslogMessageProcessor messageProcessor) {
@ -84,23 +89,53 @@ public class StructuredSyslogMessageProcessor extends AbstractSyslogMessageProce
this.processId = processId;
}
public String createSyslogHeader(final int facility, final int level, String localName, final boolean sendLocalTimestamp, final boolean sendLocalName) {
final StringBuffer buffer = new StringBuffer();
/* (non-Javadoc)
* @see org.graylog2.syslog4j.impl.message.processor.AbstractSyslogMessageProcessor#appendTimestamp(java.lang.StringBuffer, java.util.Date)
*
* This is compatible with RFC5424 protocol.
*/
@Override
public void appendTimestamp(StringBuffer buffer, Date datetime) {
SimpleDateFormat formatter = new SimpleDateFormat(SyslogConstants.SYSLOG_DATEFORMAT_RFC5424);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(datetime.getTime());
String formatedTimestamp = formatter.format(calendar.getTime());
buffer.append(formatedTimestamp);
buffer.append(' ');
}
/* (non-Javadoc)
* @see org.graylog2.syslog4j.SyslogMessageProcessorIF#createSyslogHeader(int, int, java.lang.String, boolean, boolean)
*
* This is compatible with RFC5424 protocol.
*
* RFC5424 does not allow flags of sendLocalTimestamp and sendLocalName be off and therefore the incoming flags will not be used in this method.
*
*/
public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalTimestamp, boolean sendLocalName) {
return createSyslogHeaderInner(facility, level, localName, new Date());
}
/* (non-Javadoc)
* @see org.graylog2.syslog4j.SyslogMessageProcessorIF#createSyslogHeader(int, int, java.lang.String, boolean, java.util.Date)
*
* This is compatible with RFC5424 protocol.
*
* RFC5424 does not allow sendLocalName flag to be off and therefore sendLocalName will not be used in this method.
*/
public String createSyslogHeader(int facility, int level, String localName, boolean sendLocalName, Date datetime) {
return createSyslogHeaderInner(facility, level, localName, datetime);
}
private String createSyslogHeaderInner(int facility, int level, String localName, Date datetime) {
StringBuffer buffer = new StringBuffer();
appendPriority(buffer, facility, level);
buffer.append(VERSION);
buffer.append(' ');
getDateTimeFormatter().printTo(buffer, System.currentTimeMillis());
buffer.append(' ');
appendTimestamp(buffer, datetime);
appendLocalName(buffer, localName);
buffer.append(StructuredSyslogMessage.nilProtect(this.applicationName))
.append(' ');
buffer.append(StructuredSyslogMessage.nilProtect(this.applicationName)).append(' ');
buffer.append(StructuredSyslogMessage.nilProtect(this.processId)).append(' ');
return buffer.toString();
}
}

@ -1,5 +1,7 @@
package org.graylog2.syslog4j.impl.multiple;
import java.util.Date;
import org.graylog2.syslog4j.Syslog;
import org.graylog2.syslog4j.SyslogConfigIF;
import org.graylog2.syslog4j.SyslogConstants;
@ -171,4 +173,9 @@ public class MultipleSyslog implements SyslogIF {
public String getProtocol() {
return this.syslogProtocol;
}
public void log(int level, String message, Date datetime) {
}
}