问题描述
所以我试图学习log4j2并将头缠绕在伐木者及其水平和父母的传播周围.
当前我的来源层次结构运行是:
├── main │ ├── java │ │ └── calculatorMain │ │ ├── Main.java │ │ ├── someClass2.java │ │ └── someClass1.java │ └── resources │ ├── Excels │ │ └── TestExcel.xlsx │ ├── FXMLs │ │ └── mainWindow.fxml │ └── log4j2.xml
我的计算瘤是:
Public class Main extends Application { private static final String mainWindow = //FXML stuff private static final Logger logger = LogManager.getLogger(Main.class.getName()); public static void main(String[] args) { logger.debug("Main has started"); launch(args); } @Override public void start(Stage primaryStage) { try { //FXML stuff Parent root = //fxml stuff logger.info("Main scene loaded successfully"); if (root != null) { //FXML stuff } else logger.error("Root was null"); } catch (Exception e) { logger.error("Error",e); } } }
我的log4j2.xml是
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="BrightnessCalculator packages"> <!-- Logging Properties --> <Properties> <Property name="basePath">./logs</Property> <Property name="filePattern">${date:yyyy-MM-dd}</Property> </Properties> <Appenders> <!-- File Appenders --> <RollingFile name="mainLog" fileName="${basePath}/info-${filePattern}.log" filePattern="${basePath}/app-info-%d{yyyy-MM-dd}.log.gz"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %logger{36} - %msg%n" /> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> </Policies> </RollingFile> <!-- Console Appender --> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="ERROR"> <AppenderRef ref="console"/> </Root> <Logger name="calculatorMain" level="ERROR"> <appenderRef ref="mainLog"/> </Logger> <Logger name="calculatorMain.Main" level="TRACE"> <appenderRef ref="mainLog"/> </Logger> </Loggers> </Configuration>
问题在于,输出到控制台的根记录器设置为level="ERROR".从我对级别的理解中,这意味着我的根记录器应仅输出误差日志或更低.然后是我的CalculatorMain Calculator.Main记录器,前者只应记录错误,而后者则应记录迹线并较低.因此,我的理解是,错误日志和下部将被打印两次,并且上述错误日志的任何内容都只能根据父繁殖一次打印到日志中.但是,基于我的日志文件输出以下内容并非如此:
[DEBUG] 2018-08-17 16:37:28.239 [main] calculatorMain.Main - Main has started [DEBUG] 2018-08-17 16:37:28.239 [main] calculatorMain.Main - Main has started [INFO ] 2018-08-17 16:37:28.741 [JavaFX Application Thread] calculatorMain.Main - Main scene loaded successfully [INFO ] 2018-08-17 16:37:28.741 [JavaFX Application Thread] calculatorMain.Main - Main scene loaded successfully
这些上面的日志只能打印一次.我一直在关注 this 经过深思熟虑的教程,但我猜我一定会误解.
推荐答案
您遇到的问题默认情况下是添加性为true.您的教程具有误导性,因为它说:
默认情况下,log4j2记录是加法的.这意味着所有父母 Loggers 也将在使用特定的记录器时使用.
实际上不是意味着所有父登录器将使用,这意味着将使用所有附录 .您应该阅读 log4j2手册.
在本手册的"添加性"部分中,有一个示例,其中有一些解释:
请注意,来自com.foo.bar的跟踪消息出现两次.这是 因为首先使用了与logger com.foo.bar关联的appender,所以 将第一个实例写入控制台.接下来,父母 引用了com.foo.bar(在这种情况下是根记录器).这 然后将事件传递给其 appender ,也将其写入 控制台,导致第二个实例.这被称为 添加性.
将添加性设置为true(默认情况下是)子记录器接受的任何事件都将传递给所有父loggers的附录.
问题描述
So I'm trying to learn log4j2 and wrap my head around the loggers and their levels and parental propagation.
Currently my source hierarchy runs is:
├── main │ ├── java │ │ └── calculatorMain │ │ ├── Main.java │ │ ├── someClass2.java │ │ └── someClass1.java │ └── resources │ ├── Excels │ │ └── TestExcel.xlsx │ ├── FXMLs │ │ └── mainWindow.fxml │ └── log4j2.xml
and my calculatorMain is:
Public class Main extends Application { private static final String mainWindow = //FXML stuff private static final Logger logger = LogManager.getLogger(Main.class.getName()); public static void main(String[] args) { logger.debug("Main has started"); launch(args); } @Override public void start(Stage primaryStage) { try { //FXML stuff Parent root = //fxml stuff logger.info("Main scene loaded successfully"); if (root != null) { //FXML stuff } else logger.error("Root was null"); } catch (Exception e) { logger.error("Error",e); } } }
My log4j2.xml is
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="BrightnessCalculator packages"> <!-- Logging Properties --> <Properties> <Property name="basePath">./logs</Property> <Property name="filePattern">${date:yyyy-MM-dd}</Property> </Properties> <Appenders> <!-- File Appenders --> <RollingFile name="mainLog" fileName="${basePath}/info-${filePattern}.log" filePattern="${basePath}/app-info-%d{yyyy-MM-dd}.log.gz"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %logger{36} - %msg%n" /> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> </Policies> </RollingFile> <!-- Console Appender --> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="ERROR"> <AppenderRef ref="console"/> </Root> <Logger name="calculatorMain" level="ERROR"> <appenderRef ref="mainLog"/> </Logger> <Logger name="calculatorMain.Main" level="TRACE"> <appenderRef ref="mainLog"/> </Logger> </Loggers> </Configuration>
The problem is that the root logger which outputs to the console is set to level="ERROR". From my understanding of levels that means my root logger should only output error logs or lower. Then there's my CalculatorMain Calculator.Main loggers, the former should only log errors and lower whereas the latter should log traces and lower. So my understanding is that error logs and lower will be printed twice and anything above error logs should only get printed to the log once based on parent propagation. However that is not the case based with my log file outputting the following:
[DEBUG] 2018-08-17 16:37:28.239 [main] calculatorMain.Main - Main has started [DEBUG] 2018-08-17 16:37:28.239 [main] calculatorMain.Main - Main has started [INFO ] 2018-08-17 16:37:28.741 [JavaFX Application Thread] calculatorMain.Main - Main scene loaded successfully [INFO ] 2018-08-17 16:37:28.741 [JavaFX Application Thread] calculatorMain.Main - Main scene loaded successfully
These above logs should've only printed once. I've been following this well thought out tutorial but I guess I must be misunderstanding.
推荐答案
The issue you're having is due to additivity being true by default. Your tutorial is misleading in that it says:
By default log4j2 logging is additive. It means that all the parent loggers will also be used when a specific logger is used.
In fact it does not mean that all parent loggers will be used, it means all of the appenders of parent loggers will be used. You should read the log4j2 manual, particularly the section on additivity.
In the additivity section of the manual, there is an example with some explanation after it:
Notice that the trace messages from com.foo.Bar appear twice. This is because the appender associated with logger com.foo.Bar is first used, which writes the first instance to the Console. Next, the parent of com.foo.Bar, which in this case is the root logger, is referenced. The event is then passed to its appender, which also writes to the Console, resulting in the second instance. This is known as additivity.
With additivity set to true (as it is by default) any event accepted by a child logger is passed to the appenders of all parent loggers.