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.
+ *
+ *
+ * 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.
+ *
+ *
+ * @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