Log4j2的日志输出过程
2021-02-21 本文已影响0人
晴天哥_王志
系列
背景
该篇文章主要介绍Log4j2的日志输出过程,核心流程包含获取Logger对象和通过Logger输出日志。
- Logger的获取过程主要通过LoggerContext和LoggerRegistry来获取。
- Logger的日志输出主要通过Logger、LoggerConfig、AppenderControl、Appender进行日志输出
Logger获取过程
Log4j2获取Logger的过程主要从LoggerContext、LoggerRegistry处获取Logger对象。
public class LogManager {
public static Logger getLogger(final String name) {
return name != null ? getContext(false).getLogger(name) :
getLogger(StackLocatorUtil.getCallerClass(2));
}
}
- LogManager通过LoggerContext来获取Logger对象。
public class LoggerContext
public Logger getLogger(final String name, final MessageFactory messageFactory) {
// 通过LoggerRegistry来获取Logger对象
Logger logger = loggerRegistry.getLogger(name, messageFactory);
if (logger != null) {
AbstractLogger.checkMessageFactory(logger, messageFactory);
return logger;
}
logger = newInstance(this, name, messageFactory);
loggerRegistry.putIfAbsent(name, messageFactory, logger);
return loggerRegistry.getLogger(name, messageFactory);
}
}
- LoggerContext通过LoggerRegistry来获取Logger对象。
public class LoggerRegistry<T extends ExtendedLogger> {
public T getLogger(final String name, final MessageFactory messageFactory) {
return getOrCreateInnerMap(factoryKey(messageFactory)).get(name);
}
private Map<String, T> getOrCreateInnerMap(final String factoryName) {
Map<String, T> inner = map.get(factoryName);
if (inner == null) {
inner = factory.createInnerMap();
map.put(factoryName, inner);
}
return inner;
}
}
- LoggerRegistry内部维护Logger对象。
日志输出过程

