Use custom JSON string encoding
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/838f14c5 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/838f14c5 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/838f14c5 Branch: refs/heads/LOG4J2-1356 Commit: 838f14c5b5ec6acc2c95c900cb8122695471cbe3 Parents: 8dc5bd4 Author: Mikael Ståldal <[email protected]> Authored: Fri Apr 8 14:03:43 2016 +0200 Committer: Mikael Ståldal <[email protected]> Committed: Fri Apr 8 14:03:43 2016 +0200 ---------------------------------------------------------------------- .../logging/log4j/core/layout/GelfLayout.java | 23 +++-- .../logging/log4j/core/util/JsonUtils.java | 93 ++++++++++++++++++++ pom.xml | 6 +- 3 files changed, 107 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/838f14c5/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java index 424cfff..8dae8c3 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java @@ -16,7 +16,6 @@ */ package org.apache.logging.log4j.core.layout; -import com.fasterxml.jackson.core.io.JsonStringEncoder; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Layout; import org.apache.logging.log4j.core.LogEvent; @@ -27,6 +26,7 @@ import org.apache.logging.log4j.core.config.plugins.PluginElement; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.net.Severity; import org.apache.logging.log4j.core.util.Constants; +import org.apache.logging.log4j.core.util.JsonUtils; import org.apache.logging.log4j.core.util.KeyValuePair; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.status.StatusLogger; @@ -177,42 +177,41 @@ public final class GelfLayout extends AbstractStringLayout { } private StringBuilder toText(LogEvent event, StringBuilder builder, boolean gcFree) { - final JsonStringEncoder jsonEncoder = JsonStringEncoder.getInstance(); builder.append('{'); builder.append("\"version\":\"1.1\","); builder.append("\"host\":\""); - jsonEncoder.quoteAsString(toNullSafeString(host), builder); + JsonUtils.quoteAsString(toNullSafeString(host), builder); builder.append(QC); builder.append("\"timestamp\":").append(formatTimestamp(event.getTimeMillis())).append(C); builder.append("\"level\":").append(formatLevel(event.getLevel())).append(C); if (event.getThreadName() != null) { builder.append("\"_thread\":\""); - jsonEncoder.quoteAsString(event.getThreadName(), builder); + JsonUtils.quoteAsString(event.getThreadName(), builder); builder.append(QC); } if (event.getLoggerName() != null) { builder.append("\"_logger\":\""); - jsonEncoder.quoteAsString(event.getLoggerName(), builder); + JsonUtils.quoteAsString(event.getLoggerName(), builder); builder.append(QC); } for (final KeyValuePair additionalField : additionalFields) { builder.append(QU); - jsonEncoder.quoteAsString(additionalField.getKey(), builder); + JsonUtils.quoteAsString(additionalField.getKey(), builder); builder.append("\":\""); - jsonEncoder.quoteAsString(toNullSafeString(additionalField.getValue()), builder); + JsonUtils.quoteAsString(toNullSafeString(additionalField.getValue()), builder); builder.append(QC); } for (final Map.Entry<String, String> entry : event.getContextMap().entrySet()) { builder.append(QU); - jsonEncoder.quoteAsString(entry.getKey(), builder); + JsonUtils.quoteAsString(entry.getKey(), builder); builder.append("\":\""); - jsonEncoder.quoteAsString(toNullSafeString(entry.getValue()), builder); + JsonUtils.quoteAsString(toNullSafeString(entry.getValue()), builder); builder.append(QC); } if (event.getThrown() != null) { builder.append("\"full_message\":\""); - jsonEncoder.quoteAsString(formatThrowable(event.getThrown()), builder); + JsonUtils.quoteAsString(formatThrowable(event.getThrown()), builder); builder.append(QC); } @@ -221,9 +220,9 @@ public final class GelfLayout extends AbstractStringLayout { if (gcFree && message instanceof StringBuilderFormattable) { StringBuilder messageBuffer = getMessageStringBuilder(); ((StringBuilderFormattable)message).formatTo(messageBuffer); - jsonEncoder.quoteAsString(messageBuffer, builder); + JsonUtils.quoteAsString(messageBuffer, builder); } else { - jsonEncoder.quoteAsString(toNullSafeString(message.getFormattedMessage()), builder); + JsonUtils.quoteAsString(toNullSafeString(message.getFormattedMessage()), builder); } builder.append(Q); builder.append('}'); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/838f14c5/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java new file mode 100644 index 0000000..bca5417 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java @@ -0,0 +1,93 @@ +/* + * 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.core.util; + +import com.fasterxml.jackson.core.io.CharTypes; + +/** + * This class is borrowed from <a href="https://github.com/FasterXML/jackson-core">Jackson</a>. + */ +public final class JsonUtils { + + private final static char[] HC = CharTypes.copyHexChars(); + + /** + * Temporary buffer used for composing quote/escape sequences + */ + private final static ThreadLocal<char[]> _qbufLocal = new ThreadLocal<>(); + + private static char[] getQBuf() { + char[] _qbuf = _qbufLocal.get(); + if (_qbuf == null) { + _qbuf = new char[6]; + _qbuf[0] = '\\'; + _qbuf[2] = '0'; + _qbuf[3] = '0'; + + _qbufLocal.set(_qbuf); + } + return _qbuf; + } + + /** + * Quote text contents using JSON standard quoting, and append results to a supplied {@link StringBuilder}. + */ + public static void quoteAsString(CharSequence input, StringBuilder output) { + final char[] qbuf = getQBuf(); + final int[] escCodes = CharTypes.get7BitOutputEscapes(); + final int escCodeCount = escCodes.length; + int inPtr = 0; + final int inputLen = input.length(); + + outer: + while (inPtr < inputLen) { + tight_loop: + while (true) { + char c = input.charAt(inPtr); + if (c < escCodeCount && escCodes[c] != 0) { + break tight_loop; + } + output.append(c); + if (++inPtr >= inputLen) { + break outer; + } + } + // something to escape; 2 or 6-char variant? + char d = input.charAt(inPtr++); + int escCode = escCodes[d]; + int length = (escCode < 0) + ? _appendNumeric(d, qbuf) + : _appendNamed(escCode, qbuf); + + output.append(qbuf, 0, length); + } + } + + private static int _appendNumeric(int value, char[] qbuf) { + qbuf[1] = 'u'; + // We know it's a control char, so only the last 2 chars are non-0 + qbuf[4] = HC[value >> 4]; + qbuf[5] = HC[value & 0xF]; + return 6; + } + + private static int _appendNamed(int esc, char[] qbuf) { + qbuf[1] = (char) esc; + return 2; + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/838f14c5/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 1f42907..c0e54d2 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,7 @@ <slf4jVersion>1.7.13</slf4jVersion> <logbackVersion>1.1.3</logbackVersion> <jackson1Version>1.9.13</jackson1Version> - <jackson2Version>2.8.0-SNAPSHOT</jackson2Version> + <jackson2Version>2.7.3</jackson2Version> <springVersion>3.2.13.RELEASE</springVersion> <flumeVersion>1.6.0</flumeVersion> <disruptorVersion>3.3.4</disruptorVersion> @@ -542,13 +542,13 @@ <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-yaml</artifactId> - <version>2.7.3</version> + <version>${jackson2Version}</version> <optional>true</optional> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> - <version>2.7.3</version> + <version>${jackson2Version}</version> <optional>true</optional> </dependency> <dependency>
