* There are two types of logger for command center and common modules specified by annotation of `LogTarget` * Add implementing examples in `sentinel-demo/sentinel-demo-log-logback` * All implementations should support placeholder '{}'master
@@ -15,36 +15,77 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.log; | package com.alibaba.csp.sentinel.log; | ||||
import java.util.logging.Handler; | |||||
import java.util.logging.Level; | |||||
import java.util.logging.Logger; | |||||
import java.util.Iterator; | |||||
import java.util.ServiceLoader; | |||||
/** | /** | ||||
* Logger for command center. | * Logger for command center. | ||||
*/ | */ | ||||
public class CommandCenterLog extends LogBase { | |||||
private static final Logger heliumRecordLog = Logger.getLogger("cspCommandCenterLog"); | |||||
private static final String FILE_NAME = "command-center.log"; | |||||
private static Handler logHandler = null; | |||||
public class CommandCenterLog { | |||||
private static com.alibaba.csp.sentinel.log.Logger log = null; | |||||
static { | static { | ||||
logHandler = makeLogger(FILE_NAME, heliumRecordLog); | |||||
ServiceLoader<Logger> load = ServiceLoader.load(Logger.class); | |||||
Logger logger = null; | |||||
Iterator<Logger> iterator = load.iterator(); | |||||
while (iterator.hasNext()) { | |||||
Logger next = iterator.next(); | |||||
LogTarget annotation = next.getClass().getAnnotation(LogTarget.class); | |||||
if (annotation == null) { | |||||
continue; | |||||
} | |||||
String value = annotation.value().name(); | |||||
if (value.equals(LogType.COMMAND_CENTER_LOG.name())) { | |||||
logger = next; | |||||
break; | |||||
} | |||||
} | |||||
// Use user implementations. | |||||
if (logger != null) { | |||||
log = logger; | |||||
} else { | |||||
// Use default implementations. | |||||
log = new CommandCenterLogLogging(); | |||||
} | |||||
} | |||||
public static void info(String format, Object... arguments) { | |||||
log.info(format, arguments); | |||||
} | |||||
public static void info(String msg, Throwable e) { | |||||
log.info(msg, e); | |||||
} | |||||
public static void warn(String format, Object... arguments) { | |||||
log.warn(format, arguments); | |||||
} | |||||
public static void warn(String msg, Throwable e) { | |||||
log.warn(msg, e); | |||||
} | |||||
public static void trace(String format, Object... arguments) { | |||||
log.trace(format, arguments); | |||||
} | |||||
public static void trace(String msg, Throwable e) { | |||||
log.trace(msg, e); | |||||
} | } | ||||
public static void info(String detail, Object... params) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, detail, params); | |||||
public static void debug(String format, Object... arguments) { | |||||
log.debug(format, arguments); | |||||
} | } | ||||
public static void info(String detail, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, detail, e); | |||||
public static void debug(String msg, Throwable e) { | |||||
log.debug(msg, e); | |||||
} | } | ||||
public static void warn(String detail, Object... params) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, detail, params); | |||||
public static void error(String format, Object... arguments) { | |||||
log.error(format, arguments); | |||||
} | } | ||||
public static void warn(String detail, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, detail, e); | |||||
public static void error(String msg, Throwable e) { | |||||
log.error(msg, e); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,79 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
import java.util.logging.Handler; | |||||
import java.util.logging.Logger; | |||||
/** | |||||
* Default logger implementation. | |||||
* @author xue8 | |||||
*/ | |||||
public class CommandCenterLogLogging extends LogBase implements com.alibaba.csp.sentinel.log.Logger { | |||||
private final Logger heliumRecordLog = Logger.getLogger("cspCommandCenterLog"); | |||||
private final String FILE_NAME = "command-center.log"; | |||||
private final Handler logHandler = makeLogger(FILE_NAME, heliumRecordLog); | |||||
@Override | |||||
public void info(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, format, arguments); | |||||
} | |||||
@Override | |||||
public void info(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, msg, e); | |||||
} | |||||
@Override | |||||
public void warn(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, format, arguments); | |||||
} | |||||
@Override | |||||
public void warn(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, msg, e); | |||||
} | |||||
@Override | |||||
public void trace(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.TRACE, format, arguments); | |||||
} | |||||
@Override | |||||
public void trace(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.TRACE, msg, e); | |||||
} | |||||
@Override | |||||
public void debug(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.DEBUG, format, arguments); | |||||
} | |||||
@Override | |||||
public void debug(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.DEBUG, msg, e); | |||||
} | |||||
@Override | |||||
public void error(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.ERROR, format, arguments); | |||||
} | |||||
@Override | |||||
public void error(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.ERROR, msg, e); | |||||
} | |||||
} |
@@ -0,0 +1,59 @@ | |||||
/* | |||||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
/** | |||||
* Copyright notice | |||||
* This code copy from SLF4J which licensed under the MIT License. | |||||
* | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
/** | |||||
* Holds the results of formatting done by {@link MessageFormatter}. | |||||
* | |||||
* @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; | |||||
} | |||||
} |
@@ -0,0 +1,34 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
/** | |||||
* Logging levels | |||||
* @author xue8 | |||||
*/ | |||||
public class Level extends java.util.logging.Level { | |||||
private static final String defaultBundle = "sun.util.logging.resources.logging"; | |||||
public static final Level ERROR = new Level("ERROR", 1000); | |||||
public static final Level WARNING = new Level("WARNING", 900); | |||||
public static final Level INFO = new Level("INFO", 800); | |||||
public static final Level DEBUG = new Level("DEBUG", 700); | |||||
public static final Level TRACE = new Level("TRACE", 600); | |||||
protected Level(String name, int value) { | |||||
super(name, value, defaultBundle); | |||||
} | |||||
} |
@@ -152,11 +152,10 @@ public class LogBase { | |||||
return; | return; | ||||
} | } | ||||
LoggerUtils.disableOtherHandlers(logger, handler); | LoggerUtils.disableOtherHandlers(logger, handler); | ||||
if (params.length == 0) { | |||||
logger.log(level, detail); | |||||
} else { | |||||
logger.log(level, detail, params); | |||||
} | |||||
FormattingTuple formattingTuple = MessageFormatter.arrayFormat(detail, params); | |||||
String message = formattingTuple.getMessage(); | |||||
logger.log(level, message); | |||||
} | } | ||||
protected static void log(Logger logger, Handler handler, Level level, String detail, Throwable throwable) { | protected static void log(Logger logger, Handler handler, Level level, String detail, Throwable throwable) { | ||||
@@ -0,0 +1,32 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
import java.lang.annotation.*; | |||||
/** | |||||
* @author xue8 | |||||
*/ | |||||
@Retention(RetentionPolicy.RUNTIME) | |||||
@Target(ElementType.TYPE) | |||||
@Documented | |||||
public @interface LogTarget { | |||||
/** | |||||
* Returns the kinds of log type. | |||||
* @return Returns the kinds of log type | |||||
*/ | |||||
LogType value() default LogType.RECORD_LOG; | |||||
} |
@@ -0,0 +1,25 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
/** | |||||
* An enum marks log type. | |||||
* @author xue8 | |||||
*/ | |||||
public enum LogType { | |||||
COMMAND_CENTER_LOG, | |||||
RECORD_LOG, | |||||
} |
@@ -0,0 +1,113 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
/** | |||||
* Provide logger SPI interface. | |||||
* The default implementation is {@link java.util.logging}. | |||||
* | |||||
* Notice, the placeholder only supports the most popular placeholder convention (slf4j). | |||||
* So, if you're not using slf4j, you should create adapters compatible with placeholders "{}". | |||||
* | |||||
* @author xue8 | |||||
*/ | |||||
public interface Logger { | |||||
/** | |||||
* Log a message at the INFO level according to the specified format | |||||
* and arguments. | |||||
* @param format the format string | |||||
* @param arguments a list of arguments | |||||
*/ | |||||
void info(String format, Object... arguments); | |||||
/** | |||||
* Log an exception (throwable) at the INFO level with an | |||||
* accompanying message. | |||||
* | |||||
* @param msg the message accompanying the exception | |||||
* @param e the exception (throwable) to log | |||||
*/ | |||||
void info(String msg, Throwable e); | |||||
/** | |||||
* Log a message at the WARN level according to the specified format | |||||
* and arguments. | |||||
* @param format the format string | |||||
* @param arguments a list of arguments | |||||
*/ | |||||
void warn(String format, Object... arguments); | |||||
/** | |||||
* Log an exception (throwable) at the WARN level with an | |||||
* accompanying message. | |||||
* | |||||
* @param msg the message accompanying the exception | |||||
* @param e the exception (throwable) to log | |||||
*/ | |||||
void warn(String msg, Throwable e); | |||||
/** | |||||
* Log a message at the TRACE level according to the specified format | |||||
* and arguments. | |||||
* @param format the format string | |||||
* @param arguments a list of arguments | |||||
*/ | |||||
void trace(String format, Object... arguments); | |||||
/** | |||||
* Log an exception (throwable) at the TRACE level with an | |||||
* accompanying message. | |||||
* | |||||
* @param msg the message accompanying the exception | |||||
* @param e the exception (throwable) to log | |||||
*/ | |||||
void trace(String msg, Throwable e); | |||||
/** | |||||
* Log a message at the DEBUG level according to the specified format | |||||
* and arguments. | |||||
* @param format the format string | |||||
* @param arguments a list of arguments | |||||
*/ | |||||
void debug(String format, Object... arguments); | |||||
/** | |||||
* Log an exception (throwable) at the DEBUG level with an | |||||
* accompanying message. | |||||
* | |||||
* @param msg the message accompanying the exception | |||||
* @param e the exception (throwable) to log | |||||
*/ | |||||
void debug(String msg, Throwable e); | |||||
/** | |||||
* Log a message at the ERROR level according to the specified format | |||||
* and arguments. | |||||
* @param format the format string | |||||
* @param arguments a list of arguments | |||||
*/ | |||||
void error(String format, Object... arguments); | |||||
/** | |||||
* Log an exception (throwable) at the ERROR level with an | |||||
* accompanying message. | |||||
* | |||||
* @param msg the message accompanying the exception | |||||
* @param e the exception (throwable) to log | |||||
*/ | |||||
void error(String msg, Throwable e); | |||||
} |
@@ -0,0 +1,427 @@ | |||||
/* | |||||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
/** | |||||
* Copyright notice | |||||
* This code copy from SLF4J which licensed under the MIT License. | |||||
* | |||||
*/ | |||||
/** | |||||
* Copyright notice | |||||
* This code copy from SLF4J which licensed under the MIT License. | |||||
* | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
// contributors: lizongbo: proposed special treatment of array parameter values | |||||
// Joern Huxhorn: pointed out double[] omission, suggested deep array copy | |||||
import java.text.MessageFormat; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
/** | |||||
* Formats messages according to very simple substitution rules. Substitutions | |||||
* can be made 1, 2 or more arguments. | |||||
* | |||||
* <p> | |||||
* For example, | |||||
* | |||||
* <pre> | |||||
* MessageFormatter.format("Hi {}.", "there") | |||||
* </pre> | |||||
* | |||||
* will return the string "Hi there.". | |||||
* <p> | |||||
* The {} pair is called the <em>formatting anchor</em>. It serves to designate | |||||
* the location where arguments need to be substituted within the message | |||||
* pattern. | |||||
* <p> | |||||
* In case your message contains the '{' or the '}' character, you do not have | |||||
* to do anything special unless the '}' character immediately follows '{'. For | |||||
* example, | |||||
* | |||||
* <pre> | |||||
* MessageFormatter.format("Set {1,2,3} is not equal to {}.", "1,2"); | |||||
* </pre> | |||||
* | |||||
* will return the string "Set {1,2,3} is not equal to 1,2.". | |||||
* | |||||
* <p> | |||||
* If for whatever reason you need to place the string "{}" in the message | |||||
* without its <em>formatting anchor</em> 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, | |||||
* | |||||
* <pre> | |||||
* MessageFormatter.format("Set \\{} is not equal to {}.", "1,2"); | |||||
* </pre> | |||||
* | |||||
* will return the string "Set {} is not equal to 1,2.". | |||||
* | |||||
* <p> | |||||
* The escaping behavior just described can be overridden by escaping the escape | |||||
* character '\'. Calling | |||||
* | |||||
* <pre> | |||||
* MessageFormatter.format("File name is C:\\\\{}.", "file.zip"); | |||||
* </pre> | |||||
* | |||||
* will return the string "File name is C:\file.zip". | |||||
* | |||||
* <p> | |||||
* 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. | |||||
* | |||||
* <p> | |||||
* 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. | |||||
* <p> | |||||
* For example, | |||||
* | |||||
* <pre> | |||||
* MessageFormatter.format("Hi {}.", "there"); | |||||
* </pre> | |||||
* | |||||
* will return the string "Hi there.". | |||||
* <p> | |||||
* | |||||
* @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. | |||||
* <p> | |||||
* For example, | |||||
* | |||||
* <pre> | |||||
* MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob"); | |||||
* </pre> | |||||
* | |||||
* 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 }); | |||||
} | |||||
static final Throwable getThrowableCandidate(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; | |||||
} | |||||
final public static FormattingTuple arrayFormat(final String messagePattern, final Object[] argArray) { | |||||
Throwable throwableCandidate = getThrowableCandidate(argArray); | |||||
Object[] args = argArray; | |||||
if (throwableCandidate != null) { | |||||
args = trimmedCopy(argArray); | |||||
} | |||||
return arrayFormat(messagePattern, args, throwableCandidate); | |||||
} | |||||
private static Object[] trimmedCopy(Object[] argArray) { | |||||
if (argArray == null || argArray.length == 0) { | |||||
throw new IllegalStateException("non-sensical empty or null argument array"); | |||||
} | |||||
final int trimemdLen = argArray.length - 1; | |||||
Object[] trimmed = new Object[trimemdLen]; | |||||
System.arraycopy(argArray, 0, trimmed, 0, trimemdLen); | |||||
return trimmed; | |||||
} | |||||
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<Object[], Object>()); | |||||
i = j + 2; | |||||
} | |||||
} else { | |||||
// normal case | |||||
sbuf.append(messagePattern, i, j); | |||||
deeplyAppendParameter(sbuf, argArray[L], new HashMap<Object[], Object>()); | |||||
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<Object[], Object> 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) { | |||||
sbuf.append("[FAILED toString()]"); | |||||
} | |||||
} | |||||
private static void objectArrayAppend(StringBuilder sbuf, Object[] a, Map<Object[], Object> 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(']'); | |||||
} | |||||
} |
@@ -15,9 +15,8 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.log; | package com.alibaba.csp.sentinel.log; | ||||
import java.util.logging.Handler; | |||||
import java.util.logging.Level; | |||||
import java.util.logging.Logger; | |||||
import java.util.Iterator; | |||||
import java.util.ServiceLoader; | |||||
/*** | /*** | ||||
* The basic logger for vital events. | * The basic logger for vital events. | ||||
@@ -25,27 +24,71 @@ import java.util.logging.Logger; | |||||
* @author youji.zj | * @author youji.zj | ||||
*/ | */ | ||||
public class RecordLog extends LogBase { | public class RecordLog extends LogBase { | ||||
private static final Logger heliumRecordLog = Logger.getLogger("cspSentinelRecordLog"); | |||||
private static final String FILE_NAME = "sentinel-record.log"; | |||||
private static Handler logHandler = null; | |||||
private static com.alibaba.csp.sentinel.log.Logger log = null; | |||||
static { | static { | ||||
logHandler = makeLogger(FILE_NAME, heliumRecordLog); | |||||
ServiceLoader<Logger> load = ServiceLoader.load(Logger.class); | |||||
Logger logger = null; | |||||
Iterator<Logger> iterator = load.iterator(); | |||||
while (iterator.hasNext()) { | |||||
Logger next = iterator.next(); | |||||
LogTarget annotation = next.getClass().getAnnotation(LogTarget.class); | |||||
if (annotation == null) { | |||||
continue; | |||||
} | |||||
String value = annotation.value().name(); | |||||
if (value.equals(LogType.RECORD_LOG.name())) { | |||||
logger = next; | |||||
break; | |||||
} | |||||
} | |||||
// Use user implementations. | |||||
if (logger != null) { | |||||
log = logger; | |||||
} else { | |||||
// Use default implementations. | |||||
log = new RecordLogLogging(); | |||||
} | |||||
} | } | ||||
public static void info(String detail, Object... params) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, detail, params); | |||||
public static void info(String format, Object... arguments) { | |||||
log.info(format, arguments); | |||||
} | } | ||||
public static void info(String detail, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, detail, e); | |||||
public static void info(String msg, Throwable e) { | |||||
log.info(msg, e); | |||||
} | } | ||||
public static void warn(String detail, Object... params) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, detail, params); | |||||
public static void warn(String format, Object... arguments) { | |||||
log.warn(format, arguments); | |||||
} | } | ||||
public static void warn(String detail, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, detail, e); | |||||
public static void warn(String msg, Throwable e) { | |||||
log.warn(msg, e); | |||||
} | } | ||||
public static void trace(String format, Object... arguments) { | |||||
log.trace(format, arguments); | |||||
} | |||||
public static void trace(String msg, Throwable e) { | |||||
log.trace(msg, e); | |||||
} | |||||
public static void debug(String format, Object... arguments) { | |||||
log.debug(format, arguments); | |||||
} | |||||
public static void debug(String msg, Throwable e) { | |||||
log.debug(msg, e); | |||||
} | |||||
public static void error(String format, Object... arguments) { | |||||
log.error(format, arguments); | |||||
} | |||||
public static void error(String msg, Throwable e) { | |||||
log.error(msg, e); | |||||
} | |||||
} | } |
@@ -0,0 +1,79 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.log; | |||||
import java.util.logging.Handler; | |||||
import java.util.logging.Logger; | |||||
/** | |||||
* Default logger implementation. | |||||
* @author xue8 | |||||
*/ | |||||
public class RecordLogLogging extends LogBase implements com.alibaba.csp.sentinel.log.Logger { | |||||
private final Logger heliumRecordLog = Logger.getLogger("cspSentinelRecordLog"); | |||||
private final String FILE_NAME = "sentinel-record.log"; | |||||
private final Handler logHandler = makeLogger(FILE_NAME, heliumRecordLog); | |||||
@Override | |||||
public void info(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, format, arguments); | |||||
} | |||||
@Override | |||||
public void info(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.INFO, msg, e); | |||||
} | |||||
@Override | |||||
public void warn(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, format, arguments); | |||||
} | |||||
@Override | |||||
public void warn(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.WARNING, msg, e); | |||||
} | |||||
@Override | |||||
public void trace(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.TRACE, format, arguments); | |||||
} | |||||
@Override | |||||
public void trace(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.TRACE, msg, e); | |||||
} | |||||
@Override | |||||
public void debug(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.DEBUG, format, arguments); | |||||
} | |||||
@Override | |||||
public void debug(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.DEBUG, msg, e); | |||||
} | |||||
@Override | |||||
public void error(String format, Object... arguments) { | |||||
log(heliumRecordLog, logHandler, Level.ERROR, format, arguments); | |||||
} | |||||
@Override | |||||
public void error(String msg, Throwable e) { | |||||
log(heliumRecordLog, logHandler, Level.ERROR, msg, e); | |||||
} | |||||
} |
@@ -107,4 +107,14 @@ public class RecordLogTest { | |||||
} | |||||
// Because log only writes into the file, | |||||
// can't read the log(file conflict), so no assertion in this unit test. | |||||
@Test | |||||
public void testMessageFormatter() { | |||||
RecordLog.info("1 2 {} 4 {} 6", "3", "5"); | |||||
RecordLog.info("1 2 {} 4 {} 6", "3"); | |||||
RecordLog.info("1 2 {} 4 {} 6"); | |||||
RecordLog.info("1 2 \\{} 4 {} 6", "5"); | |||||
} | |||||
} |
@@ -36,6 +36,7 @@ | |||||
<module>sentinel-demo-zuul-gateway</module> | <module>sentinel-demo-zuul-gateway</module> | ||||
<module>sentinel-demo-etcd-datasource</module> | <module>sentinel-demo-etcd-datasource</module> | ||||
<module>sentinel-demo-spring-webmvc</module> | <module>sentinel-demo-spring-webmvc</module> | ||||
<module>sentinel-demo-log-logback</module> | |||||
</modules> | </modules> | ||||
<dependencies> | <dependencies> | ||||
@@ -0,0 +1,41 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
<parent> | |||||
<artifactId>sentinel-demo</artifactId> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<version>1.7.2-SNAPSHOT</version> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>sentinel-demo-log-logback</artifactId> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>ch.qos.logback</groupId> | |||||
<artifactId>logback-classic</artifactId> | |||||
<version>1.2.3</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>ch.qos.logback</groupId> | |||||
<artifactId>logback-core</artifactId> | |||||
<version>1.2.3</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>junit</groupId> | |||||
<artifactId>junit</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.github.stefanbirkner</groupId> | |||||
<artifactId>system-rules</artifactId> | |||||
<version>RELEASE</version> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
</dependencies> | |||||
</project> |
@@ -0,0 +1,90 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.demo.log.logback; | |||||
import com.alibaba.csp.sentinel.log.LogTarget; | |||||
import com.alibaba.csp.sentinel.log.LogType; | |||||
import com.alibaba.csp.sentinel.log.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
/** | |||||
* This class is a demo shows how to create a customized logger implementation. | |||||
* | |||||
* <ul> | |||||
* <li>1. Create a class which implements the {@link Logger} SPI interface</li> | |||||
* <li>2. Use a {@link LogTarget} to specify the log type</li> | |||||
* <li>3. Implement your own method </li> | |||||
* <li>4. Add your logger in {@code com.alibaba.csp.sentinel.log.Logger} file which is stored in | |||||
* {@code resources/META-INF/services/} directory </li> | |||||
* </ul> | |||||
* | |||||
* @author xue8 | |||||
*/ | |||||
@LogTarget(value = LogType.COMMAND_CENTER_LOG) | |||||
public class CommandCenterLogLoggerImpl implements Logger { | |||||
private final org.slf4j.Logger logger = LoggerFactory.getLogger("commandCenterLogLogger"); | |||||
@Override | |||||
public void info(String format, Object... arguments) { | |||||
logger.info(format, arguments); | |||||
} | |||||
@Override | |||||
public void info(String msg, Throwable e) { | |||||
logger.info(msg, e); | |||||
} | |||||
@Override | |||||
public void warn(String format, Object... arguments) { | |||||
logger.warn(format, arguments); | |||||
} | |||||
@Override | |||||
public void warn(String msg, Throwable e) { | |||||
logger.warn(msg, e); | |||||
} | |||||
@Override | |||||
public void trace(String format, Object... arguments) { | |||||
logger.trace(format, arguments); | |||||
} | |||||
@Override | |||||
public void trace(String msg, Throwable e) { | |||||
logger.trace(msg, e); | |||||
} | |||||
@Override | |||||
public void debug(String format, Object... arguments) { | |||||
logger.debug(format, arguments); | |||||
} | |||||
@Override | |||||
public void debug(String msg, Throwable e) { | |||||
logger.debug(msg, e); | |||||
} | |||||
@Override | |||||
public void error(String format, Object... arguments) { | |||||
logger.error(format, arguments); | |||||
} | |||||
@Override | |||||
public void error(String msg, Throwable e) { | |||||
logger.error(msg, e); | |||||
} | |||||
} |
@@ -0,0 +1,90 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.demo.log.logback; | |||||
import com.alibaba.csp.sentinel.log.LogTarget; | |||||
import com.alibaba.csp.sentinel.log.LogType; | |||||
import com.alibaba.csp.sentinel.log.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
/** | |||||
* This class is a demo shows how to create a customized logger implementation. | |||||
* | |||||
* <ul> | |||||
* <li>1. Create a class which implements the {@link Logger} SPI interface</li> | |||||
* <li>2. Use a {@link LogTarget} to specify the log type</li> | |||||
* <li>3. Implement your own method </li> | |||||
* <li>4. Add your logger in {@code com.alibaba.csp.sentinel.log.Logger} file which is stored in | |||||
* {@code resources/META-INF/services/} directory </li> | |||||
* </ul> | |||||
* | |||||
* @author xue8 | |||||
*/ | |||||
@LogTarget(value = LogType.RECORD_LOG) | |||||
public class RecordLogLoggerImpl implements Logger { | |||||
private final org.slf4j.Logger logger = LoggerFactory.getLogger("recordLogLogger"); | |||||
@Override | |||||
public void info(String format, Object... arguments) { | |||||
logger.info(format, arguments); | |||||
} | |||||
@Override | |||||
public void info(String msg, Throwable e) { | |||||
logger.info(msg, e); | |||||
} | |||||
@Override | |||||
public void warn(String format, Object... arguments) { | |||||
logger.warn(format, arguments); | |||||
} | |||||
@Override | |||||
public void warn(String msg, Throwable e) { | |||||
logger.warn(msg, e); | |||||
} | |||||
@Override | |||||
public void trace(String format, Object... arguments) { | |||||
logger.trace(format, arguments); | |||||
} | |||||
@Override | |||||
public void trace(String msg, Throwable e) { | |||||
logger.trace(msg, e); | |||||
} | |||||
@Override | |||||
public void debug(String format, Object... arguments) { | |||||
logger.debug(format, arguments); | |||||
} | |||||
@Override | |||||
public void debug(String msg, Throwable e) { | |||||
logger.debug(msg, e); | |||||
} | |||||
@Override | |||||
public void error(String format, Object... arguments) { | |||||
logger.error(format, arguments); | |||||
} | |||||
@Override | |||||
public void error(String msg, Throwable e) { | |||||
logger.error(msg, e); | |||||
} | |||||
} |
@@ -0,0 +1,2 @@ | |||||
com.alibaba.csp.sentinel.demo.log.logback.RecordLogLoggerImpl | |||||
com.alibaba.csp.sentinel.demo.log.logback.CommandCenterLogLoggerImpl |
@@ -0,0 +1,42 @@ | |||||
<?xml version="1.0" encoding="UTF-8" ?> | |||||
<configuration scan="false" scanPeriod="60000" debug="false"> | |||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | |||||
<layout class="ch.qos.logback.classic.PatternLayout"> | |||||
<pattern>%-5level %logger - %msg%n</pattern> | |||||
</layout> | |||||
</appender> | |||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender"> | |||||
<file>sentinel-record.log</file> | |||||
<append>true</append> | |||||
<encoder> | |||||
<pattern>%-5level %logger - %msg%n</pattern> | |||||
</encoder> | |||||
</appender> | |||||
<appender name="FILE2" class="ch.qos.logback.core.FileAppender"> | |||||
<file>sentinel-command-center.log</file> | |||||
<append>true</append> | |||||
<encoder> | |||||
<pattern>%-5level %logger - %msg%n</pattern> | |||||
</encoder> | |||||
</appender> | |||||
<logger name="recordLogLogger" level="trace"> | |||||
<appender-ref ref="STDOUT" /> | |||||
<appender-ref ref="FILE" /> | |||||
</logger> | |||||
<logger name="commandCenterLogLogger" level="trace"> | |||||
<appender-ref ref="STDOUT" /> | |||||
<appender-ref ref="FILE2" /> | |||||
</logger> | |||||
<!--<root level="info">--> | |||||
<!--<appender-ref ref="STDOUT" />--> | |||||
<!--<appender-ref ref="FILE" />--> | |||||
<!--</root>--> | |||||
</configuration> | |||||
@@ -0,0 +1,116 @@ | |||||
/* | |||||
* Copyright 1999-2019 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.demo.log.logback; | |||||
import com.alibaba.csp.sentinel.log.CommandCenterLog; | |||||
import org.junit.Assert; | |||||
import org.junit.Rule; | |||||
import org.junit.Test; | |||||
import org.junit.contrib.java.lang.system.SystemOutRule; | |||||
/** | |||||
* @author xue8 | |||||
*/ | |||||
public class CommandCenterLogTest { | |||||
@Rule | |||||
public SystemOutRule log = new SystemOutRule().enableLog(); | |||||
@Test | |||||
public void testLog() { | |||||
CommandCenterLog.info("init"); | |||||
log.clearLog(); | |||||
int count = 0; | |||||
// info test | |||||
while (count++ < 1000) { | |||||
log.clearLog(); | |||||
CommandCenterLog.info("Count {}", count); | |||||
String str = String.format("INFO commandCenterLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// warn test | |||||
while (count++ < 2000) { | |||||
log.clearLog(); | |||||
CommandCenterLog.warn("Count {}", count); | |||||
String str = String.format("WARN commandCenterLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// trace test | |||||
while (count++ < 3000) { | |||||
log.clearLog(); | |||||
CommandCenterLog.trace("Count {}", count); | |||||
String str = String.format("TRACE commandCenterLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// debug test | |||||
while (count++ < 4000) { | |||||
log.clearLog(); | |||||
CommandCenterLog.debug("Count {}", count); | |||||
String str = String.format("DEBUG commandCenterLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// test error | |||||
while (count++ < 5000) { | |||||
log.clearLog(); | |||||
CommandCenterLog.error("Count {}", count); | |||||
String str = String.format("ERROR commandCenterLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
} | |||||
@Test | |||||
public void testLogException() { | |||||
CommandCenterLog.info("init"); | |||||
log.clearLog(); | |||||
Exception e = new Exception("ex"); | |||||
// info test | |||||
CommandCenterLog.info("Error", e); | |||||
// split the log for test | |||||
String[] logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("INFO commandCenterLogLogger - Error", logSplit[0]); | |||||
// warn test | |||||
log.clearLog(); | |||||
CommandCenterLog.warn("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("WARN commandCenterLogLogger - Error", logSplit[0]); | |||||
// trace test | |||||
log.clearLog(); | |||||
CommandCenterLog.trace("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("TRACE commandCenterLogLogger - Error", logSplit[0]); | |||||
// debug test | |||||
log.clearLog(); | |||||
CommandCenterLog.debug("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("DEBUG commandCenterLogLogger - Error", logSplit[0]); | |||||
// error test | |||||
log.clearLog(); | |||||
CommandCenterLog.error("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("ERROR commandCenterLogLogger - Error", logSplit[0]); | |||||
} | |||||
} |
@@ -0,0 +1,115 @@ | |||||
/* | |||||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed 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 com.alibaba.csp.sentinel.demo.log.logback; | |||||
import com.alibaba.csp.sentinel.log.RecordLog; | |||||
import org.junit.Assert; | |||||
import org.junit.Rule; | |||||
import org.junit.Test; | |||||
import org.junit.contrib.java.lang.system.SystemOutRule; | |||||
/** | |||||
* @author xue8 | |||||
*/ | |||||
public class RecordLogTest { | |||||
@Rule | |||||
public SystemOutRule log = new SystemOutRule().enableLog(); | |||||
@Test | |||||
public void testLog() { | |||||
RecordLog.info("init"); | |||||
log.clearLog(); | |||||
int count = 0; | |||||
// info test | |||||
while (count++ < 1000) { | |||||
log.clearLog(); | |||||
RecordLog.info("Count {}", count); | |||||
String str = String.format("INFO recordLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// warn test | |||||
while (count++ < 2000) { | |||||
log.clearLog(); | |||||
RecordLog.warn("Count {}", count); | |||||
String str = String.format("WARN recordLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// trace test | |||||
while (count++ < 3000) { | |||||
log.clearLog(); | |||||
RecordLog.trace("Count {}", count); | |||||
String str = String.format("TRACE recordLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// debug test | |||||
while (count++ < 4000) { | |||||
log.clearLog(); | |||||
RecordLog.debug("Count {}", count); | |||||
String str = String.format("DEBUG recordLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
// test error | |||||
while (count++ < 5000) { | |||||
log.clearLog(); | |||||
RecordLog.error("Count {}", count); | |||||
String str = String.format("ERROR recordLogLogger - Count %d" + System.lineSeparator(), count); | |||||
Assert.assertEquals(str, log.getLog()); | |||||
} | |||||
} | |||||
@Test | |||||
public void testLogException() { | |||||
RecordLog.info("init"); | |||||
log.clearLog(); | |||||
Exception e = new Exception("ex"); | |||||
// info test | |||||
RecordLog.info("Error", e); | |||||
// split the log for test | |||||
String[] logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("INFO recordLogLogger - Error", logSplit[0]); | |||||
// warn test | |||||
log.clearLog(); | |||||
RecordLog.warn("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("WARN recordLogLogger - Error", logSplit[0]); | |||||
// trace test | |||||
log.clearLog(); | |||||
RecordLog.trace("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("TRACE recordLogLogger - Error", logSplit[0]); | |||||
// debug test | |||||
log.clearLog(); | |||||
RecordLog.debug("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("DEBUG recordLogLogger - Error", logSplit[0]); | |||||
// error test | |||||
log.clearLog(); | |||||
RecordLog.error("Error", e); | |||||
logSplit = log.getLog().split(System.lineSeparator()); | |||||
Assert.assertEquals("ERROR recordLogLogger - Error", logSplit[0]); | |||||
} | |||||
} |