Reputation: 757
Having the following config file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss.SSS} %-5level] %logger{36} - %msg%n"/>
</Console>
<File name="File" fileName="error.log">
<PatternLayout pattern="[%d{ISO8601} %-5level] %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Logger name="errors" level="error">
<AppenderRef ref="File"/>
</Logger>
<Root level="all">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
only writes (all) logging output to the console. I however had the intention to write anything above error
to a file named error.log
with a slightly different format. However, running my application results in everything being written to the console, leaving an empty file behind (which gets created, just not filled).
Somehow it seems like the Root logger catches everything because I had also tried this:
<Logger name="errors" level="error">
<AppenderRef ref="Console"/>
</Logger>
which does not log twice. I'm out of ideas really, I even copied an example from the docs (sample #2 from here) and that aswell leaves an empty file.
Upvotes: 13
Views: 27786
Reputation: 51
Log4J2 doesn't write to file until the process has completed. By default the buffer isn't flushed with each call to the logger. For example,
<File name="File" fileName="LogfileName.log" immediateFlush="false" append="false">
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
will not log to the file immediately. Change the values of immediateFlush to true to force the buffer to flush on each call to logger.
Upvotes: 1
Reputation: 36844
Yes, the root logger level is ALL so it will receive all events. One option is to do this:
<Loggers>
<Root level="all">
<AppenderRef ref="Console" level="trace" />
<AppenderRef ref="File" level="error" />
</Root>
</Loggers>
This way you only have one logger, so you don't need to worry about additivity and in your code you can just write LogManager.getLogger(MyClass.class)
to get a Logger
instance. (If you use a named Logger, you would need to use the logger name in your code: LogManager.getLogger("error")
.)
Upvotes: 18
Reputation: 13736
Try this something like this.
Here Target is important attribute to be noticed.
The console appender has one param element defined. Looking at the javadoc for ConsoleAppender , the setTarget method is used to choose which console stream to print messages to, System.out or System.err. The example configures the appender to use System.out.
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
Upvotes: -2
Reputation: 757
Ah, I was being stupid. The attribute name
seems to be a filter for which classes will use that logger. Changing name
to my top level package resolved the issue.
Upvotes: 8