diff --git a/.licenserc.yaml b/.licenserc.yaml index 22235dda53..0e8b7409d8 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -102,6 +102,8 @@ header: - 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java' - 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java' - 'dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/**' + - 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java' + - 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java' comment: on-failure diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java index 511dd8a66d..f55646a6b2 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java @@ -30,6 +30,14 @@ public interface Logger { */ void trace(String msg); + /** + * Logs a message with trace log level. + * + * @param msg log this message + * @param arguments a list of arguments + */ + void trace(String msg, Object... arguments); + /** * Logs an error with trace log level. * @@ -52,6 +60,14 @@ public interface Logger { */ void debug(String msg); + /** + * Logs a message with debug log level. + * + * @param msg log this message + * @param arguments a list of arguments + */ + void debug(String msg, Object... arguments); + /** * Logs an error with debug log level. * @@ -74,6 +90,14 @@ public interface Logger { */ void info(String msg); + /** + * Logs a message with info log level. + * + * @param msg log this message + * @param arguments a list of arguments + */ + void info(String msg, Object... arguments); + /** * Logs an error with info log level. * @@ -96,6 +120,14 @@ public interface Logger { */ void warn(String msg); + /** + * Logs a message with warn log level. + * + * @param msg log this message + * @param arguments a list of arguments + */ + void warn(String msg, Object... arguments); + /** * Logs a message with warn log level. * @@ -118,6 +150,14 @@ public interface Logger { */ void error(String msg); + /** + * Logs a message with error log level. + * + * @param msg log this message + * @param arguments a list of arguments + */ + void error(String msg, Object... arguments); + /** * Logs an error with error log level. * diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java new file mode 100644 index 0000000000..53c89c75c5 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.apache.dubbo.common.logger.helpers; + +/** + * Holds the results of formatting done by {@link MessageFormatter}. + * This is a copy of org.slf4j.helpers.FormattingTuple from slf4j-api. + * + * @author Joern Huxhorn + */ +public class FormattingTuple { + + static public FormattingTuple NULL = new FormattingTuple(null); + + private String message; + private Throwable throwable; + private Object[] argArray; + + public FormattingTuple(String message) { + this(message, null, null); + } + + public FormattingTuple(String message, Object[] argArray, Throwable throwable) { + this.message = message; + this.throwable = throwable; + this.argArray = argArray; + } + + public String getMessage() { + return message; + } + + public Object[] getArgArray() { + return argArray; + } + + public Throwable getThrowable() { + return throwable; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java new file mode 100644 index 0000000000..18986acdc8 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.apache.dubbo.common.logger.helpers; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +// contributors: lizongbo: proposed special treatment of array parameter values +// Joern Huxhorn: pointed out double[] omission, suggested deep array copy + +/** + * This is a copy of org.slf4j.helpers.MessageFormatter from slf4j-api. + * 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. + * + * @author Ceki Gülcü + * @author Joern Huxhorn + */ +final public class MessageFormatter { + static final char DELIM_START = '{'; + static final char DELIM_STOP = '}'; + 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 + */ + final public 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 arg1 The argument to be substituted in place of the first formatting + * anchor + * @param arg2 The argument to be substituted in place of the second formatting + * anchor + * @return The formatted message + */ + final public static FormattingTuple format(final String messagePattern, Object arg1, Object arg2) { + return arrayFormat(messagePattern, new Object[]{arg1, arg2}); + } + + + final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray) { + Throwable throwableCandidate = MessageFormatter.getThrowableCandidate(argArray); + Object[] args = argArray; + if (throwableCandidate != null) { + args = MessageFormatter.trimmedCopy(argArray); + } + return arrayFormat(messagePattern, args, throwableCandidate); + } + + final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray, Throwable throwable) { + + if (messagePattern == null) { + return new FormattingTuple(null, argArray, throwable); + } + + if (argArray == null) { + return new FormattingTuple(messagePattern); + } + + int i = 0; + int j; + // use string builder for better multicore performance + StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50); + + int L; + for (L = 0; L < argArray.length; L++) { + + j = messagePattern.indexOf(DELIM_STR, i); + + if (j == -1) { + // no more variables + if (i == 0) { // this is a simple string + return new FormattingTuple(messagePattern, argArray, throwable); + } else { // add the tail string which contains no variables and return + // the result. + sbuf.append(messagePattern, i, messagePattern.length()); + return new FormattingTuple(sbuf.toString(), argArray, throwable); + } + } else { + if (isEscapedDelimeter(messagePattern, j)) { + if (!isDoubleEscaped(messagePattern, j)) { + L--; // DELIM_START was escaped, thus should not be incremented + sbuf.append(messagePattern, i, j - 1); + sbuf.append(DELIM_START); + i = j + 1; + } else { + // The escape character preceding the delimiter start is + // itself escaped: "abc x:\\{}" + // we have to consume one backward slash + sbuf.append(messagePattern, i, j - 1); + deeplyAppendParameter(sbuf, argArray[L], new HashMap()); + i = j + 2; + } + } else { + // normal case + sbuf.append(messagePattern, i, j); + deeplyAppendParameter(sbuf, argArray[L], new HashMap()); + i = j + 2; + } + } + } + // append the characters following the last {} pair. + sbuf.append(messagePattern, i, messagePattern.length()); + return new FormattingTuple(sbuf.toString(), argArray, throwable); + } + + final static boolean isEscapedDelimeter(String messagePattern, int delimeterStartIndex) { + + if (delimeterStartIndex == 0) { + return false; + } + char potentialEscape = messagePattern.charAt(delimeterStartIndex - 1); + if (potentialEscape == ESCAPE_CHAR) { + return true; + } else { + return false; + } + } + + final static boolean isDoubleEscaped(String messagePattern, int delimeterStartIndex) { + if (delimeterStartIndex >= 2 && messagePattern.charAt(delimeterStartIndex - 2) == ESCAPE_CHAR) { + return true; + } else { + return false; + } + } + + // special treatment of array values was suggested by 'lizongbo' + private static void deeplyAppendParameter(StringBuilder sbuf, Object o, Map seenMap) { + if (o == null) { + sbuf.append("null"); + return; + } + if (!o.getClass().isArray()) { + safeObjectAppend(sbuf, o); + } else { + // check for primitive array types because they + // unfortunately cannot be cast to Object[] + if (o instanceof boolean[]) { + booleanArrayAppend(sbuf, (boolean[]) o); + } else if (o instanceof byte[]) { + byteArrayAppend(sbuf, (byte[]) o); + } else if (o instanceof char[]) { + charArrayAppend(sbuf, (char[]) o); + } else if (o instanceof short[]) { + shortArrayAppend(sbuf, (short[]) o); + } else if (o instanceof int[]) { + intArrayAppend(sbuf, (int[]) o); + } else if (o instanceof long[]) { + longArrayAppend(sbuf, (long[]) o); + } else if (o instanceof float[]) { + floatArrayAppend(sbuf, (float[]) o); + } else if (o instanceof double[]) { + doubleArrayAppend(sbuf, (double[]) o); + } else { + objectArrayAppend(sbuf, (Object[]) o, seenMap); + } + } + } + + private static void safeObjectAppend(StringBuilder sbuf, Object o) { + try { + String oAsString = o.toString(); + sbuf.append(oAsString); + } catch (Throwable t) { + System.err.println("SLF4J: Failed toString() invocation on an object of type [" + o.getClass().getName() + "]"); + System.err.println("Reported exception:"); + StackTraceElement[] stackTrace = t.getStackTrace(); + StringBuilder stackBuilder = new StringBuilder(); + for (StackTraceElement traceElement : stackTrace) { + stackBuilder.append("\tat ").append(traceElement).append("\n"); + } + System.err.println(stackBuilder); + sbuf.append("[FAILED toString()]"); + } + + } + + private static void objectArrayAppend(StringBuilder sbuf, Object[] a, Map seenMap) { + sbuf.append('['); + if (!seenMap.containsKey(a)) { + seenMap.put(a, null); + final int len = a.length; + for (int i = 0; i < len; i++) { + deeplyAppendParameter(sbuf, a[i], seenMap); + if (i != len - 1) + sbuf.append(", "); + } + // allow repeats in siblings + seenMap.remove(a); + } else { + sbuf.append("..."); + } + sbuf.append(']'); + } + + private static void booleanArrayAppend(StringBuilder sbuf, boolean[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void byteArrayAppend(StringBuilder sbuf, byte[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void charArrayAppend(StringBuilder sbuf, char[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void shortArrayAppend(StringBuilder sbuf, short[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void intArrayAppend(StringBuilder sbuf, int[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void longArrayAppend(StringBuilder sbuf, long[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void floatArrayAppend(StringBuilder sbuf, float[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + private static void doubleArrayAppend(StringBuilder sbuf, double[] a) { + sbuf.append('['); + final int len = a.length; + for (int i = 0; i < len; i++) { + sbuf.append(a[i]); + if (i != len - 1) + sbuf.append(", "); + } + sbuf.append(']'); + } + + /** + * Helper method to determine if an {@link Object} array contains a {@link Throwable} as last element + * + * @param argArray The arguments off which we want to know if it contains a {@link Throwable} as last element + * @return if the last {@link Object} in argArray is a {@link Throwable} this method will return it, + * otherwise it returns null + */ + public static Throwable getThrowableCandidate(final Object[] argArray) { + if (argArray == null || argArray.length == 0) { + return null; + } + + final Object lastEntry = argArray[argArray.length - 1]; + if (lastEntry instanceof Throwable) { + return (Throwable) lastEntry; + } + + return null; + } + + /** + * Helper method to get all but the last element of an array + * + * @param argArray The arguments from which we want to remove the last element + * @return a copy of the array without the last element + */ + public static Object[] trimmedCopy(final Object[] argArray) { + if (argArray == null || argArray.length == 0) { + throw new IllegalStateException("non-sensical empty or null argument array"); + } + + final int trimmedLen = argArray.length - 1; + + Object[] trimmed = new Object[trimmedLen]; + + if (trimmedLen > 0) { + System.arraycopy(argArray, 0, trimmed, 0, trimmedLen); + } + + return trimmed; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java index 5021b3f721..690f198360 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLogger.java @@ -19,6 +19,8 @@ package org.apache.dubbo.common.logger.jcl; import org.apache.dubbo.common.logger.Logger; import org.apache.commons.logging.Log; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; /** * Adaptor to commons logging, depends on commons-logging.jar. For more information about commons logging, pls. refer to @@ -37,6 +39,12 @@ public class JclLogger implements Logger { logger.trace(msg); } + @Override + public void trace(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.trace(ft.getMessage(), ft.getThrowable()); + } + @Override public void trace(Throwable e) { logger.trace(e); @@ -52,6 +60,12 @@ public class JclLogger implements Logger { logger.debug(msg); } + @Override + public void debug(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.debug(ft.getMessage(), ft.getThrowable()); + } + @Override public void debug(Throwable e) { logger.debug(e); @@ -67,6 +81,12 @@ public class JclLogger implements Logger { logger.info(msg); } + @Override + public void info(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.info(ft.getMessage(), ft.getThrowable()); + } + @Override public void info(Throwable e) { logger.info(e); @@ -82,6 +102,12 @@ public class JclLogger implements Logger { logger.warn(msg); } + @Override + public void warn(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.warn(ft.getMessage(), ft.getThrowable()); + } + @Override public void warn(Throwable e) { logger.warn(e); @@ -97,6 +123,12 @@ public class JclLogger implements Logger { logger.error(msg); } + @Override + public void error(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.error(ft.getMessage(), ft.getThrowable()); + } + @Override public void error(Throwable e) { logger.error(e); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLogger.java index 5f778885f5..3e1c7194a8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLogger.java @@ -17,6 +17,8 @@ package org.apache.dubbo.common.logger.jdk; import org.apache.dubbo.common.logger.Logger; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; import java.util.logging.Level; @@ -33,6 +35,12 @@ public class JdkLogger implements Logger { logger.log(Level.FINER, msg); } + @Override + public void trace(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(Level.FINER, ft.getMessage(), ft.getThrowable()); + } + @Override public void trace(Throwable e) { logger.log(Level.FINER, e.getMessage(), e); @@ -48,6 +56,12 @@ public class JdkLogger implements Logger { logger.log(Level.FINE, msg); } + @Override + public void debug(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(Level.FINE, ft.getMessage(), ft.getThrowable()); + } + @Override public void debug(Throwable e) { logger.log(Level.FINE, e.getMessage(), e); @@ -63,6 +77,12 @@ public class JdkLogger implements Logger { logger.log(Level.INFO, msg); } + @Override + public void info(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(Level.INFO, ft.getMessage(), ft.getThrowable()); + } + @Override public void info(String msg, Throwable e) { logger.log(Level.INFO, msg, e); @@ -73,6 +93,12 @@ public class JdkLogger implements Logger { logger.log(Level.WARNING, msg); } + @Override + public void warn(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + @Override public void warn(String msg, Throwable e) { logger.log(Level.WARNING, msg, e); @@ -83,6 +109,12 @@ public class JdkLogger implements Logger { logger.log(Level.SEVERE, msg); } + @Override + public void error(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + @Override public void error(String msg, Throwable e) { logger.log(Level.SEVERE, msg, e); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLogger.java index 8007c981e3..ed621224ce 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLogger.java @@ -20,6 +20,8 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.support.FailsafeLogger; import org.apache.log4j.Level; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; public class Log4jLogger implements Logger { @@ -36,6 +38,12 @@ public class Log4jLogger implements Logger { logger.log(FQCN, Level.TRACE, msg, null); } + @Override + public void trace(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(FQCN, Level.TRACE, ft.getMessage(), ft.getThrowable()); + } + @Override public void trace(Throwable e) { logger.log(FQCN, Level.TRACE, e == null ? null : e.getMessage(), e); @@ -51,6 +59,12 @@ public class Log4jLogger implements Logger { logger.log(FQCN, Level.DEBUG, msg, null); } + @Override + public void debug(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable()); + } + @Override public void debug(Throwable e) { logger.log(FQCN, Level.DEBUG, e == null ? null : e.getMessage(), e); @@ -66,6 +80,12 @@ public class Log4jLogger implements Logger { logger.log(FQCN, Level.INFO, msg, null); } + @Override + public void info(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(FQCN, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + @Override public void info(Throwable e) { logger.log(FQCN, Level.INFO, e == null ? null : e.getMessage(), e); @@ -81,6 +101,12 @@ public class Log4jLogger implements Logger { logger.log(FQCN, Level.WARN, msg, null); } + @Override + public void warn(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable()); + } + @Override public void warn(Throwable e) { logger.log(FQCN, Level.WARN, e == null ? null : e.getMessage(), e); @@ -96,6 +122,12 @@ public class Log4jLogger implements Logger { logger.log(FQCN, Level.ERROR, msg, null); } + @Override + public void error(String msg, Object... arguments) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + logger.log(FQCN, Level.ERROR, ft.getMessage(), ft.getThrowable()); + } + @Override public void error(Throwable e) { logger.log(FQCN, Level.ERROR, e == null ? null : e.getMessage(), e); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2Logger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2Logger.java index ed40b65766..f0a1ab773d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2Logger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2Logger.java @@ -31,6 +31,11 @@ public class Log4j2Logger implements Logger { logger.trace(msg); } + @Override + public void trace(String msg, Object... arguments) { + logger.trace(msg, arguments); + } + @Override public void trace(Throwable e) { logger.trace(e == null ? null : e.getMessage(), e); @@ -46,6 +51,11 @@ public class Log4j2Logger implements Logger { logger.debug(msg); } + @Override + public void debug(String msg, Object... arguments) { + logger.debug(msg, arguments); + } + @Override public void debug(Throwable e) { logger.debug(e == null ? null : e.getMessage(), e); @@ -61,6 +71,11 @@ public class Log4j2Logger implements Logger { logger.info(msg); } + @Override + public void info(String msg, Object... arguments) { + logger.info(msg, arguments); + } + @Override public void info(Throwable e) { logger.info(e == null ? null : e.getMessage(), e); @@ -76,6 +91,11 @@ public class Log4j2Logger implements Logger { logger.warn(msg); } + @Override + public void warn(String msg, Object... arguments) { + logger.warn(msg, arguments); + } + @Override public void warn(Throwable e) { logger.warn(e == null ? null : e.getMessage(), e); @@ -91,6 +111,11 @@ public class Log4j2Logger implements Logger { logger.error(msg); } + @Override + public void error(String msg, Object... arguments) { + logger.error(msg, arguments); + } + @Override public void error(Throwable e) { logger.error(e == null ? null : e.getMessage(), e); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java index d212cb183d..7b8ca7b3c7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLogger.java @@ -19,6 +19,8 @@ package org.apache.dubbo.common.logger.slf4j; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.support.FailsafeLogger; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; import org.slf4j.spi.LocationAwareLogger; public class Slf4jLogger implements Logger { @@ -47,6 +49,16 @@ public class Slf4jLogger implements Logger { logger.trace(msg); } + @Override + public void trace(String msg, Object... arguments) { + if (locationAwareLogger != null) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, ft.getArgArray(), ft.getThrowable()); + return; + } + logger.trace(msg, arguments); + } + @Override public void trace(Throwable e) { if (locationAwareLogger != null) { @@ -74,6 +86,16 @@ public class Slf4jLogger implements Logger { logger.debug(msg); } + @Override + public void debug(String msg, Object... arguments) { + if (locationAwareLogger != null) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, ft.getArgArray(), ft.getThrowable()); + return; + } + logger.debug(msg, arguments); + } + @Override public void debug(Throwable e) { if (locationAwareLogger != null) { @@ -101,6 +123,16 @@ public class Slf4jLogger implements Logger { logger.info(msg); } + @Override + public void info(String msg, Object... arguments) { + if (locationAwareLogger != null) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, ft.getArgArray(), ft.getThrowable()); + return; + } + logger.info(msg, arguments); + } + @Override public void info(Throwable e) { if (locationAwareLogger != null) { @@ -128,6 +160,16 @@ public class Slf4jLogger implements Logger { logger.warn(msg); } + @Override + public void warn(String msg, Object... arguments) { + if (locationAwareLogger != null) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, ft.getArgArray(), ft.getThrowable()); + return; + } + logger.warn(msg, arguments); + } + @Override public void warn(Throwable e) { if (locationAwareLogger != null) { @@ -155,6 +197,16 @@ public class Slf4jLogger implements Logger { logger.error(msg); } + @Override + public void error(String msg, Object... arguments) { + if (locationAwareLogger != null) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, arguments); + locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, ft.getArgArray(), ft.getThrowable()); + return; + } + logger.error(msg, arguments); + } + @Override public void error(Throwable e) { if (locationAwareLogger != null) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeLogger.java index 66e369f83b..79ab6ff640 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/support/FailsafeLogger.java @@ -83,6 +83,17 @@ public class FailsafeLogger implements Logger { } } + @Override + public void trace(String msg, Object... arguments) { + if (disabled) { + return; + } + try { + logger.trace(appendContextMessage(msg), arguments); + } catch (Throwable t) { + } + } + @Override public void debug(String msg, Throwable e) { if (disabled) { @@ -116,6 +127,17 @@ public class FailsafeLogger implements Logger { } } + @Override + public void debug(String msg, Object... arguments) { + if (disabled) { + return; + } + try { + logger.debug(appendContextMessage(msg), arguments); + } catch (Throwable t) { + } + } + @Override public void info(String msg, Throwable e) { if (disabled) { @@ -138,6 +160,17 @@ public class FailsafeLogger implements Logger { } } + @Override + public void info(String msg, Object... arguments) { + if (disabled) { + return; + } + try { + logger.info(appendContextMessage(msg), arguments); + } catch (Throwable t) { + } + } + @Override public void warn(String msg, Throwable e) { if (disabled) { @@ -160,6 +193,17 @@ public class FailsafeLogger implements Logger { } } + @Override + public void warn(String msg, Object... arguments) { + if (disabled) { + return; + } + try { + logger.warn(appendContextMessage(msg), arguments); + } catch (Throwable t) { + } + } + @Override public void error(String msg, Throwable e) { if (disabled) { @@ -182,6 +226,17 @@ public class FailsafeLogger implements Logger { } } + @Override + public void error(String msg, Object... arguments) { + if (disabled) { + return; + } + try { + logger.error(appendContextMessage(msg), arguments); + } catch (Throwable t) { + } + } + @Override public void error(Throwable e) { if (disabled) { diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java index e834433c94..e4d8d8551c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerTest.java @@ -56,7 +56,13 @@ class LoggerTest { logger.warn("warn"); logger.info("info"); logger.debug("debug"); - logger.trace("info"); + logger.trace("trace"); + + logger.error("error:{}", "arg1"); + logger.warn("warn:{}", "arg1"); + logger.info("info:{}", "arg1"); + logger.debug("debug:{}", "arg1"); + logger.trace("trace:{}", "arg1"); logger.error(new Exception("error")); logger.warn(new Exception("warn")); @@ -69,6 +75,12 @@ class LoggerTest { logger.info("info", new Exception("info")); logger.debug("debug", new Exception("debug")); logger.trace("trace", new Exception("trace")); + + logger.error("error:{}","arg1", new Exception("error")); + logger.warn("warn:{}", "arg1", new Exception("warn")); + logger.info("info:{}", "arg1", new Exception("info")); + logger.debug("debug:{}", "arg1", new Exception("debug")); + logger.trace("trace:{}", "arg1", new Exception("trace")); } @ParameterizedTest diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java index 931e34313e..ce8f5b5fe0 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerTest.java @@ -19,10 +19,7 @@ package org.apache.dubbo.common.logger.slf4j; import org.junit.jupiter.api.Test; import org.slf4j.spi.LocationAwareLogger; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.internal.verification.VerificationModeFactory.times; @@ -34,14 +31,22 @@ class Slf4jLoggerTest { Slf4jLogger logger = new Slf4jLogger(locationAwareLogger); logger.error("error"); - logger.warn("warn"); logger.info("info"); logger.debug("debug"); logger.trace("info"); verify(locationAwareLogger, times(5)).log(isNull(), anyString(), - anyInt(), anyString(), isNull(), isNull()); + anyInt(), anyString(), isNull(), isNull()); + + logger.error("error:{}", "arg1"); + logger.warn("warn:{}", "arg1"); + logger.info("info:{}", "arg1"); + logger.debug("debug:{}", "arg1"); + logger.trace("info:{}", "arg1"); + + verify(locationAwareLogger, times(5)).log(isNull(), anyString(), + anyInt(), anyString(), eq(new String[]{"arg1"}), isNull()); logger.error(new Exception("error")); logger.warn(new Exception("warn")); @@ -56,6 +61,15 @@ class Slf4jLoggerTest { logger.trace("trace", new Exception("trace")); verify(locationAwareLogger, times(10)).log(isNull(), anyString(), - anyInt(), anyString(), isNull(), any(Throwable.class)); + anyInt(), anyString(), isNull(), any(Throwable.class)); + + logger.error("error:{}","arg1", new Exception("error")); + logger.warn("warn:{}", "arg1", new Exception("warn")); + logger.info("info:{}", "arg1", new Exception("info")); + logger.debug("debug:{}", "arg1", new Exception("debug")); + logger.trace("trace:{}", "arg1", new Exception("trace")); + + verify(locationAwareLogger, times(5)).log(isNull(), anyString(), + anyInt(), anyString(), eq(new String[]{"arg1"}), any(Throwable.class)); } } diff --git a/dubbo-common/src/test/resources/log4j.xml b/dubbo-common/src/test/resources/log4j.xml index 183ab37ebe..377b2a65dc 100644 --- a/dubbo-common/src/test/resources/log4j.xml +++ b/dubbo-common/src/test/resources/log4j.xml @@ -34,7 +34,7 @@ - + diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java index 27ee5908e7..bd059ffb2a 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java @@ -105,7 +105,7 @@ class ConfigValidationUtilsTest { config.setName("testName"); config.setQosEnable(false); mock.validateApplicationConfig(config); - verify(loggerMock, never()).warn(any(), any()); + verify(loggerMock, never()).warn(any(), any(Throwable.class)); config.setQosEnable(true); mock.validateApplicationConfig(config); diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/MockLogger.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/MockLogger.java index 162f72de0b..e2a80dd6cb 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/MockLogger.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/MockLogger.java @@ -38,6 +38,11 @@ public class MockLogger implements Logger { } + @Override + public void trace(String msg, Object... arguments) { + + } + @Override public void trace(Throwable e) { @@ -53,6 +58,11 @@ public class MockLogger implements Logger { } + @Override + public void debug(String msg, Object... arguments) { + + } + @Override public void debug(Throwable e) { @@ -68,6 +78,11 @@ public class MockLogger implements Logger { } + @Override + public void info(String msg, Object... arguments) { + + } + @Override public void info(Throwable e) { @@ -83,6 +98,11 @@ public class MockLogger implements Logger { } + @Override + public void warn(String msg, Object... arguments) { + + } + @Override public void warn(Throwable e) { @@ -98,6 +118,11 @@ public class MockLogger implements Logger { } + @Override + public void error(String msg, Object... arguments) { + + } + @Override public void error(Throwable e) { diff --git a/pom.xml b/pom.xml index f8bee0e59f..00655eedd8 100644 --- a/pom.xml +++ b/pom.xml @@ -368,6 +368,8 @@ **/org/apache/dubbo/rpc/protocol/tri/TriHttp2RemoteFlowController.java, **/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java, **/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java, + **/org/apache/dubbo/common/logger/helpers/FormattingTuple.java, + **/org/apache/dubbo/common/logger/helpers/MessageFormatter.java, **/istio/v1/auth/**/*, **/com/google/rpc/*, **/generated/**/*, @@ -536,6 +538,10 @@ License|BSD|3-Clause BSD License|The New BSD License + + **/org/apache/dubbo/common/logger/helpers/FormattingTuple.java, + **/org/apache/dubbo/common/logger/helpers/MessageFormatter.java +