- 整体日志输出流程通过Logger、LoggerConfig、AppenderControl、Appender进行日志输出。
日志输出源码
public abstract class AbstractLogger
public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final String message,final Throwable t) {
// 全局Filter和全局的日志级别进行过滤
if (isEnabled(level, marker, message, t)) {
// 输出日志
logMessage(fqcn, level, marker, message, t);
}
}
protected void logMessage(final String fqcn, final Level level,
final Marker marker, final String message,final Throwable t) {
// 通过ReusableMessageFactory组建消息体
logMessageSafely(fqcn, level, marker,
messageFactory.newMessage(message), t);
}
private void logMessageSafely(final String fqcn, final Level level,
final Marker marker, final Message msg, final Throwable throwable) {
try {
logMessageTrackRecursion(fqcn, level, marker, msg, throwable);
} finally {
ReusableMessageFactory.release(msg);
}
}
private void logMessageTrackRecursion(final String fqcn,
final Level level,
final Marker marker,
final Message msg,
final Throwable throwable) {
try {
incrementRecursionDepth(); // LOG4J2-1518, LOG4J2-2031
tryLogMessage(fqcn, getLocation(fqcn), level,
marker, msg, throwable);
} finally {
decrementRecursionDepth();
}
}
private void tryLogMessage(final String fqcn,
final StackTraceElement location,
final Level level,
final Marker marker,
final Message msg,
final Throwable throwable) {
try {
log(level, marker, fqcn, location, msg, throwable);
} catch (final Exception e) {
handleLogMessageException(e, fqcn, msg);
}
}
protected void log(final Level level, final Marker marker,
final String fqcn, final StackTraceElement location,
final Message message, final Throwable throwable) {
// strategy为AwaitCompletionReliabilityStrategy
final ReliabilityStrategy strategy =
privateConfig.loggerConfig.getReliabilityStrategy();
if (strategy instanceof LocationAwareReliabilityStrategy) {
// 继续跟进log过程
((LocationAwareReliabilityStrategy) strategy)
.log(this, getName(), fqcn, location, marker, level,
message, throwable);
} else {
// 省略代码
}
}
}
- Logger通过PrivateConfig的isEnabled进行过滤。
- Logger通过strategy的log方法进行日志输出。
public class Logger extends AbstractLogger implements Supplier<LoggerConfig> {
public boolean isEnabled(final Level level, final Marker marker,
final String message, final Throwable t) {
return privateConfig.filter(level, marker, message, t);
}
protected class PrivateConfig {
boolean filter(final Level level, final Marker marker,
final String msg, final Throwable t) {
// 先通过全局的Filter进行过滤
final Filter filter = config.getFilter();
if (filter != null) {
final Filter.Result r =
filter.filter(logger, level, marker, (Object) msg, t);
if (r != Filter.Result.NEUTRAL) {
return r == Filter.Result.ACCEPT;
}
}
// 再判断日志等级是否满足要求
return level != null && intLevel >= level.intLevel();
}
}
}
- PrivateConfig的filter负责日志输出过滤。
public class AwaitCompletionReliabilityStrategy
public void log(final Supplier<LoggerConfig> reconfigured,
final String loggerName, final String fqcn,
final StackTraceElement location, final Marker marker,
final Level level, final Message data, final Throwable t) {
// 通过LoggerConfig的进行日志打印
final LoggerConfig config = getActiveLoggerConfig(reconfigured);
try {
config.log(loggerName, fqcn, location, marker, level, data, t);
} finally {
config.getReliabilityStrategy().afterLogEvent();
}
}
}
- AwaitCompletionReliabilityStrategy通过LoggerConfig进行日志输出。
public class LoggerConfig extends AbstractFilterable implements LocationAware {
public void log(final String loggerName, final String fqcn,
final StackTraceElement location, final Marker marker,
final Level level, final Message data, final Throwable t) {
List<Property> props = null;
if (!propertiesRequireLookup) {
props = properties;
}
// 创建LogEvent对象
final LogEvent logEvent =
logEventFactory instanceof LocationAwareLogEventFactory ?
((LocationAwareLogEventFactory) logEventFactory).createEvent(
loggerName, marker, fqcn, location, level, data, props, t) :
logEventFactory.createEvent(
loggerName, marker, fqcn, level, data, props, t);
try {
// 继续执行
log(logEvent, LoggerConfigPredicate.ALL);
} finally {
ReusableLogEventFactory.release(logEvent);
}
}
protected void log(final LogEvent event,
final LoggerConfigPredicate predicate) {
if (!isFiltered(event)) {
processLogEvent(event, predicate);
}
}
private void processLogEvent(final LogEvent event,
final LoggerConfigPredicate predicate) {
event.setIncludeLocation(isIncludeLocation());
if (predicate.allow(this)) {
callAppenders(event);
}
logParent(event, predicate);
}
protected void callAppenders(final LogEvent event) {
final AppenderControl[] controls = appenders.get();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < controls.length; i++) {
controls[i].callAppender(event);
}
}
}
- LoggerConfig通过AppenderControl的callAppender进行日志输出。
public class AppenderControl extends AbstractFilterable {
public void callAppender(final LogEvent event) {
if (shouldSkip(event)) {
return;
}
callAppenderPreventRecursion(event);
}
private void callAppenderPreventRecursion(final LogEvent event) {
try {
recursive.set(this);
callAppender0(event);
} finally {
recursive.set(null);
}
}
private void callAppender0(final LogEvent event) {
ensureAppenderStarted();
if (!isFilteredByAppender(event)) {
tryCallAppender(event);
}
}
private void tryCallAppender(final LogEvent event) {
try {
appender.append(event);
} catch (final RuntimeException ex) {
handleAppenderError(event, ex);
} catch (final Exception ex) {
handleAppenderError(event, new AppenderLoggingException(ex));
}
}
private boolean shouldSkip(final LogEvent event) {
return isFilteredByAppenderControl(event)
|| isFilteredByLevel(event) || isRecursiveCall();
}
}
- AppenderControl通过Appender的append进行日志输出。
public abstract class AbstractOutputStreamAppender<
M extends OutputStreamManager> extends AbstractAppender {
public void append(final LogEvent event) {
try {
tryAppend(event);
} catch (final AppenderLoggingException ex) {
throw ex;
}
}
private void tryAppend(final LogEvent event) {
if (Constants.ENABLE_DIRECT_ENCODERS) {
directEncodeEvent(event);
} else {
writeByteArrayToManager(event);
}
}
protected void directEncodeEvent(final LogEvent event) {
getLayout().encode(event, manager);
if (this.immediateFlush || event.isEndOfBatch()) {
manager.flush();
}
}
}
- 具体的Appender进行格式化并输出日志。