diff --git a/README.md b/README.md index 9cf953e..fc7c464 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ In your `logback.xml`: - %msg + %msg @@ -116,7 +116,7 @@ The fields `@timestamp` and `message` are always sent and can not currently be c * `name` (required): Key to be used in the log event * `value` (required): Text string to be sent. Internally, the value is populated using a Logback PatternLayout, so all [Conversion Words](http://logback.qos.ch/manual/layouts.html#conversionWord) can be used (in addition to the standard static variable interpolations like `${HOSTNAME}`). * `allowEmpty` (optional, default `false`): Normally, if the `value` results in a `null` or empty string, the field will not be sent. If `allowEmpty` is set to `true` then the field will be sent regardless - * `type` (optional, default `String`): type of the field on the resulting JSON message. Possible values are: `String`, `int`, `float` and `boolean`. + * `type` (optional, default `String`): type of the field on the resulting JSON message. Possible values are: `String`, `int`, `float`, `boolean` and `object`. Use `object` if the value is the string representation of a JSON object or array ie. `{"k" : true}`or `[1,2,3,]`. Groovy Configuration ==================== diff --git a/src/main/java/com/internetitem/logback/elasticsearch/PropertySerializer.java b/src/main/java/com/internetitem/logback/elasticsearch/PropertySerializer.java index 6e23a98..2a5e4ac 100644 --- a/src/main/java/com/internetitem/logback/elasticsearch/PropertySerializer.java +++ b/src/main/java/com/internetitem/logback/elasticsearch/PropertySerializer.java @@ -19,6 +19,9 @@ void serializeProperty(JsonGenerator jsonGenerator, T event, AbstractPropertyAnd case BOOLEAN: serializeBooleanField(jsonGenerator, propertyAndEncoder, value); break; + case OBJECT: + serializeJsonObjectField(jsonGenerator, propertyAndEncoder, value); + break; default: serializeStringField(jsonGenerator, propertyAndEncoder, value); } @@ -52,4 +55,19 @@ private void serializeBooleanField(JsonGenerator jsonGenerator, AbstractProperty serializeStringField(jsonGenerator, propertyAndEncoder, value); } } + + + private void serializeJsonObjectField(JsonGenerator jsonGenerator, AbstractPropertyAndEncoder propertyAndEncoder, String value) throws IOException { + String trimmed = value != null ? value.trim() : ""; + if ("".equals(value)) { + jsonGenerator.writeFieldName(propertyAndEncoder.getName()); + jsonGenerator.writeRawValue("{}"); + } else if ((trimmed.startsWith("{") && trimmed.endsWith("}")) + || (trimmed.startsWith("[") && trimmed.endsWith("]"))) { + jsonGenerator.writeFieldName(propertyAndEncoder.getName()); + jsonGenerator.writeRawValue(trimmed); + } else { + serializeStringField(jsonGenerator, propertyAndEncoder, value); + } + } } \ No newline at end of file diff --git a/src/main/java/com/internetitem/logback/elasticsearch/config/Property.java b/src/main/java/com/internetitem/logback/elasticsearch/config/Property.java index a56f706..37de930 100644 --- a/src/main/java/com/internetitem/logback/elasticsearch/config/Property.java +++ b/src/main/java/com/internetitem/logback/elasticsearch/config/Property.java @@ -7,7 +7,7 @@ public class Property { private Type type = Type.STRING; public enum Type { - STRING, INT, FLOAT, BOOLEAN + STRING, INT, FLOAT, BOOLEAN, OBJECT } public Property() { diff --git a/src/test/java/com/internetitem/logback/elasticsearch/PropertySerializerTest.java b/src/test/java/com/internetitem/logback/elasticsearch/PropertySerializerTest.java index 3ae7c12..11f0c3d 100644 --- a/src/test/java/com/internetitem/logback/elasticsearch/PropertySerializerTest.java +++ b/src/test/java/com/internetitem/logback/elasticsearch/PropertySerializerTest.java @@ -138,4 +138,49 @@ public void should_serialize_object_when_invalid_type() throws Exception { // then verify(jsonGenerator).writeObject("value"); } + + @Test + public void should_serialize_object_as_raw_json() throws Exception { + Property property = new Property(); + property.setName("args"); + property.setValue("{\"name\": \"value\", \"serial\": 1} "); + property.setType("object"); + + org.mockito.Mockito.reset(jsonGenerator); + // when + propertySerializer.serializeProperty(jsonGenerator, loggingEvent, new ClassicPropertyAndEncoder(property, context)); + + // then + verify(jsonGenerator).writeRawValue("{\"name\": \"value\", \"serial\": 1}"); + } + + @Test + public void should_serialize_empty_object() throws Exception { + Property property = new Property(); + property.setName("args"); + property.setValue(""); + property.setType("object"); + property.setAllowEmpty(true); + + // when + propertySerializer.serializeProperty(jsonGenerator, loggingEvent, new ClassicPropertyAndEncoder(property, context)); + + // then + verify(jsonGenerator).writeRawValue("{}"); + } + + @Test + public void should_serialize_invalid_object_as_text() throws Exception { + Property property = new Property(); + property.setName("args2"); + property.setValue("{\"name\": \"value\""); + property.setType("object"); + + org.mockito.Mockito.reset(jsonGenerator); + // when + propertySerializer.serializeProperty(jsonGenerator, loggingEvent, new ClassicPropertyAndEncoder(property, context)); + + // then + verify(jsonGenerator).writeObject("{\"name\": \"value\""); + } } \ No newline at end of file