Summary
Syslog4j's SyslogServerEvent mishandles older RFC3164-style syslog messages that contain an ISO8601 timestamp. Example message that causes unwanted behavior:
<6>2016-10-12T14:10:18Z hostname testmsg[20]: {"cf_origin":"firehose","deployment":"cf","event_type":"ValueMetric","ip":"127.0.0.1","job_index":"0","level_mod":"6","msg":"","name":"RequestLatency","origin":"bbs","time":"2016-10-12T14:10:18Z","unit":"nanos","value":2.6071897e+07}"
Expected Behavior
Section 5.1 of RFC3164 says that implementers may wish to use an ISO8601 timestamp, so the expected behavior is that this is parsed out properly.
Current Behavior
Creating a SyslogServerEvent() with the above message will cause the timestamp to get replaced with Date(), and the rest of the message to be improperly parsed.
Possible Solution
In SyslogServerEvent, import org.joda.time.DateTime
and change the parseDate() function to the following:
protected void parseDate() {
int datelength = 16;
String dateFormatS = DATE_FORMAT;
boolean isDate8601 = false;
if (this.message.length() > datelength) {
// http://jira.graylog2.org/browse/SERVER-287
if (this.message.charAt(5) == ' ') {
datelength = 15;
dateFormatS = DATE_FORMAT_S;
}
if (Character.isDigit(this.message.charAt(0))) {
datelength = this.message.indexOf(' ') + 1;
isDate8601 = true;
}
String year = Integer.toString(Calendar.getInstance().get(Calendar.YEAR));
String originalDate = this.message.substring(0, datelength - 1);
String modifiedDate = originalDate + " " + year;
DateFormat dateFormat = new SimpleDateFormat(dateFormatS, Locale.ENGLISH);
try {
if (!isDate8601) {
this.date = dateFormat.parse(modifiedDate);
} else {
this.date = DateTime.parse(originalDate).toDate();
}
this.message = this.message.substring(datelength);
} catch (ParseException pe) {
this.date = new Date();
}
}
parseHost();
}
This will ensure that the timestamp is parsed properly and the parsing continues on to parse the host properly.
Steps to Reproduce (for bugs)
- Run Graylog 2.1.1 and set up a Syslog TCP stream
- Save the above message to a file, let's call it testmsg
cat testmsg|nc grayloghost port
- Check Graylog, find mangled fields in the message.
Context
This was discovered when trying to use Graylog to collect stats and other messages from Pivotal Cloud Foundry using the firehose-to-syslog nozzle provided to funnel stats into syslog messages. Due to the timestamp being ISO8601, syslog4j replaces it with the time the message was parsed with SyslogServerEvent.parseDate()
Your Environment
- Graylog Version: 2.1.1
- Elasticsearch Version: 2.3.3
- MongoDB Version: 3.2.6
- Operating System: RHEL 7.2
- Browser version: Chrome 52