在一个 class 配置中设置 log4j.rootLogger=OFF,将导致另一个 class 中的日志崩溃
Setting log4j.rootLogger=OFF in one class configuration, will cause log crash in another class
在一个 class 配置中设置 log4j.rootLogger=OFF,将导致另一个 class 不登录。
我有两个示例 classes:LogCrasher 和 MainLogger。这两个 classes 被配置为记录一些测试日志。每个 class 都有自己的配置文件。从 MainLogger 调用了 LogCrasher。当LogCrashers log4j配置文件中的log4j.rootLogger设置为INFO, WARN... logging没有问题,但是如果我们设置为OFF,那么MainLogger就不会再输出日志了。
如何解决这个问题,将一个 class 记录器与另一个记录器隔离开来。
MainLogger.java
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class MainLogger {
private static String LOG_PROPS = "mainlogger.properties";
final static Logger logger = Logger.getLogger(MainLogger.class);
static {
PropertyConfigurator.configureAndWatch(LOG_PROPS);
}
public static void main(String[] args) {
MainLogger mainLogger = new MainLogger();
try {
mainLogger.doLogging();
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
public void doLogging() {
logger.info("Before calling log crasher.");
printTestLog();
new Thread(new Runnable() {
@Override
public void run() {
LogCrasher logCrasher = new LogCrasher();
logCrasher.printTestLog();
}
}).start();
logger.info("After calling log crasher.");
printTestLog();
}
private void printTestLog() {
int counter = 0;
while (++counter < 5) {
logger.info("Counter: " + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.info("printTestLog sleeper thread interupted: " + e.getMessage());
}
}
}
}
LogCrasher.java
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class LogCrasher {
private static String LOG_PROPS = "logcrasher.properties";
final static Logger logger = Logger.getLogger(LogCrasher.class);
static {
PropertyConfigurator.configureAndWatch(LOG_PROPS);
}
public void printTestLog() {
int counter = 0;
while (++counter < 5) {
logger.info("Counter: " + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.info("printTestLog sleeper thread interupted: " + e.getMessage());
}
}
}
}
logcrasher.properties
# Root logger option
log4j.rootLogger=OFF, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logcrasher.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
mainlogger.properties
# Root logger option
log4j.rootLogger=INFO, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=mainlogger.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4 framework
使用 factory/singleton
方法...因此如果您在 1 class 中重新加载新的 config
,则所有 class同样 class loader
应该看到 config
就好像它是 1 true live config
.
您需要做的是在 package/class
级别封装您需要的日志记录行为,您将在调用 Logger.getLogger()
时看到效果。使用较新版本的 apache log4j
,您可以使用 no args
调用 LogManger.getLogger()
以获取 current class
的记录器(使其易于在所有 class 文件中定义).
然后因为你可以有一系列不同的 loggers
和 appenders
,以及设置附加程序通过不同的记录器级联,你不应该需要超过 1 个配置文件。
希望对您有所帮助!
您不能像这样定义 2 个 log4j 属性文件。 Log4j 框架将只加载并考虑一个,它将首先在 class 路径中找到。
现在对于您的问题的解决方案部分,您不能像这样在 class 级别有单独的日志记录方案,但您可以在包级别有单独的日志记录方案。
现在考虑到你的 2 classes 在不同的包中,你可以有你的 log4j.properties 如下。
log4j.logger.com.Whosebug.meta
将应用于 com.Whosebug.meta
包中的所有 classes,log4j.logger.com.Whosebug.code
将应用于 com.Whosebug.code
包中的所有 classes。
像这样,您现在可以控制包级别的日志记录。
log4j.logger.com.Whosebug.meta=OFF, file, stdout
log4j.logger.com.Whosebug.code=DEBUG, file, stdout
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=mainlogger.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
在一个 class 配置中设置 log4j.rootLogger=OFF,将导致另一个 class 不登录。 我有两个示例 classes:LogCrasher 和 MainLogger。这两个 classes 被配置为记录一些测试日志。每个 class 都有自己的配置文件。从 MainLogger 调用了 LogCrasher。当LogCrashers log4j配置文件中的log4j.rootLogger设置为INFO, WARN... logging没有问题,但是如果我们设置为OFF,那么MainLogger就不会再输出日志了。 如何解决这个问题,将一个 class 记录器与另一个记录器隔离开来。
MainLogger.java
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class MainLogger {
private static String LOG_PROPS = "mainlogger.properties";
final static Logger logger = Logger.getLogger(MainLogger.class);
static {
PropertyConfigurator.configureAndWatch(LOG_PROPS);
}
public static void main(String[] args) {
MainLogger mainLogger = new MainLogger();
try {
mainLogger.doLogging();
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
public void doLogging() {
logger.info("Before calling log crasher.");
printTestLog();
new Thread(new Runnable() {
@Override
public void run() {
LogCrasher logCrasher = new LogCrasher();
logCrasher.printTestLog();
}
}).start();
logger.info("After calling log crasher.");
printTestLog();
}
private void printTestLog() {
int counter = 0;
while (++counter < 5) {
logger.info("Counter: " + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.info("printTestLog sleeper thread interupted: " + e.getMessage());
}
}
}
}
LogCrasher.java
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class LogCrasher {
private static String LOG_PROPS = "logcrasher.properties";
final static Logger logger = Logger.getLogger(LogCrasher.class);
static {
PropertyConfigurator.configureAndWatch(LOG_PROPS);
}
public void printTestLog() {
int counter = 0;
while (++counter < 5) {
logger.info("Counter: " + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.info("printTestLog sleeper thread interupted: " + e.getMessage());
}
}
}
}
logcrasher.properties
# Root logger option
log4j.rootLogger=OFF, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logcrasher.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
mainlogger.properties
# Root logger option
log4j.rootLogger=INFO, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=mainlogger.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4 framework
使用 factory/singleton
方法...因此如果您在 1 class 中重新加载新的 config
,则所有 class同样 class loader
应该看到 config
就好像它是 1 true live config
.
您需要做的是在 package/class
级别封装您需要的日志记录行为,您将在调用 Logger.getLogger()
时看到效果。使用较新版本的 apache log4j
,您可以使用 no args
调用 LogManger.getLogger()
以获取 current class
的记录器(使其易于在所有 class 文件中定义).
然后因为你可以有一系列不同的 loggers
和 appenders
,以及设置附加程序通过不同的记录器级联,你不应该需要超过 1 个配置文件。
希望对您有所帮助!
您不能像这样定义 2 个 log4j 属性文件。 Log4j 框架将只加载并考虑一个,它将首先在 class 路径中找到。
现在对于您的问题的解决方案部分,您不能像这样在 class 级别有单独的日志记录方案,但您可以在包级别有单独的日志记录方案。
现在考虑到你的 2 classes 在不同的包中,你可以有你的 log4j.properties 如下。
log4j.logger.com.Whosebug.meta
将应用于 com.Whosebug.meta
包中的所有 classes,log4j.logger.com.Whosebug.code
将应用于 com.Whosebug.code
包中的所有 classes。
像这样,您现在可以控制包级别的日志记录。
log4j.logger.com.Whosebug.meta=OFF, file, stdout
log4j.logger.com.Whosebug.code=DEBUG, file, stdout
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Rirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=mainlogger.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n