问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/51898831/java-log4j2-logger-levels-arent-being-followed