diff --git a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/JBossNettyLoggerFactory.java b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/JBossNettyLoggerFactory.java index 2c4cfd9155936..db0d8b3068fba 100644 --- a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/JBossNettyLoggerFactory.java +++ b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/JBossNettyLoggerFactory.java @@ -1,5 +1,9 @@ package io.quarkus.netty.deployment; +import java.text.MessageFormat; +import java.util.HashSet; +import java.util.Set; + import org.jboss.logging.Logger; import io.netty.util.internal.logging.AbstractInternalLogger; @@ -29,26 +33,43 @@ public boolean isTraceEnabled() { @Override public void trace(String msg) { - log.trace(msg); + if (isTraceEnabled()) { + log.trace(msg); + } } @Override public void trace(String format, Object arg) { - log.tracef(format, arg); + if (isTraceEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arg); + trace0(ft.getMessage(), ft.getThrowable()); + } } @Override public void trace(String format, Object argA, Object argB) { - log.tracef(format, argA, argB); + if (isTraceEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, argA, argB); + trace0(ft.getMessage(), ft.getThrowable()); + } } @Override public void trace(String format, Object... arguments) { - log.tracef(format, arguments); + if (isTraceEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arguments); + trace0(ft.getMessage(), ft.getThrowable()); + } } @Override public void trace(String msg, Throwable t) { + if (isTraceEnabled()) { + trace0(msg, t); + } + } + + private void trace0(String msg, Throwable t) { log.trace(msg, t); } @@ -59,26 +80,43 @@ public boolean isDebugEnabled() { @Override public void debug(String msg) { - log.debug(msg); + if (isDebugEnabled()) { + log.debug(msg); + } } @Override public void debug(String format, Object arg) { - log.debugf(format, arg); + if (isDebugEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arg); + debug0(ft.getMessage(), ft.getThrowable()); + } } @Override public void debug(String format, Object argA, Object argB) { - log.debugf(format, argA, argB); + if (isDebugEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, argA, argB); + debug0(ft.getMessage(), ft.getThrowable()); + } } @Override public void debug(String format, Object... arguments) { - log.debugf(format, arguments); + if (isDebugEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arguments); + debug0(ft.getMessage(), ft.getThrowable()); + } } @Override public void debug(String msg, Throwable t) { + if (isDebugEnabled()) { + debug0(msg, t); + } + } + + private void debug0(String msg, Throwable t) { log.debug(msg, t); } @@ -89,26 +127,43 @@ public boolean isInfoEnabled() { @Override public void info(String msg) { - log.info(msg); + if (isInfoEnabled()) { + log.info(msg); + } } @Override public void info(String format, Object arg) { - log.infof(format, arg); + if (isInfoEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arg); + info0(ft.getMessage(), ft.getThrowable()); + } } @Override public void info(String format, Object argA, Object argB) { - log.infof(format, argA, argB); + if (isInfoEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, argA, argB); + info0(ft.getMessage(), ft.getThrowable()); + } } @Override public void info(String format, Object... arguments) { - log.infof(format, arguments); + if (isInfoEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arguments); + info0(ft.getMessage(), ft.getThrowable()); + } } @Override public void info(String msg, Throwable t) { + if (isInfoEnabled()) { + info0(msg, t); + } + } + + private void info0(String msg, Throwable t) { log.info(msg, t); } @@ -119,26 +174,43 @@ public boolean isWarnEnabled() { @Override public void warn(String msg) { - log.warn(msg); + if (isWarnEnabled()) { + log.warn(msg); + } } @Override public void warn(String format, Object arg) { - log.warnf(format, arg); + if (isWarnEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arg); + warn0(ft.getMessage(), ft.getThrowable()); + } } @Override public void warn(String format, Object... arguments) { - log.warnf(format, arguments); + if (isWarnEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arguments); + warn0(ft.getMessage(), ft.getThrowable()); + } } @Override public void warn(String format, Object argA, Object argB) { - log.warnf(format, argA, argB); + if (isWarnEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, argA, argB); + warn0(ft.getMessage(), ft.getThrowable()); + } } @Override public void warn(String msg, Throwable t) { + if (isWarnEnabled()) { + warn0(msg, t); + } + } + + private void warn0(String msg, Throwable t) { log.warn(msg, t); } @@ -149,29 +221,466 @@ public boolean isErrorEnabled() { @Override public void error(String msg) { - log.error(msg); + if (isErrorEnabled()) { + log.error(msg); + } } @Override public void error(String format, Object arg) { - log.errorf(format, arg); + if (isErrorEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arg); + error0(ft.getMessage(), ft.getThrowable()); + } } @Override public void error(String format, Object argA, Object argB) { - log.errorf(format, argA, argB); + if (isErrorEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, argA, argB); + error0(ft.getMessage(), ft.getThrowable()); + } } @Override public void error(String format, Object... arguments) { - log.errorf(format, arguments); + if (isErrorEnabled()) { + FormattingTuple ft = MessageFormatter.format(format, arguments); + error0(ft.getMessage(), ft.getThrowable()); + } } @Override public void error(String msg, Throwable t) { + if (isErrorEnabled()) { + error0(msg, t); + } + } + + private void error0(String msg, Throwable t) { log.error(msg, t); } } + // MessageFormatter class copied from Netty because its methods are package private + + /* + * Copyright 2013 The Netty Project + * + * The Netty Project 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: + * + * https://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. + */ + + /** + * Formats messages according to very simple substitution rules. Substitutions + * can be made 1, 2 or more arguments. + *
+ * + * For example, + * + * + *+ * MessageFormatter.format("Hi {}.", "there") + *+ * + * will return the string "Hi there.". + * + * The {} pair is called the formatting anchor. It serves to designate + * the location where arguments need to be substituted within the message + * pattern. + * + * In case your message contains the '{' or the '}' character, you do not have + * to do anything special unless the '}' character immediately follows '{'. For + * example, + * + * + *
+ * MessageFormatter.format("Set {1,2,3} is not equal to {}.", "1,2"); + *+ * + * will return the string "Set {1,2,3} is not equal to 1,2.". + * + * + * If for whatever reason you need to place the string "{}" in the message + * without its formatting anchor meaning, then you need to escape the + * '{' character with '\', that is the backslash character. Only the '{' + * character should be escaped. There is no need to escape the '}' character. + * For example, + * + * + *
+ * MessageFormatter.format("Set \\{} is not equal to {}.", "1,2"); + *+ * + * will return the string "Set {} is not equal to 1,2.". + * + * + * The escaping behavior just described can be overridden by escaping the escape + * character '\'. Calling + * + * + *
+ * MessageFormatter.format("File name is C:\\\\{}.", "file.zip"); + *+ * + * will return the string "File name is C:\file.zip". + * + * + * The formatting conventions are different than those of {@link MessageFormat} + * which ships with the Java platform. This is justified by the fact that + * SLF4J's implementation is 10 times faster than that of {@link MessageFormat}. + * This local performance difference is both measurable and significant in the + * larger context of the complete logging processing chain. + * + * + * See also {@link #format(String, Object)}, + * {@link #format(String, Object, Object)} and + * {@link #arrayFormat(String, Object[])} methods for more details. + */ + public static final class MessageFormatter { + private static final String DELIM_STR = "{}"; + private static final char ESCAPE_CHAR = '\\'; + + /** + * Performs single argument substitution for the 'messagePattern' passed as + * parameter. + * + * For example, + * + * + *
+ * MessageFormatter.format("Hi {}.", "there"); + *+ * + * will return the string "Hi there.". + * + * + * @param messagePattern The message pattern which will be parsed and formatted + * @param arg The argument to be substituted in place of the formatting anchor + * @return The formatted message + */ + static FormattingTuple format(String messagePattern, Object arg) { + return arrayFormat(messagePattern, new Object[] { arg }); + } + + /** + * Performs a two argument substitution for the 'messagePattern' passed as + * parameter. + * + * For example, + * + * + *
+ * MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob"); + *+ * + * will return the string "Hi Alice. My name is Bob.". + * + * @param messagePattern The message pattern which will be parsed and formatted + * @param argA The argument to be substituted in place of the first formatting + * anchor + * @param argB The argument to be substituted in place of the second formatting + * anchor + * @return The formatted message + */ + static FormattingTuple format(final String messagePattern, + Object argA, Object argB) { + return arrayFormat(messagePattern, new Object[] { argA, argB }); + } + + /** + * Same principle as the {@link #format(String, Object)} and + * {@link #format(String, Object, Object)} methods except that any number of + * arguments can be passed in an array. + * + * @param messagePattern The message pattern which will be parsed and formatted + * @param argArray An array of arguments to be substituted in place of formatting + * anchors + * @return The formatted message + */ + static FormattingTuple arrayFormat(final String messagePattern, + final Object[] argArray) { + if (argArray == null || argArray.length == 0) { + return new FormattingTuple(messagePattern, null); + } + + int lastArrIdx = argArray.length - 1; + Object lastEntry = argArray[lastArrIdx]; + Throwable throwable = lastEntry instanceof Throwable ? (Throwable) lastEntry : null; + + if (messagePattern == null) { + return new FormattingTuple(null, throwable); + } + + int j = messagePattern.indexOf(DELIM_STR); + if (j == -1) { + // this is a simple string + return new FormattingTuple(messagePattern, throwable); + } + + StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50); + int i = 0; + int L = 0; + do { + boolean notEscaped = j == 0 || messagePattern.charAt(j - 1) != ESCAPE_CHAR; + if (notEscaped) { + // normal case + sbuf.append(messagePattern, i, j); + } else { + sbuf.append(messagePattern, i, j - 1); + // check that escape char is not is escaped: "abc x:\\{}" + notEscaped = j >= 2 && messagePattern.charAt(j - 2) == ESCAPE_CHAR; + } + + i = j + 2; + if (notEscaped) { + deeplyAppendParameter(sbuf, argArray[L], null); + L++; + if (L > lastArrIdx) { + break; + } + } else { + sbuf.append(DELIM_STR); + } + j = messagePattern.indexOf(DELIM_STR, i); + } while (j != -1); + + // append the characters following the last {} pair. + sbuf.append(messagePattern, i, messagePattern.length()); + return new FormattingTuple(sbuf.toString(), L <= lastArrIdx ? throwable : null); + } + + // special treatment of array values was suggested by 'lizongbo' + private static void deeplyAppendParameter(StringBuilder sbuf, Object o, + Set