Polish logging SPI related code and add general JUL adapter for Logger SPI (#1338)

* Move the legacy JUL methods from LogBase to BaseJulLogger.
* Add a JavaLoggingAdapter as the general JUL adapter for the Logger SPI, which makes it convenient to use (as the default logger).
* Add LoggerSpiProvider to resolve Logger SPI.
* Polish the logback demo.

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
Eric Zhao 2020-03-16 10:00:46 +08:00 committed by GitHub
parent 22df09b427
commit 624d19d4ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 443 additions and 455 deletions

View File

@ -15,77 +15,73 @@
*/
package com.alibaba.csp.sentinel.log;
import java.util.Iterator;
import java.util.ServiceLoader;
import com.alibaba.csp.sentinel.log.jul.JavaLoggingAdapter;
/**
* Logger for command center.
*
* @author Eric Zhao
*/
public class CommandCenterLog {
private static com.alibaba.csp.sentinel.log.Logger log = null;
public static final String LOGGER_NAME = "sentinelCommandCenterLogger";
public static final String DEFAULT_LOG_FILENAME = "command-center.log";
private static com.alibaba.csp.sentinel.log.Logger logger = null;
static {
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;
try {
// Load user-defined logger implementation first.
logger = LoggerSpiProvider.getLogger(LOGGER_NAME);
if (logger == null) {
// If no customized loggers are provided, we use the default logger based on JUL.
logger = new JavaLoggingAdapter(LOGGER_NAME, DEFAULT_LOG_FILENAME);
}
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();
} catch (Throwable t) {
System.err.println("Error: failed to initialize Sentinel CommandCenterLog");
t.printStackTrace();
}
}
public static void info(String format, Object... arguments) {
log.info(format, arguments);
logger.info(format, arguments);
}
public static void info(String msg, Throwable e) {
log.info(msg, e);
logger.info(msg, e);
}
public static void warn(String format, Object... arguments) {
log.warn(format, arguments);
logger.warn(format, arguments);
}
public static void warn(String msg, Throwable e) {
log.warn(msg, e);
logger.warn(msg, e);
}
public static void trace(String format, Object... arguments) {
log.trace(format, arguments);
logger.trace(format, arguments);
}
public static void trace(String msg, Throwable e) {
log.trace(msg, e);
logger.trace(msg, e);
}
public static void debug(String format, Object... arguments) {
log.debug(format, arguments);
logger.debug(format, arguments);
}
public static void debug(String msg, Throwable e) {
log.debug(msg, e);
logger.debug(msg, e);
}
public static void error(String format, Object... arguments) {
log.error(format, arguments);
logger.error(format, arguments);
}
public static void error(String msg, Throwable e) {
log.error(msg, e);
logger.error(msg, e);
}
private CommandCenterLog() {}
}

View File

@ -1,79 +0,0 @@
/*
* 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);
}
}

View File

@ -15,19 +15,14 @@
*/
package com.alibaba.csp.sentinel.log;
import com.alibaba.csp.sentinel.util.PidUtil;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.alibaba.csp.sentinel.util.ConfigUtil.addSeparator;
/**
* <p>The base class for logging.</p>
* <p>The base config class for logging.</p>
*
* <p>
* The default log base directory is {@code ${user.home}/logs/csp/}. We can use the {@link #LOG_DIR}
@ -36,7 +31,8 @@ import static com.alibaba.csp.sentinel.util.ConfigUtil.addSeparator;
* In this case, {@link #LOG_NAME_USE_PID} property could be configured as "true" to turn on this switch.
* </p>
*
* @author leyou
* @author Carpenter Lee
* @author Eric Zhao
*/
public class LogBase {
@ -66,15 +62,15 @@ public class LogBase {
static {
try {
initialize();
initializeDefault();
loadProperties();
} catch (Throwable t) {
System.err.println("[LogBase] FATAL ERROR when initializing log class");
System.err.println("[LogBase] FATAL ERROR when initializing logging config");
t.printStackTrace();
}
}
private static void initialize() {
private static void initializeDefault() {
logNameUsePid = false;
logOutputType = LOG_OUTPUT_TYPE_FILE;
logBaseDir = addSeparator(System.getProperty(USER_HOME)) + DIR_NAME + File.separator;
@ -104,7 +100,6 @@ public class LogBase {
}
System.out.println("INFO: log base dir is: " + logBaseDir);
String usePid = properties.getProperty(LOG_NAME_USE_PID);
logNameUsePid = "true".equalsIgnoreCase(usePid);
System.out.println("INFO: log name use pid is: " + logNameUsePid);
@ -147,64 +142,4 @@ public class LogBase {
return logCharSet;
}
protected static void log(Logger logger, Handler handler, Level level, String detail, Object... params) {
if (detail == null) {
return;
}
LoggerUtils.disableOtherHandlers(logger, handler);
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) {
if (detail == null) {
return;
}
LoggerUtils.disableOtherHandlers(logger, handler);
logger.log(level, detail, throwable);
}
protected static Handler makeLogger(String logName, Logger heliumRecordLog) {
CspFormatter formatter = new CspFormatter();
Handler handler = null;
// Create handler according to logOutputType, set formatter to CspFormatter, set encoding to LOG_CHARSET
switch (logOutputType) {
case LOG_OUTPUT_TYPE_FILE:
String fileName = LogBase.getLogBaseDir() + logName;
if (isLogNameUsePid()) {
fileName += ".pid" + PidUtil.getPid();
}
try {
handler = new DateFileLogHandler(fileName + ".%d", 1024 * 1024 * 200, 4, true);
handler.setFormatter(formatter);
handler.setEncoding(logCharSet);
} catch (IOException e) {
e.printStackTrace();
}
break;
case LOG_OUTPUT_TYPE_CONSOLE:
try {
handler = new ConsoleHandler();
handler.setFormatter(formatter);
handler.setEncoding(logCharSet);
} catch (IOException e) {
e.printStackTrace();
}
break;
default:
break;
}
if (handler != null) {
LoggerUtils.disableOtherHandlers(heliumRecordLog, handler);
}
heliumRecordLog.setLevel(Level.ALL);
return handler;
}
}

View File

@ -19,14 +19,16 @@ import java.lang.annotation.*;
/**
* @author xue8
* @since 1.7.2
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface LogTarget {
/**
* Returns the kinds of log type.
* @return Returns the kinds of log type
* Returns the logger name.
*
* @return the logger name. Record logger by default
*/
LogType value() default LogType.RECORD_LOG;
String value() default RecordLog.LOGGER_NAME;
}

View File

@ -1,25 +0,0 @@
/*
* 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,
}

View File

@ -16,18 +16,19 @@
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 "{}".
* <p>The universal logger SPI interface.</p>
* <p>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 "{}".</p>
*
* @author xue8
* @since 1.7.2
*/
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
*/
@ -45,6 +46,7 @@ public interface Logger {
/**
* 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
*/
@ -62,6 +64,7 @@ public interface Logger {
/**
* 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
*/
@ -79,6 +82,7 @@ public interface Logger {
/**
* 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
*/
@ -96,6 +100,7 @@ public interface Logger {
/**
* 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
*/

View File

@ -0,0 +1,72 @@
/*
* Copyright 1999-2020 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.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
import com.alibaba.csp.sentinel.util.StringUtil;
/**
* SPI provider of Sentinel {@link Logger}.
*
* @author Eric Zhao
* @since 1.7.2
*/
public final class LoggerSpiProvider {
private static final Map<String, Logger> LOGGER_MAP = new HashMap<>();
static {
// NOTE: this class SHOULD NOT depend on any other Sentinel classes
// except the util classes to avoid circular dependency.
try {
resolveLoggers();
} catch (Throwable t) {
System.err.println("Failed to resolve Sentinel Logger SPI");
t.printStackTrace();
}
}
public static Logger getLogger(String name) {
if (name == null) {
return null;
}
return LOGGER_MAP.get(name);
}
private static void resolveLoggers() {
// NOTE: Here we cannot use {@code SpiLoader} directly because it depends on the RecordLog.
ServiceLoader<Logger> loggerLoader = ServiceLoader.load(Logger.class);
for (Logger logger : loggerLoader) {
LogTarget annotation = logger.getClass().getAnnotation(LogTarget.class);
if (annotation == null) {
continue;
}
String name = annotation.value();
// Load first encountered logger if multiple loggers are associated with the same name.
if (StringUtil.isNotBlank(name) && !LOGGER_MAP.containsKey(name)) {
LOGGER_MAP.put(name, logger);
System.out.println("Sentinel Logger SPI loaded for <" + name + ">: "
+ logger.getClass().getCanonicalName());
}
}
}
private LoggerSpiProvider() {}
}

View File

@ -1,55 +0,0 @@
/*
* 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.log;
import java.util.logging.Handler;
import java.util.logging.Logger;
/**
* Util class for logger.
*/
class LoggerUtils {
/**
* Remove all current handlers from the logger and attach it with the given log handler.
*
* @param logger logger
* @param handler the log handler
*/
static void disableOtherHandlers(Logger logger, Handler handler) {
if (logger == null) {
return;
}
synchronized (logger) {
Handler[] handlers = logger.getHandlers();
if (handlers == null) {
return;
}
if (handlers.length == 1 && handlers[0].equals(handler)) {
return;
}
logger.setUseParentHandlers(false);
// Remove all current handlers.
for (Handler h : handlers) {
logger.removeHandler(h);
}
// Attach the given handler.
logger.addHandler(handler);
}
}
}

View File

@ -15,80 +15,74 @@
*/
package com.alibaba.csp.sentinel.log;
import java.util.Iterator;
import java.util.ServiceLoader;
import com.alibaba.csp.sentinel.log.jul.JavaLoggingAdapter;
/***
* The basic logger for vital events.
/**
* The basic biz logger of Sentinel.
*
* @author youji.zj
* @author Eric Zhao
*/
public class RecordLog extends LogBase {
private static com.alibaba.csp.sentinel.log.Logger log = null;
public class RecordLog {
public static final String LOGGER_NAME = "sentinelRecordLogger";
public static final String DEFAULT_LOG_FILENAME = "sentinel-record.log";
private static com.alibaba.csp.sentinel.log.Logger logger = null;
static {
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;
try {
// Load user-defined logger implementation first.
logger = LoggerSpiProvider.getLogger(LOGGER_NAME);
if (logger == null) {
// If no customized loggers are provided, we use the default logger based on JUL.
logger = new JavaLoggingAdapter(LOGGER_NAME, DEFAULT_LOG_FILENAME);
}
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();
} catch (Throwable t) {
System.err.println("Error: failed to initialize Sentinel RecordLog");
t.printStackTrace();
}
}
public static void info(String format, Object... arguments) {
log.info(format, arguments);
logger.info(format, arguments);
}
public static void info(String msg, Throwable e) {
log.info(msg, e);
logger.info(msg, e);
}
public static void warn(String format, Object... arguments) {
log.warn(format, arguments);
logger.warn(format, arguments);
}
public static void warn(String msg, Throwable e) {
log.warn(msg, e);
logger.warn(msg, e);
}
public static void trace(String format, Object... arguments) {
log.trace(format, arguments);
logger.trace(format, arguments);
}
public static void trace(String msg, Throwable e) {
log.trace(msg, e);
logger.trace(msg, e);
}
public static void debug(String format, Object... arguments) {
log.debug(format, arguments);
logger.debug(format, arguments);
}
public static void debug(String msg, Throwable e) {
log.debug(msg, e);
logger.debug(msg, e);
}
public static void error(String format, Object... arguments) {
log.error(format, arguments);
logger.error(format, arguments);
}
public static void error(String msg, Throwable e) {
log.error(msg, e);
logger.error(msg, e);
}
private RecordLog() {}
}

View File

@ -1,79 +0,0 @@
/*
* 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);
}
}

View File

@ -0,0 +1,126 @@
/*
* 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.jul;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.alibaba.csp.sentinel.log.LogBase;
import com.alibaba.csp.sentinel.util.PidUtil;
import static com.alibaba.csp.sentinel.log.LogBase.LOG_OUTPUT_TYPE_CONSOLE;
import static com.alibaba.csp.sentinel.log.LogBase.LOG_OUTPUT_TYPE_FILE;
/**
* The default logger based on java.util.logging.
*
* @author Eric Zhao
* @since 1.7.2
*/
public class BaseJulLogger {
protected void log(Logger logger, Handler handler, Level level, String detail, Object... params) {
if (detail == null) {
return;
}
disableOtherHandlers(logger, handler);
// Compatible with slf4j placeholder format "{}".
FormattingTuple formattingTuple = MessageFormatter.arrayFormat(detail, params);
String message = formattingTuple.getMessage();
logger.log(level, message);
}
protected void log(Logger logger, Handler handler, Level level, String detail, Throwable throwable) {
if (detail == null) {
return;
}
disableOtherHandlers(logger, handler);
logger.log(level, detail, throwable);
}
protected Handler makeLoggingHandler(String logName, Logger heliumRecordLog) {
CspFormatter formatter = new CspFormatter();
String logCharSet = LogBase.getLogCharset();
Handler handler = null;
// Create handler according to logOutputType, set formatter to CspFormatter, set encoding to LOG_CHARSET
switch (LogBase.getLogOutputType()) {
case LOG_OUTPUT_TYPE_FILE:
String fileName = LogBase.getLogBaseDir() + logName;
if (LogBase.isLogNameUsePid()) {
fileName += ".pid" + PidUtil.getPid();
}
try {
handler = new DateFileLogHandler(fileName + ".%d", 1024 * 1024 * 200, 4, true);
handler.setFormatter(formatter);
handler.setEncoding(logCharSet);
} catch (IOException e) {
e.printStackTrace();
}
break;
case LOG_OUTPUT_TYPE_CONSOLE:
try {
handler = new ConsoleHandler();
handler.setFormatter(formatter);
handler.setEncoding(logCharSet);
} catch (IOException e) {
e.printStackTrace();
}
break;
default:
break;
}
if (handler != null) {
disableOtherHandlers(heliumRecordLog, handler);
}
heliumRecordLog.setLevel(Level.ALL);
return handler;
}
/**
* Remove all current handlers from the logger and attach it with the given log handler.
*
* @param logger logger
* @param handler the log handler
*/
static void disableOtherHandlers(Logger logger, Handler handler) {
if (logger == null) {
return;
}
synchronized (logger) {
Handler[] handlers = logger.getHandlers();
if (handlers == null) {
return;
}
if (handlers.length == 1 && handlers[0].equals(handler)) {
return;
}
logger.setUseParentHandlers(false);
// Remove all current handlers.
for (Handler h : handlers) {
logger.removeHandler(h);
}
// Attach the given handler.
logger.addHandler(handler);
}
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.log;
package com.alibaba.csp.sentinel.log.jul;
import java.io.UnsupportedEncodingException;
import java.util.logging.*;

View File

@ -10,7 +10,7 @@
* 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;
package com.alibaba.csp.sentinel.log.jul;
import java.io.PrintWriter;
import java.io.StringWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.log;
package com.alibaba.csp.sentinel.log.jul;
import java.io.File;
import java.io.IOException;

View File

@ -14,12 +14,8 @@
* limitations under the License.
*/
/**
* Copyright notice
* This code copy from SLF4J which licensed under the MIT License.
*
*/
package com.alibaba.csp.sentinel.log;
// Copyright notice: This code was copied from SLF4J which licensed under the MIT License.
package com.alibaba.csp.sentinel.log.jul;
/**
* Holds the results of formatting done by {@link MessageFormatter}.

View File

@ -0,0 +1,104 @@
/*
* 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.jul;
import java.util.logging.Handler;
import com.alibaba.csp.sentinel.log.Logger;
import com.alibaba.csp.sentinel.util.AssertUtil;
/**
* JUL adapter for Sentinel {@link Logger} SPI.
*
* @author Eric Zhao
* @since 1.7.2
*/
public class JavaLoggingAdapter extends BaseJulLogger implements Logger {
private final String loggerName;
private final String fileNamePattern;
private final java.util.logging.Logger julLogger;
private final Handler logHandler;
public JavaLoggingAdapter(String loggerName, String fileNamePattern) {
AssertUtil.assertNotBlank(loggerName, "loggerName cannot be blank");
AssertUtil.assertNotBlank(fileNamePattern, "fileNamePattern cannot be blank");
this.loggerName = loggerName;
this.fileNamePattern = fileNamePattern;
this.julLogger = java.util.logging.Logger.getLogger(loggerName);
this.logHandler = makeLoggingHandler(fileNamePattern, julLogger);
}
@Override
public void info(String format, Object... arguments) {
log(julLogger, logHandler, Level.INFO, format, arguments);
}
@Override
public void info(String msg, Throwable e) {
log(julLogger, logHandler, Level.INFO, msg, e);
}
@Override
public void warn(String format, Object... arguments) {
log(julLogger, logHandler, Level.WARNING, format, arguments);
}
@Override
public void warn(String msg, Throwable e) {
log(julLogger, logHandler, Level.WARNING, msg, e);
}
@Override
public void trace(String format, Object... arguments) {
log(julLogger, logHandler, Level.TRACE, format, arguments);
}
@Override
public void trace(String msg, Throwable e) {
log(julLogger, logHandler, Level.TRACE, msg, e);
}
@Override
public void debug(String format, Object... arguments) {
log(julLogger, logHandler, Level.DEBUG, format, arguments);
}
@Override
public void debug(String msg, Throwable e) {
log(julLogger, logHandler, Level.DEBUG, msg, e);
}
@Override
public void error(String format, Object... arguments) {
log(julLogger, logHandler, Level.ERROR, format, arguments);
}
@Override
public void error(String msg, Throwable e) {
log(julLogger, logHandler, Level.ERROR, msg, e);
}
public String getLoggerName() {
return loggerName;
}
public String getFileNamePattern() {
return fileNamePattern;
}
}

View File

@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.log;
package com.alibaba.csp.sentinel.log.jul;
/**
* Logging levels
* JUL logging levels.
*
* @author xue8
*/
public class Level extends java.util.logging.Level {

View File

@ -14,18 +14,8 @@
* 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;
// Copyright notice: This code was copied from SLF4J which licensed under the MIT License.
package com.alibaba.csp.sentinel.log.jul;
// contributors: lizongbo: proposed special treatment of array parameter values

View File

@ -42,15 +42,15 @@ import com.alibaba.csp.sentinel.log.RecordLog;
* <li>every metric file is accompanied with an index file, which file name is {@code ${metricFileName}.idx}</li>
* </ol>
*
* @author leyou
* @author Carpenter Lee
*/
public class MetricWriter {
private static final String CHARSET = SentinelConfig.charset();
public static final String METRIC_BASE_DIR = RecordLog.getLogBaseDir();
public static final String METRIC_BASE_DIR = LogBase.getLogBaseDir();
/**
* Note: {@link MetricFileNameComparator}'s implementation relays on the metric file name,
* we should be careful when changing the metric file name.
* Note: {@link MetricFileNameComparator}'s implementation relies on the metric file name,
* so we should be careful when changing the metric file name.
*
* @see #formMetricFileName(String, int)
*/

View File

@ -114,7 +114,7 @@ public final class SpiLoader {
SpiOrderWrapper<T> w = null;
for (T spi : serviceLoader) {
int order = SpiOrderResolver.resolveOrder(spi);
RecordLog.info("[SpiLoader] Found {0} SPI: {1} with order " + order, clazz.getSimpleName(),
RecordLog.info("[SpiLoader] Found {} SPI: {} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
if (w == null || order < w.order) {
w = new SpiOrderWrapper<>(order, spi);
@ -181,7 +181,7 @@ public final class SpiLoader {
int order = SpiOrderResolver.resolveOrder(spi);
// Since SPI is lazy initialized in ServiceLoader, we use online sort algorithm here.
SpiOrderResolver.insertSorted(orderWrappers, spi, order);
RecordLog.info("[SpiLoader] Found {0} SPI: {1} with order " + order, clazz.getSimpleName(),
RecordLog.info("[SpiLoader] Found {} SPI: {} with order " + order, clazz.getSimpleName(),
spi.getClass().getCanonicalName());
}
List<T> list = new ArrayList<>();

View File

@ -54,7 +54,7 @@ public class RecordLogTest {
System.setProperty(LogBase.LOG_DIR, newLogBase);
RecordLog.info("testChangeLogBase");
String logFileName = RecordLog.getLogBaseDir();
String logFileName = LogBase.getLogBaseDir();
Assert.assertTrue(newLogBase.equals(logFileName));
File[] files = new File(logFileName).listFiles();
assertTrue(files != null && files.length > 0);
@ -65,7 +65,7 @@ public class RecordLogTest {
@Test
public void testLogBaseDir() {
assertTrue(RecordLog.getLogBaseDir().startsWith(System.getProperty("user.home")));
assertTrue(LogBase.getLogBaseDir().startsWith(System.getProperty("user.home")));
}
public void testLogNameNotUsePid() {

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.log;
package com.alibaba.csp.sentinel.log.jul;
import org.junit.Test;
@ -22,6 +22,9 @@ import java.io.PrintStream;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import com.alibaba.csp.sentinel.log.jul.ConsoleHandler;
import com.alibaba.csp.sentinel.log.jul.CspFormatter;
import static org.junit.Assert.*;
/**

View File

@ -21,7 +21,7 @@ public class EagleEyeLogUtilTest {
public void testWriteLog() throws Exception {
EagleEyeLogUtil.log("resourceName", "BlockException", "app1", "origin", 1);
final File file = new File(RecordLog.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME);
final File file = new File(LogBase.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME);
await().timeout(2, TimeUnit.SECONDS)
.until(new Callable<File>() {
@Override
@ -42,7 +42,7 @@ public class EagleEyeLogUtilTest {
EagleEyeLogUtil.log("resourceName", "BlockException", "app1", "origin", 1);
final File file = new File(RecordLog.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME);
final File file = new File(LogBase.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME);
await().timeout(2, TimeUnit.SECONDS)
.until(new Callable<File>() {
@Override
@ -51,7 +51,7 @@ public class EagleEyeLogUtilTest {
}
}, FileMatchers.anExistingFile());
Assert.assertTrue(file.getAbsolutePath().startsWith(newLogBase));
deleteLogDir(new File(RecordLog.getLogBaseDir()));
deleteLogDir(new File(LogBase.getLogBaseDir()));
}
private void deleteLogDir(File logDirFile) {

View File

@ -12,12 +12,16 @@
<artifactId>sentinel-demo-log-logback</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-common</artifactId>
</dependency>
<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>

View File

@ -15,8 +15,8 @@
*/
package com.alibaba.csp.sentinel.demo.log.logback;
import com.alibaba.csp.sentinel.log.CommandCenterLog;
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;
@ -33,9 +33,10 @@ import org.slf4j.LoggerFactory;
*
* @author xue8
*/
@LogTarget(value = LogType.COMMAND_CENTER_LOG)
@LogTarget(value = CommandCenterLog.LOGGER_NAME)
public class CommandCenterLogLoggerImpl implements Logger {
private final org.slf4j.Logger logger = LoggerFactory.getLogger("commandCenterLogLogger");
private final org.slf4j.Logger logger = LoggerFactory.getLogger(CommandCenterLog.LOGGER_NAME);
@Override
public void info(String format, Object... arguments) {

View File

@ -16,8 +16,9 @@
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 com.alibaba.csp.sentinel.log.RecordLog;
import org.slf4j.LoggerFactory;
/**
@ -33,9 +34,10 @@ import org.slf4j.LoggerFactory;
*
* @author xue8
*/
@LogTarget(value = LogType.RECORD_LOG)
@LogTarget(value = RecordLog.LOGGER_NAME)
public class RecordLogLoggerImpl implements Logger {
private final org.slf4j.Logger logger = LoggerFactory.getLogger("recordLogLogger");
private final org.slf4j.Logger logger = LoggerFactory.getLogger(RecordLog.LOGGER_NAME);
@Override
public void info(String format, Object... arguments) {

View File

@ -22,21 +22,16 @@
</encoder>
</appender>
<logger name="recordLogLogger" level="trace">
<logger name="sentinelRecordLogger" level="trace">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
<logger name="commandCenterLogLogger" level="trace">
<logger name="sentinelCommandCenterLogger" level="trace">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE2" />
</logger>
<!--<root level="info">-->
<!--<appender-ref ref="STDOUT" />-->
<!--<appender-ref ref="FILE" />-->
<!--</root>-->
</configuration>

View File

@ -38,7 +38,7 @@ public class CommandCenterLogTest {
while (count++ < 1000) {
log.clearLog();
CommandCenterLog.info("Count {}", count);
String str = String.format("INFO commandCenterLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("INFO sentinelCommandCenterLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -46,7 +46,7 @@ public class CommandCenterLogTest {
while (count++ < 2000) {
log.clearLog();
CommandCenterLog.warn("Count {}", count);
String str = String.format("WARN commandCenterLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("WARN sentinelCommandCenterLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -54,7 +54,7 @@ public class CommandCenterLogTest {
while (count++ < 3000) {
log.clearLog();
CommandCenterLog.trace("Count {}", count);
String str = String.format("TRACE commandCenterLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("TRACE sentinelCommandCenterLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -62,7 +62,7 @@ public class CommandCenterLogTest {
while (count++ < 4000) {
log.clearLog();
CommandCenterLog.debug("Count {}", count);
String str = String.format("DEBUG commandCenterLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("DEBUG sentinelCommandCenterLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -70,7 +70,7 @@ public class CommandCenterLogTest {
while (count++ < 5000) {
log.clearLog();
CommandCenterLog.error("Count {}", count);
String str = String.format("ERROR commandCenterLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("ERROR sentinelCommandCenterLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
}
@ -85,31 +85,31 @@ public class CommandCenterLogTest {
CommandCenterLog.info("Error", e);
// split the log for test
String[] logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("INFO commandCenterLogLogger - Error", logSplit[0]);
Assert.assertEquals("INFO sentinelCommandCenterLogger - Error", logSplit[0]);
// warn test
log.clearLog();
CommandCenterLog.warn("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("WARN commandCenterLogLogger - Error", logSplit[0]);
Assert.assertEquals("WARN sentinelCommandCenterLogger - Error", logSplit[0]);
// trace test
log.clearLog();
CommandCenterLog.trace("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("TRACE commandCenterLogLogger - Error", logSplit[0]);
Assert.assertEquals("TRACE sentinelCommandCenterLogger - Error", logSplit[0]);
// debug test
log.clearLog();
CommandCenterLog.debug("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("DEBUG commandCenterLogLogger - Error", logSplit[0]);
Assert.assertEquals("DEBUG sentinelCommandCenterLogger - Error", logSplit[0]);
// error test
log.clearLog();
CommandCenterLog.error("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("ERROR commandCenterLogLogger - Error", logSplit[0]);
Assert.assertEquals("ERROR sentinelCommandCenterLogger - Error", logSplit[0]);
}

View File

@ -38,7 +38,7 @@ public class RecordLogTest {
while (count++ < 1000) {
log.clearLog();
RecordLog.info("Count {}", count);
String str = String.format("INFO recordLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("INFO sentinelRecordLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -46,7 +46,7 @@ public class RecordLogTest {
while (count++ < 2000) {
log.clearLog();
RecordLog.warn("Count {}", count);
String str = String.format("WARN recordLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("WARN sentinelRecordLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -54,7 +54,7 @@ public class RecordLogTest {
while (count++ < 3000) {
log.clearLog();
RecordLog.trace("Count {}", count);
String str = String.format("TRACE recordLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("TRACE sentinelRecordLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -62,7 +62,7 @@ public class RecordLogTest {
while (count++ < 4000) {
log.clearLog();
RecordLog.debug("Count {}", count);
String str = String.format("DEBUG recordLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("DEBUG sentinelRecordLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
@ -70,7 +70,7 @@ public class RecordLogTest {
while (count++ < 5000) {
log.clearLog();
RecordLog.error("Count {}", count);
String str = String.format("ERROR recordLogLogger - Count %d" + System.lineSeparator(), count);
String str = String.format("ERROR sentinelRecordLogger - Count %d" + System.lineSeparator(), count);
Assert.assertEquals(str, log.getLog());
}
}
@ -85,31 +85,31 @@ public class RecordLogTest {
RecordLog.info("Error", e);
// split the log for test
String[] logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("INFO recordLogLogger - Error", logSplit[0]);
Assert.assertEquals("INFO sentinelRecordLogger - Error", logSplit[0]);
// warn test
log.clearLog();
RecordLog.warn("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("WARN recordLogLogger - Error", logSplit[0]);
Assert.assertEquals("WARN sentinelRecordLogger - Error", logSplit[0]);
// trace test
log.clearLog();
RecordLog.trace("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("TRACE recordLogLogger - Error", logSplit[0]);
Assert.assertEquals("TRACE sentinelRecordLogger - Error", logSplit[0]);
// debug test
log.clearLog();
RecordLog.debug("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("DEBUG recordLogLogger - Error", logSplit[0]);
Assert.assertEquals("DEBUG sentinelRecordLogger - Error", logSplit[0]);
// error test
log.clearLog();
RecordLog.error("Error", e);
logSplit = log.getLog().split(System.lineSeparator());
Assert.assertEquals("ERROR recordLogLogger - Error", logSplit[0]);
Assert.assertEquals("ERROR sentinelRecordLogger - Error", logSplit[0]);
}
}