http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java new file mode 100644 index 0000000..1db6f52 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +/** + * Keeps constants separate from any class that may depend on third party jars. + */ +public final class JsonConstants { + public static final String ELT_CAUSE = "cause"; + public static final String ELT_EVENT = "event"; + public static final String ELT_CONTEXT_MAP = "contextMap"; + public static final String ELT_CONTEXT_STACK = "contextStack"; + public static final String ELT_MARKER = "marker"; + public static final String ELT_PARENTS = "parents"; + public static final String ELT_SOURCE = "source"; + public static final String ELT_SUPPRESSED = "suppressed"; + public static final String ELT_THROWN = "thrown"; + public static final String ELT_MESSAGE = "message"; + public static final String ELT_EXTENDED_STACK_TRACE = "extendedStackTrace"; + public static final String ELT_NANO_TIME = "nanoTime"; + public static final String ELT_INSTANT = "instant"; +}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java new file mode 100644 index 0000000..c11d22e --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Jackson mix-in for {@link Level}. + * <p> + * <em>Consider this class private.</em> + * </p> + * @see Marker + */ +@JsonIgnoreProperties({ "name", "declaringClass", "standardLevel" }) +public abstract class LevelMixIn { + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static Level getLevel(final String name) { + return null; + } + + @JsonValue + public abstract String name(); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java new file mode 100644 index 0000000..4a1199d --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public class ListOfMapEntryDeserializer extends StdDeserializer<Map<String, String>> { + + private static final long serialVersionUID = 1L; + + ListOfMapEntryDeserializer() { + super(Map.class); + } + + @Override + public Map<String, String> deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, + JsonProcessingException { + final List<MapEntry> list = jp.readValueAs(new TypeReference<List<MapEntry>>() { + // empty + }); + final HashMap<String, String> map = new HashMap<>(list.size()); + for (final MapEntry mapEntry : list) { + map.put(mapEntry.getKey(), mapEntry.getValue()); + } + return map; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java new file mode 100644 index 0000000..48a9911 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public class ListOfMapEntrySerializer extends StdSerializer<Map<String, String>> { + + private static final long serialVersionUID = 1L; + + protected ListOfMapEntrySerializer() { + super(Map.class, false); + } + + protected MapEntry[] createMapEntryArray(final Set<Entry<String, String>> entrySet) { + return new MapEntry[entrySet.size()]; + } + + @Override + public void serialize(final Map<String, String> map, final JsonGenerator jgen, final SerializerProvider provider) + throws IOException, JsonGenerationException { + final Set<Entry<String, String>> entrySet = map.entrySet(); + final MapEntry[] pairs = createMapEntryArray(entrySet); + int i = 0; + for (final Entry<String, String> entry : entrySet) { + pairs[i++] = new MapEntry(entry.getKey(), entry.getValue()); + } + jgen.writeObject(pairs); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java new file mode 100644 index 0000000..7d03805 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; + +/** + * Copy and edit the Jackson (Apache License 2.0) class to use Log4j attribute names. Does not work as of Jackson 2.3.2. + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public final class Log4jStackTraceElementDeserializer extends StdScalarDeserializer<StackTraceElement> { + private static final long serialVersionUID = 1L; + + /** + * Constructs a new initialized instance. + */ + public Log4jStackTraceElementDeserializer() { + super(StackTraceElement.class); + } + + @Override + public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, + JsonProcessingException { + JsonToken t = jp.getCurrentToken(); + // Must get an Object + if (t == JsonToken.START_OBJECT) { + String className = null, methodName = null, fileName = null; + int lineNumber = -1; + + while ((t = jp.nextValue()) != JsonToken.END_OBJECT) { + final String propName = jp.getCurrentName(); + if ("class".equals(propName)) { + className = jp.getText(); + } else if ("file".equals(propName)) { + fileName = jp.getText(); + } else if ("line".equals(propName)) { + if (t.isNumeric()) { + lineNumber = jp.getIntValue(); + } else { + // An XML number always comes in a string since there is no syntax help as with JSON. + try { + lineNumber = Integer.parseInt(jp.getText().trim()); + } catch (final NumberFormatException e) { + throw JsonMappingException.from(jp, "Non-numeric token (" + t + ") for property 'line'", e); + } + } + } else if ("method".equals(propName)) { + methodName = jp.getText(); + } else if ("nativeMethod".equals(propName)) { + // no setter, not passed via constructor: ignore + } else { + this.handleUnknownProperty(jp, ctxt, this._valueClass, propName); + } + } + return new StackTraceElement(className, methodName, fileName, lineNumber); + } + throw ctxt.mappingException(this._valueClass, t); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java new file mode 100644 index 0000000..e9607bd --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.util.Map; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.ThreadContext.ContextStack; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.impl.ThrowableProxy; +import org.apache.logging.log4j.core.time.Instant; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.util.ReadOnlyStringMap; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonRootName(JsonConstants.ELT_EVENT) +@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent") +@JsonPropertyOrder({ + // @formatter:off + "timeMillis", + JsonConstants.ELT_INSTANT, + "threadName", + "level", + "loggerName", + "marker", + "message", + "thrown", + JsonConstants.ELT_CONTEXT_MAP, + JsonConstants.ELT_CONTEXT_STACK, + "loggerFQCN", + "Source", + "endOfBatch" }) + // @formatter:on +/** + * As of Jackson 2.9.4, if we extend AbstractLogEventMixIn, then the {@link ObjectMessage} serializer + * {@code ObjectMessageSerializer} does not get invoked. Either a bug in Jackson or in our set up code. + */ +public abstract class LogEventJsonMixIn /* extends AbstractLogEventMixIn */ implements LogEvent { + + private static final long serialVersionUID = 1L; + + @JsonProperty(JsonConstants.ELT_CONTEXT_MAP) + @JsonSerialize(using = ContextDataSerializer.class) + @JsonDeserialize(using = ContextDataDeserializer.class) + @Override + public abstract ReadOnlyStringMap getContextData(); + + @Override + @JsonIgnore + public abstract Map<String, String> getContextMap(); + + @JsonProperty(JsonConstants.ELT_CONTEXT_STACK) + @Override + public abstract ContextStack getContextStack(); + + @JsonProperty(JsonConstants.ELT_INSTANT) + @Override + public abstract Instant getInstant(); + + @JsonProperty() + @Override + public abstract Level getLevel(); + + @JsonProperty() + @Override + public abstract String getLoggerFqcn(); + + @JsonProperty() + @Override + public abstract String getLoggerName(); + + @JsonProperty(JsonConstants.ELT_MARKER) + @Override + public abstract Marker getMarker(); + + @JsonProperty(JsonConstants.ELT_MESSAGE) + @JsonDeserialize(using = SimpleMessageDeserializer.class) + @Override + public abstract Message getMessage(); + + @JsonProperty(JsonConstants.ELT_SOURCE) + @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class) + @Override + public abstract StackTraceElement getSource(); + + @Override + @JsonProperty("threadId") + public abstract long getThreadId(); + + @Override + @JsonProperty("thread") + public abstract String getThreadName(); + + @Override + @JsonProperty("threadPriority") + public abstract int getThreadPriority(); + + @JsonIgnore + @Override + public abstract Throwable getThrown(); + + @JsonProperty(JsonConstants.ELT_THROWN) + @Override + public abstract ThrowableProxy getThrownProxy(); + + @JsonIgnore // ignore from 2.11 + @Override + public abstract long getTimeMillis(); + + @JsonProperty() + @Override + public abstract boolean isEndOfBatch(); + + @JsonIgnore + @Override + public abstract boolean isIncludeLocation(); + + @Override + public abstract void setEndOfBatch(boolean endOfBatch); + + @Override + public abstract void setIncludeLocation(boolean locationRequired); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java new file mode 100644 index 0000000..cd0639b --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.util.Map; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.ThreadContext.ContextStack; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.impl.ThrowableProxy; +import org.apache.logging.log4j.core.time.Instant; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.util.ReadOnlyStringMap; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonRootName(XmlConstants.ELT_EVENT) +@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent") +@JsonPropertyOrder({ "timeMillis", XmlConstants.ELT_INSTANT, "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP, + JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" }) +abstract class LogEventWithContextListMixIn implements LogEvent { + + private static final long serialVersionUID = 1L; + + @JsonProperty(JsonConstants.ELT_CONTEXT_MAP) + @JsonSerialize(using = ContextDataAsEntryListSerializer.class) + @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class) +// @JsonIgnore + @Override + public abstract ReadOnlyStringMap getContextData(); + + @Override + @JsonIgnore + public abstract Map<String, String> getContextMap(); + + @JsonProperty(JsonConstants.ELT_CONTEXT_STACK) + @Override + public abstract ContextStack getContextStack(); + + @JsonProperty(JsonConstants.ELT_INSTANT) + @Override + public abstract Instant getInstant(); + + @JsonProperty() + @Override + public abstract Level getLevel(); + + @JsonProperty() + @Override + public abstract String getLoggerFqcn(); + + @JsonProperty() + @Override + public abstract String getLoggerName(); + + @JsonProperty(JsonConstants.ELT_MARKER) + @Override + public abstract Marker getMarker(); + + @JsonProperty(JsonConstants.ELT_MESSAGE) + @JsonSerialize(using = MessageSerializer.class) + @JsonDeserialize(using = SimpleMessageDeserializer.class) + @Override + public abstract Message getMessage(); + + @JsonProperty(JsonConstants.ELT_SOURCE) + @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class) + @Override + public abstract StackTraceElement getSource(); + + @Override + @JsonProperty("threadId") + public abstract long getThreadId(); + + @Override + @JsonProperty("thread") + public abstract String getThreadName(); + + @Override + @JsonProperty("threadPriority") + public abstract int getThreadPriority(); + + @JsonIgnore + @Override + public abstract Throwable getThrown(); + + @JsonProperty(JsonConstants.ELT_THROWN) + @Override + public abstract ThrowableProxy getThrownProxy(); + + @JsonIgnore // ignore from 2.11 + @Override + public abstract long getTimeMillis(); + + @JsonProperty() + @Override + public abstract boolean isEndOfBatch(); + + @JsonIgnore + @Override + public abstract boolean isIncludeLocation(); + + @Override + public abstract void setEndOfBatch(boolean endOfBatch); + + @Override + public abstract void setIncludeLocation(boolean locationRequired); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java new file mode 100644 index 0000000..fc02180 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.util.Strings; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + * <p> + * Used to represent map entries in a generic fashion because the default Jackson behavior uses the key as the element + * tag. Using the key as an element/property name would mean that you cannot have a generic JSON/XML schema for all log + * event. + * </p> + */ +@JsonPropertyOrder({ "key", "value" }) +public class MapEntry { + + @JsonProperty + private String key; + + @JsonProperty + private String value; + + @JsonCreator + public MapEntry(@JsonProperty("key") final String key, @JsonProperty("value") final String value) { + this.setKey(key); + this.setValue(value); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof MapEntry)) { + return false; + } + final MapEntry other = (MapEntry) obj; + if (this.getKey() == null) { + if (other.getKey() != null) { + return false; + } + } else if (!this.getKey().equals(other.getKey())) { + return false; + } + if (this.getValue() == null) { + if (other.getValue() != null) { + return false; + } + } else if (!this.getValue().equals(other.getValue())) { + return false; + } + return true; + } + + public String getKey() { + return this.key; + } + + public String getValue() { + return this.value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((this.getKey() == null) ? 0 : this.getKey().hashCode()); + result = prime * result + ((this.getValue() == null) ? 0 : this.getValue().hashCode()); + return result; + } + + public void setKey(final String key) { + this.key = key; + } + + public void setValue(final String value) { + this.value = value; + } + + @Override + public String toString() { + return Strings.EMPTY + this.getKey() + "=" + this.getValue(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java new file mode 100644 index 0000000..45bbcc3 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.Marker; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** + * Jackson mix-in for {@link Marker}. + * <p> + * If we want to deal with more than one {@link Marker} implementation then recode these annotations to include metadata. + * </p> + * <p> + * <em>Consider this class private.</em> + * </p> + * <p> + * Example XML: + * </p> + * <pre> +<Marker name="Marker1"> + <Parents> + <Marker name="ParentMarker1"> + <Parents> + <Marker name="GrandMotherMarker"/> + <Marker name="GrandFatherMarker"/> + </Parents> + </Marker> + <Marker name="ParentMarker2"/> + </Parents> +</Marker> + * </pre> + * + * @see Marker + */ +// Alternate for multiple Marker implementation. +// @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +@JsonDeserialize(as = org.apache.logging.log4j.MarkerManager.Log4jMarker.class) +public abstract class MarkerMixIn implements Marker { + private static final long serialVersionUID = 1L; + + @JsonCreator + public MarkerMixIn(@JsonProperty("name") final String name) { + // empty + } + + @Override + @JsonProperty("name") + public abstract String getName(); + + @Override + @JsonProperty(JsonConstants.ELT_PARENTS) + public abstract Marker[] getParents(); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java new file mode 100644 index 0000000..faff2da --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; + +import org.apache.logging.log4j.message.Message; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public final class MessageSerializer extends StdScalarSerializer<Message> { + + private static final long serialVersionUID = 1L; + + public MessageSerializer() { + super(Message.class); + } + + @Override + public void serialize(final Message value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, + JsonGenerationException { + jgen.writeString(value.getFormattedMessage()); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java new file mode 100644 index 0000000..b98edb5 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; +import java.util.List; + +import org.apache.logging.log4j.spi.MutableThreadContextStack; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +final class MutableThreadContextStackDeserializer extends StdDeserializer<MutableThreadContextStack> { + + private static final long serialVersionUID = 1L; + + MutableThreadContextStackDeserializer() { + super(MutableThreadContextStack.class); + } + + @Override + public MutableThreadContextStack deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, + JsonProcessingException { + final List<String> list = jp.readValueAs(new TypeReference<List<String>>() { + // empty + }); + return new MutableThreadContextStack(list); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java new file mode 100644 index 0000000..3cb9af2 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; + +import org.apache.logging.log4j.message.ObjectMessage; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +final class ObjectMessageSerializer extends StdScalarSerializer<ObjectMessage> { + + private static final long serialVersionUID = 1L; + + ObjectMessageSerializer() { + super(ObjectMessage.class); + } + + @Override + public void serialize(final ObjectMessage value, final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider) throws IOException, JsonGenerationException { + jsonGenerator.writeObject(value.getParameter()); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java new file mode 100644 index 0000000..3d73d93 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java @@ -0,0 +1,38 @@ +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement; +import org.apache.logging.log4j.core.impl.ThrowableProxy; +import org.apache.logging.log4j.core.time.Instant; + +import com.fasterxml.jackson.databind.Module.SetupContext; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * Used to set up {@link SetupContext} from different {@link SimpleModule}s. + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public class SetupContextInitializer { + + public void setupModule(final SetupContext context, final boolean includeStacktrace, + final boolean stacktraceAsString) { + // JRE classes: we cannot edit those with Jackson annotations + context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class); + // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not + // depend on Jackson. + context.setMixInAnnotations(Marker.class, MarkerMixIn.class); + context.setMixInAnnotations(Level.class, LevelMixIn.class); + context.setMixInAnnotations(Instant.class, InstantMixIn.class); + context.setMixInAnnotations(LogEvent.class, LogEventWithContextListMixIn.class); + // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to. + context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class); + context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace + ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class) + : ThrowableProxyWithoutStacktraceMixIn.class); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java new file mode 100644 index 0000000..2ab948c --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; + +import org.apache.logging.log4j.message.SimpleMessage; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; + +/** + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public final class SimpleMessageDeserializer extends StdScalarDeserializer<SimpleMessage> { + + private static final long serialVersionUID = 1L; + + SimpleMessageDeserializer() { + super(SimpleMessage.class); + } + + @Override + public SimpleMessage deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) + throws IOException, JsonProcessingException { + return new SimpleMessage(jsonParser.getValueAsString()); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java new file mode 100644 index 0000000..edae1bc --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java @@ -0,0 +1,26 @@ +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.ThreadContext.ContextStack; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.message.ObjectMessage; + +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * Used to set up {@link SimpleModule} from different {@link SimpleModule} subclasses. + * <p> + * <em>Consider this class private.</em> + * </p> + */ +public class SimpleModuleInitializer { + public void initialize(final SimpleModule simpleModule, final boolean objectMessageAsJsonObject) { + // Workaround because mix-ins do not work for classes that already have a built-in deserializer. + // See Jackson issue 429. + simpleModule.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer()); + simpleModule.addDeserializer(ContextStack.class, new MutableThreadContextStackDeserializer()); + if (objectMessageAsJsonObject) { + simpleModule.addSerializer(ObjectMessage.class, new ObjectMessageSerializer()); + } + simpleModule.addSerializer(Message.class, new MessageSerializer()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java new file mode 100644 index 0000000..0f0f025 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.logging.log4j.jackson; + +/** + * Defines constants use for naming stack trace elements. + */ +public class StackTraceElementConstants { + + public static final String ATTR_CLASS = "class"; + public static final String ATTR_FILE = "file"; + public static final String ATTR_LINE = "line"; + public static final String ATTR_METHOD = "method"; + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java new file mode 100644 index 0000000..b3bff92 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.logging.log4j.jackson; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Jackson mix-in for {@link StackTraceElement}. + * <p> + * <em>Consider this class private.</em> + * </p> + * + * @see StackTraceElement + */ +@JsonIgnoreProperties("nativeMethod") +public abstract class StackTraceElementMixIn { + + @JsonCreator + protected StackTraceElementMixIn( + // @formatter:off + @JsonProperty(StackTraceElementConstants.ATTR_CLASS) final String declaringClass, + @JsonProperty(StackTraceElementConstants.ATTR_METHOD) final String methodName, + @JsonProperty(StackTraceElementConstants.ATTR_FILE) final String fileName, + @JsonProperty(StackTraceElementConstants.ATTR_LINE) final int lineNumber) + // @formatter:on + { + // empty + } + + @JsonProperty(StackTraceElementConstants.ATTR_CLASS) + protected abstract String getClassName(); + + @JsonProperty(StackTraceElementConstants.ATTR_FILE) + protected abstract String getFileName(); + + @JsonProperty(StackTraceElementConstants.ATTR_LINE) + protected abstract int getLineNumber(); + + @JsonProperty(StackTraceElementConstants.ATTR_METHOD) + protected abstract String getMethodName(); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java new file mode 100644 index 0000000..7116c80 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement; +import org.apache.logging.log4j.core.impl.ThrowableProxy; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Mix-in for {@link ThrowableProxy}. + */ +public abstract class ThrowableProxyMixIn { + + @JsonProperty(JsonConstants.ELT_CAUSE) + private ThrowableProxyMixIn causeProxy; + + @JsonProperty + private int commonElementCount; + + @JsonProperty(JsonConstants.ELT_EXTENDED_STACK_TRACE) + private ExtendedStackTraceElement[] extendedStackTrace; + + @JsonProperty + private String localizedMessage; + + @JsonProperty + private String message; + + @JsonProperty + private String name; + + @JsonIgnore + private transient Throwable throwable; + + @JsonIgnore + public abstract String getCauseStackTraceAsString(); + + @JsonIgnore + public abstract String getExtendedStackTraceAsString(); + + @JsonIgnore + public abstract StackTraceElement[] getStackTrace(); + + @JsonProperty(JsonConstants.ELT_SUPPRESSED) + public abstract ThrowableProxy[] getSuppressedProxies(); + + @JsonIgnore + public abstract String getSuppressedStackTrace(); + + @JsonIgnore + public abstract Throwable getThrowable(); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java new file mode 100644 index 0000000..e73a108 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement; +import org.apache.logging.log4j.core.impl.ThrowableProxy; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Mix-in for {@link org.apache.logging.log4j.core.impl.ThrowableProxy}. + */ +public abstract class ThrowableProxyWithStacktraceAsStringMixIn { + + @JsonProperty(JsonConstants.ELT_CAUSE) + private ThrowableProxyWithStacktraceAsStringMixIn causeProxy; + + @JsonProperty + private int commonElementCount; + + @JsonIgnore + private ExtendedStackTraceElement[] extendedStackTrace; + + @JsonProperty + private String localizedMessage; + + @JsonProperty + private String message; + + @JsonProperty + private String name; + + @JsonIgnore + private transient Throwable throwable; + + @JsonIgnore + public abstract String getCauseStackTraceAsString(); + + @JsonProperty(JsonConstants.ELT_EXTENDED_STACK_TRACE) + public abstract String getExtendedStackTraceAsString(); + + @JsonIgnore + public abstract StackTraceElement[] getStackTrace(); + + @JsonProperty(JsonConstants.ELT_SUPPRESSED) + public abstract ThrowableProxy[] getSuppressedProxies(); + + @JsonIgnore + public abstract String getSuppressedStackTrace(); + + @JsonIgnore + public abstract Throwable getThrowable(); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java new file mode 100644 index 0000000..b80c89c --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement; +import org.apache.logging.log4j.core.impl.ThrowableProxy; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Mix-in for {@link ThrowableProxy}. + */ +public abstract class ThrowableProxyWithoutStacktraceMixIn { + + @JsonProperty(JsonConstants.ELT_CAUSE) + private ThrowableProxyWithoutStacktraceMixIn causeProxy; + + @JsonProperty + private int commonElementCount; + + @JsonIgnore + private ExtendedStackTraceElement[] extendedStackTrace; + + @JsonProperty + private String localizedMessage; + + @JsonProperty + private String message; + + @JsonProperty + private String name; + + @JsonIgnore + private transient Throwable throwable; + + @JsonIgnore + public abstract String getCauseStackTraceAsString(); + + @JsonIgnore + public abstract String getExtendedStackTraceAsString(); + + @JsonIgnore + public abstract StackTraceElement[] getStackTrace(); + + @JsonProperty(JsonConstants.ELT_SUPPRESSED) + public abstract ThrowableProxy[] getSuppressedProxies(); + + @JsonIgnore + public abstract String getSuppressedStackTrace(); + + @JsonIgnore + public abstract Throwable getThrowable(); + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java new file mode 100644 index 0000000..10dc37d --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.jackson; + +/** + * Keeps constants separate from any class that may depend on third party jars. + */ +public final class XmlConstants { + public static final String ELT_CAUSE = "Cause"; + public static final String ELT_CONTEXT_MAP = "ContextMap"; + public static final String ELT_CONTEXT_STACK = "ContextStack"; + public static final String ELT_CONTEXT_STACK_ITEM = "ContextStackItem"; + public static final String ELT_EVENT = "Event"; + public static final String ELT_EXTENDED_STACK_TRACE = "ExtendedStackTrace"; + public static final String ELT_EXTENDED_STACK_TRACE_ITEM = "ExtendedStackTraceItem"; + public static final String ELT_INSTANT = "Instant"; + public static final String ELT_MARKER = "Marker"; + public static final String ELT_MESSAGE = "Message"; + public static final String ELT_PARENTS = "Parents"; + public static final String ELT_SOURCE = "Source"; + public static final String ELT_SUPPRESSED = "Suppressed"; + public static final String ELT_SUPPRESSED_ITEM = "SuppressedItem"; + public static final String ELT_THROWN = "Thrown"; + public static final String XML_NAMESPACE = "http://logging.apache.org/log4j/2.0/events"; +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java new file mode 100644 index 0000000..a468c1e --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java @@ -0,0 +1,378 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ + +package org.apache.logging.log4j.jackson.layout; + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.impl.MutableLogEvent; +import org.apache.logging.log4j.core.layout.AbstractStringLayout; +import org.apache.logging.log4j.core.lookup.StrSubstitutor; +import org.apache.logging.log4j.core.util.KeyValuePair; +import org.apache.logging.log4j.core.util.StringBuilderWriter; +import org.apache.logging.log4j.jackson.XmlConstants; +import org.apache.logging.log4j.util.Strings; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectWriter; + +abstract class AbstractJacksonLayout extends AbstractStringLayout { + + public static abstract class Builder<B extends Builder<B>> extends AbstractStringLayout.Builder<B> { + + @PluginBuilderAttribute + private boolean eventEol; + + @PluginBuilderAttribute + private boolean compact; + + @PluginBuilderAttribute + private boolean complete; + + @PluginBuilderAttribute + private boolean locationInfo; + + @PluginBuilderAttribute + private boolean properties; + + @PluginBuilderAttribute + private boolean includeStacktrace = true; + + @PluginBuilderAttribute + private boolean stacktraceAsString = false; + + @PluginBuilderAttribute + private boolean includeNullDelimiter = false; + + @PluginElement("AdditionalField") + private KeyValuePair[] additionalFields; + + public KeyValuePair[] getAdditionalFields() { + return additionalFields; + } + + public boolean getEventEol() { + return eventEol; + } + + public boolean isCompact() { + return compact; + } + + public boolean isComplete() { + return complete; + } + + public boolean isIncludeNullDelimiter() { + return includeNullDelimiter; + } + + /** + * If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true". + * + * @return If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true". + */ + public boolean isIncludeStacktrace() { + return includeStacktrace; + } + + public boolean isLocationInfo() { + return locationInfo; + } + + public boolean isProperties() { + return properties; + } + + public boolean isStacktraceAsString() { + return stacktraceAsString; + } + + /** + * Additional fields to set on each log event. + * + * @return this builder + */ + public B setAdditionalFields(final KeyValuePair[] additionalFields) { + this.additionalFields = additionalFields; + return asBuilder(); + } + + public B setCompact(final boolean compact) { + this.compact = compact; + return asBuilder(); + } + + public B setComplete(final boolean complete) { + this.complete = complete; + return asBuilder(); + } + + public B setEventEol(final boolean eventEol) { + this.eventEol = eventEol; + return asBuilder(); + } + + /** + * Whether to include NULL byte as delimiter after each event (optional, default to false). + * + * @return this builder + */ + public B setIncludeNullDelimiter(final boolean includeNullDelimiter) { + this.includeNullDelimiter = includeNullDelimiter; + return asBuilder(); + } + + /** + * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". + * + * @param includeStacktrace + * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". + * @return this builder + */ + public B setIncludeStacktrace(final boolean includeStacktrace) { + this.includeStacktrace = includeStacktrace; + return asBuilder(); + } + + public B setLocationInfo(final boolean locationInfo) { + this.locationInfo = locationInfo; + return asBuilder(); + } + + public B setProperties(final boolean properties) { + this.properties = properties; + return asBuilder(); + } + + /** + * Whether to format the stacktrace as a string, and not a nested object (optional, defaults to false). + * + * @return this builder + */ + public B setStacktraceAsString(final boolean stacktraceAsString) { + this.stacktraceAsString = stacktraceAsString; + return asBuilder(); + } + + protected String toStringOrNull(final byte[] header) { + return header == null ? null : new String(header, Charset.defaultCharset()); + } + } + @JsonRootName(XmlConstants.ELT_EVENT) + public static class LogEventWrapperWithAdditionalFields { + + private final Object logEvent; + private final Map<String, String> additionalFields; + + public LogEventWrapperWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) { + this.logEvent = logEvent; + this.additionalFields = additionalFields; + } + + @JsonAnyGetter + @SuppressWarnings("unused") + public Map<String, String> getAdditionalFields() { + return additionalFields; + } + + @JsonUnwrapped + public Object getLogEvent() { + return logEvent; + } + } + + protected static class ResolvableKeyValuePair { + + final String key; + final String value; + final boolean valueNeedsLookup; + + ResolvableKeyValuePair(final KeyValuePair pair) { + this.key = pair.getKey(); + this.value = pair.getValue(); + this.valueNeedsLookup = AbstractJacksonLayout.valueNeedsLookup(this.value); + } + } + + protected static final String DEFAULT_EOL = "\r\n"; + + protected static final String COMPACT_EOL = Strings.EMPTY; + private static LogEvent convertMutableToLog4jEvent(final LogEvent event) { + // TODO Jackson-based layouts have certain filters set up for Log4jLogEvent. + // TODO Need to set up the same filters for MutableLogEvent but don't know how... + // This is a workaround. + return event instanceof MutableLogEvent ? ((MutableLogEvent) event).createMemento() : event; + } + private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config, + final KeyValuePair[] additionalFields) { + if (additionalFields == null || additionalFields.length == 0) { + // No fields set + return new ResolvableKeyValuePair[0]; + } + + // Convert to specific class which already determines whether values needs lookup during serialization + final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length]; + + for (int i = 0; i < additionalFields.length; i++) { + final ResolvableKeyValuePair resolvable = resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]); + + // Validate + if (config == null && resolvable.valueNeedsLookup) { + throw new IllegalArgumentException( + "configuration needs to be set when there are additional fields with variables"); + } + } + + return resolvableFields; + } + protected static boolean valueNeedsLookup(final String value) { + return value != null && value.contains("${"); + } + protected final String eol; + protected final ObjectWriter objectWriter; + + protected final boolean compact; + + protected final boolean complete; + + protected final boolean includeNullDelimiter; + + protected final ResolvableKeyValuePair[] additionalFields; + + @Deprecated + protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset, + final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer, + final Serializer footerSerializer) { + this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer, false); + } + + @Deprecated + protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset, + final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer, + final Serializer footerSerializer, final boolean includeNullDelimiter) { + this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer, + includeNullDelimiter, null); + } + + protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset, + final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer, + final Serializer footerSerializer, final boolean includeNullDelimiter, + final KeyValuePair[] additionalFields) { + super(config, charset, headerSerializer, footerSerializer); + this.objectWriter = objectWriter; + this.compact = compact; + this.complete = complete; + this.eol = compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL; + this.includeNullDelimiter = includeNullDelimiter; + this.additionalFields = prepareAdditionalFields(config, additionalFields); + } + + protected LogEventWrapperWithAdditionalFields createLogEventWrapperWithAdditionalFields(final LogEvent event, + final Map<String, String> additionalFieldsMap) { + return new LogEventWrapperWithAdditionalFields(event, additionalFieldsMap); + } + + private Map<String, String> resolveAdditionalFields(final LogEvent logEvent) { + // Note: LinkedHashMap retains order + final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length); + final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor(); + + // Go over each field + for (final ResolvableKeyValuePair pair : additionalFields) { + if (pair.valueNeedsLookup) { + // Resolve value + additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value)); + } else { + // Plain text value + additionalFieldsMap.put(pair.key, pair.value); + } + } + + return additionalFieldsMap; + } + + /** + * Formats a {@link org.apache.logging.log4j.core.LogEvent}. + * + * @param event + * The LogEvent. + * @return The XML representation of the LogEvent. + */ + @Override + public String toSerializable(final LogEvent event) { + final StringBuilderWriter writer = new StringBuilderWriter(); + try { + toSerializable(event, writer); + return writer.toString(); + } catch (final IOException e) { + // Should this be an ISE or IAE? + LOGGER.error(e); + return Strings.EMPTY; + } + } + + public void toSerializable(final LogEvent event, final Writer writer) + throws JsonGenerationException, JsonMappingException, IOException { + objectWriter.writeValue(writer, wrapLogEvent(convertMutableToLog4jEvent(event))); + writer.write(eol); + if (includeNullDelimiter) { + writer.write('\0'); + } + markEvent(); + } + + protected Object wrapLogEvent(final LogEvent event) { + if (additionalFields.length > 0) { + // Construct map for serialization - note that we are intentionally using original LogEvent + final Map<String, String> additionalFieldsMap = resolveAdditionalFields(event); + // This class combines LogEvent with AdditionalFields during serialization + return createLogEventWrapperWithAdditionalFields(event, additionalFieldsMap); + } + // No additional fields, return original object + return event; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java new file mode 100644 index 0000000..3b5c435 --- /dev/null +++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +/** + * Classes and interfaces for serializing and deserializing Log4j 2 log events to XML and JSON using the Jackson + * library. + */ +package org.apache.logging.log4j.jackson; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/site/manual/index.md ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/site/manual/index.md b/log4j-layout-jackson/src/site/manual/index.md new file mode 100644 index 0000000..b1d22b6 --- /dev/null +++ b/log4j-layout-jackson/src/site/manual/index.md @@ -0,0 +1,33 @@ +<!-- vim: set syn=markdown : --> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +# Apache Log4j Layout for Jackson module + +As of Log4j 3.0.0, common code for layouts based on Jackson have moved from the existing module logj-core to the new modules log4j-layout-jackson. + +## Requirements + +This module was introduced in Log4j 2.11.0 and requires Jackson. + +Some features may require optional +[dependencies](../runtime-dependencies.html). These dependencies are specified in the +documentation for those features. + +Some Log4j features require external dependencies. +See the [Dependency Tree](dependencies.html#Dependency_Tree) +for the exact list of JAR files needed for these features. http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/site/site.xml ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/site/site.xml b/log4j-layout-jackson/src/site/site.xml new file mode 100644 index 0000000..6d4cddc --- /dev/null +++ b/log4j-layout-jackson/src/site/site.xml @@ -0,0 +1,52 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<project name="Log4j Core" + xmlns="http://maven.apache.org/DECORATION/1.4.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd"> + <body> + <links> + <item name="Apache" href="http://www.apache.org/" /> + <item name="Logging Services" href="http://logging.apache.org/"/> + <item name="Log4j" href="../index.html"/> + </links> + + <!-- Component-specific reports --> + <menu ref="reports"/> + + <!-- Overall Project Info --> + <menu name="Log4j Project Information" img="icon-info-sign"> + <item name="Dependencies" href="../dependencies.html" /> + <item name="Dependency Convergence" href="../dependency-convergence.html" /> + <item name="Dependency Management" href="../dependency-management.html" /> + <item name="Project Team" href="../team-list.html" /> + <item name="Mailing Lists" href="../mail-lists.html" /> + <item name="Issue Tracking" href="../issue-tracking.html" /> + <item name="Project License" href="../license.html" /> + <item name="Source Repository" href="../source-repository.html" /> + <item name="Project Summary" href="../project-summary.html" /> + </menu> + + <menu name="Log4j Project Reports" img="icon-cog"> + <item name="Changes Report" href="../changes-report.html" /> + <item name="JIRA Report" href="../jira-report.html" /> + <item name="Surefire Report" href="../surefire-report.html" /> + <item name="RAT Report" href="../rat-report.html" /> + </menu> + </body> +</project> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java ---------------------------------------------------------------------- diff --git a/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java new file mode 100644 index 0000000..acfae96 --- /dev/null +++ b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java @@ -0,0 +1,97 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache license, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the license for the specific language governing permissions and +* limitations under the license. +*/ +package org.apache.logging.log4j.jackson; + +import java.io.IOException; + +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; +import org.apache.logging.log4j.MarkerManager.Log4jMarker; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; + +/** + * Tests {@link MarkerMixIn}. + * + * This class is in this package to let {@link Log4jMarker} have the least visibility. + */ +public abstract class AbstractMarkerMixInTest { + + private ObjectReader reader; + private ObjectWriter writer; + + protected abstract ObjectMapper newObjectMapper(); + + @Before + public void setUp() { + final ObjectMapper log4jObjectMapper = newObjectMapper(); + writer = log4jObjectMapper.writer(); + reader = log4jObjectMapper.readerFor(Log4jMarker.class); + MarkerManager.clear(); + } + + @Test + public void testNameOnly() throws IOException { + final Marker expected = MarkerManager.getMarker("A"); + final String str = writeValueAsString(expected); + Assert.assertFalse(str.contains("parents")); + final Marker actual = reader.readValue(str); + Assert.assertEquals(expected, actual); + } + + @Test + public void testOneParent() throws IOException { + final Marker expected = MarkerManager.getMarker("A"); + final Marker parent = MarkerManager.getMarker("PARENT_MARKER"); + expected.addParents(parent); + final String str = writeValueAsString(expected); + Assert.assertTrue(str.contains("PARENT_MARKER")); + final Marker actual = reader.readValue(str); + Assert.assertEquals(expected, actual); + } + + @Test + public void testTwoParents() throws IOException { + final Marker expected = MarkerManager.getMarker("A"); + final Marker parent1 = MarkerManager.getMarker("PARENT_MARKER1"); + final Marker parent2 = MarkerManager.getMarker("PARENT_MARKER2"); + expected.addParents(parent1); + expected.addParents(parent2); + final String str = writeValueAsString(expected); + Assert.assertTrue(str.contains("PARENT_MARKER1")); + Assert.assertTrue(str.contains("PARENT_MARKER2")); + final Marker actual = reader.readValue(str); + Assert.assertEquals(expected, actual); + } + + /** + * @param expected + * @return + * @throws JsonProcessingException + */ + private String writeValueAsString(final Marker expected) throws JsonProcessingException { + final String str = writer.writeValueAsString(expected); + // System.out.println(str); + return str; + } +}