Flexible loggers' support through SPI mechanism with name `com.alibaba.csp.sentinel.log.Logger` (#1265)
* 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 '{}'
This commit is contained in:
parent
c1ff9135ee
commit
5f203aa79f
|
|
@ -15,36 +15,77 @@
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
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 {
|
||||
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 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 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;
|
||||
}
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
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.
|
||||
|
|
@ -25,27 +24,71 @@ import java.util.logging.Logger;
|
|||
* @author youji.zj
|
||||
*/
|
||||
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 {
|
||||
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-etcd-datasource</module>
|
||||
<module>sentinel-demo-spring-webmvc</module>
|
||||
<module>sentinel-demo-log-logback</module>
|
||||
</modules>
|
||||
|
||||
<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]);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue