diff --git a/graylog2-server/src/main/java/org/graylog2/inputs/codecs/GelfCodec.java b/graylog2-server/src/main/java/org/graylog2/inputs/codecs/GelfCodec.java index 3ff81380bdc7..ae1f5551b124 100644 --- a/graylog2-server/src/main/java/org/graylog2/inputs/codecs/GelfCodec.java +++ b/graylog2-server/src/main/java/org/graylog2/inputs/codecs/GelfCodec.java @@ -99,15 +99,20 @@ private static int intValue(final JsonNode json, final String fieldName) { return -1; } - private static double doubleValue(final JsonNode json, final String fieldName) { - if (json != null) { - final JsonNode value = json.get(fieldName); - - if (value != null) { - return value.asDouble(-1.0); + private static double timestampValue(final JsonNode json) { + final JsonNode value = json.path(Message.FIELD_TIMESTAMP); + if (value.isNumber()) { + return value.asDouble(-1.0); + } else if (value.isTextual()) { + try { + return Double.parseDouble(value.asText()); + } catch (NumberFormatException e) { + log.debug("Unable to parse timestamp", e); + return -1.0; } + } else { + return -1.0; } - return -1.0; } @Nullable @@ -129,7 +134,7 @@ public Message decode(@Nonnull final RawMessage rawMessage) { validateGELFMessage(node, rawMessage.getId(), rawMessage.getRemoteAddress()); // Timestamp. - final double messageTimestamp = doubleValue(node, Message.FIELD_TIMESTAMP); + final double messageTimestamp = timestampValue(node); final DateTime timestamp; if (messageTimestamp <= 0) { timestamp = rawMessage.getTimestamp(); @@ -259,7 +264,7 @@ private void validateGELFMessage(JsonNode jsonNode, UUID id, ResolvableInetSocke final JsonNode timestampNode = jsonNode.path("timestamp"); if (timestampNode.isValueNode() && !timestampNode.isNumber()) { - throw new IllegalArgumentException(prefix + "has invalid \"timestamp\": " + timestampNode.asText()); + log.warn(prefix + "has invalid \"timestamp\": {} (type: {})", timestampNode.asText(), timestampNode.getNodeType().name()); } } diff --git a/graylog2-server/src/test/java/org/graylog2/inputs/codecs/GelfCodecTest.java b/graylog2-server/src/test/java/org/graylog2/inputs/codecs/GelfCodecTest.java index 10fa89df8e5f..912cb824ab69 100644 --- a/graylog2-server/src/test/java/org/graylog2/inputs/codecs/GelfCodecTest.java +++ b/graylog2-server/src/test/java/org/graylog2/inputs/codecs/GelfCodecTest.java @@ -21,6 +21,7 @@ import org.graylog2.plugin.Message; import org.graylog2.plugin.configuration.Configuration; import org.graylog2.plugin.journal.RawMessage; +import org.joda.time.DateTime; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -31,6 +32,7 @@ import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; +import java.time.DateTimeException; import java.util.Collections; import static org.assertj.core.api.Assertions.assertThat; @@ -327,7 +329,7 @@ public void decodeFailsWithBlankMessage() throws Exception { } @Test - public void decodeFailsWithWrongTypeForTimestamp() throws Exception { + public void decodeSucceedsWithWrongTypeForTimestamp() throws Exception { final String json = "{" + "\"version\": \"1.1\"," + "\"host\": \"example.org\"," @@ -337,9 +339,7 @@ public void decodeFailsWithWrongTypeForTimestamp() throws Exception { final RawMessage rawMessage = new RawMessage(json.getBytes(StandardCharsets.UTF_8)); - assertThatIllegalArgumentException().isThrownBy(() -> codec.decode(rawMessage)) - .withNoCause() - .withMessageMatching("GELF message <[0-9a-f-]+> has invalid \"timestamp\": Foobar"); + assertThat(rawMessage).isNotNull(); } @Test @@ -361,4 +361,36 @@ public void decodeSucceedsWithMinimalMessages() throws Exception { assertThat(codec.decode(new RawMessage("{\"short_message\":\"0\"}".getBytes(StandardCharsets.UTF_8)))).isNotNull(); assertThat(codec.decode(new RawMessage("{\"message\":\"0\"}".getBytes(StandardCharsets.UTF_8)))).isNotNull(); } + + @Test + public void decodeSucceedsWithValidTimestampIssue4027() throws Exception { + // https://github.com/Graylog2/graylog2-server/issues/4027 + final String json = "{" + + "\"version\": \"1.1\"," + + "\"short_message\": \"A short message that helps you identify what is going on\"," + + "\"host\": \"example.org\"," + + "\"timestamp\": 1500646980.661" + + "}"; + final RawMessage rawMessage = new RawMessage(json.getBytes(StandardCharsets.UTF_8)); + + final Message message = codec.decode(rawMessage); + assertThat(message).isNotNull(); + assertThat(message.getTimestamp()).isEqualTo(DateTime.parse("2017-07-21T14:23:00.661Z")); + } + + @Test + public void decodeSucceedsWithValidTimestampAsStringIssue4027() throws Exception { + // https://github.com/Graylog2/graylog2-server/issues/4027 + final String json = "{" + + "\"version\": \"1.1\"," + + "\"short_message\": \"A short message that helps you identify what is going on\"," + + "\"host\": \"example.org\"," + + "\"timestamp\": \"1500646980.661\"" + + "}"; + final RawMessage rawMessage = new RawMessage(json.getBytes(StandardCharsets.UTF_8)); + + final Message message = codec.decode(rawMessage); + assertThat(message).isNotNull(); + assertThat(message.getTimestamp()).isEqualTo(DateTime.parse("2017-07-21T14:23:00.661Z")); + } }