Why does log4j prints a new line break in stdout appender?
my log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
<Appenders>
<File name="FILE" fileName="<<FILEPATH>>\logfile.log"
append="true">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5p | %l - %m%n" />
</File>
<File name="UIFILE" fileName="<<FILEPATH>>\uilogfile.log"
append="true">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} | %m%n" />
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout>
<pattern>[%-5p] %C{2} - %m%n</pattern>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="INFO"/>
<Logger name="com.foo" level="DEBUG" />
<Logger name="com.foo.services.web.controllers.FOOLoggingController"
level="INFO">
<AppenderRef ref="UIFILE" />
</Logger>
<Root>
<AppenderRef ref="STDOUT" />
<AppenderRef ref="FILE" />
</Root>
</Loggers>
</Configuration>
everything works fine but I get a new line between outputs, don't know why!
I tried few things like removing %n from the pattern layout but when i do this, the log itself stops coming. The file output is good. It doesn't prints new line in between. Has someone faced a similar issue?
I solved this issue by replacing %n with \n inside the Console's pattern string. So the Console appender would look like:
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern ="[%-5p] %C{2} - %m \n" />
</Console>
Replacing with \n is not a good solution.
You should make sure if there is another logging framework wrapping your logs to standard output.
This happening in case of application servers, where deployed applications use a logging framework to send formatted messages to standard output, and server uses its own active logging framework to wrap the message around with its own format, before sending it to standard output.
This causes double formatting & therefore double newlines. Check your runtime, if there is an active logger wrapping your messages.
Related
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class AzulMain {
private static final Logger LOGGER = LogManager.getLogger(AzulMain.class.getName());
public static void main(String[] args){
LOGGER.info("Maybe my first Logger works?");
}
}
The imports work fine. I use these jar-files:
log4j-1.2-api-2.17.2.jar
log4j-api.2.17.2.jar
log4j-core-2.17.2.jar
And this is how my XML-file (log4j2.xml) looks. It is in the same folder as my AzulMain:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Properties>
<Property name="log-path">log/${date:yyyy-MM-dd HH-mm-ss-SSS}</Property>
<Property name="archive">${log-path}/archive</Property>
</Properties>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n
</pattern>
</PatternLayout>
</Console>
<File name="File-Appender-AzulMain" fileName="${log-path}/Azul.log">
<PatternLayout>
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n
</pattern>
</PatternLayout>
</File>
<RollingFile name="RollingFile-Appender"
fileName="${log-path}/rollingfile.log"
filePattern="${archive}/rollingfile.log.%d{yyyy-MM-dd#HH-mm}.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="30 MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="AzulMain" level="trace" additivity="false">
<AppenderRef ref="File-Appender-AzulMain" level="all"/>
<AppenderRef ref="Console-Appender" level="info"/>
</Logger>
<Root level="debug" additivity="false">
<AppenderRef ref="Console-Appender"/>
</Root>
</Loggers>
</Configuration>
When I use JavaUtilLogger everything works quite fine so far, I can make it create a file and print to console, however, with log4j nothing works.
I tested deleting the XML file and adding BasicConfigurator.configure() into my main-method, but it still didn't work. If I start my main-method all I get is:
Process finished with exit code 0
What is strange to me is that when I use the command java -Dlog4j.debug -cp AzulMain, it does not show me my configuration as I would expect it, but just what seems to be a very generic help message.
It is my first time, I am using a logger. Does anyone know what the problem might be?
Update:
This helped me as a first step:
BasicConfigurator replacement in log4j2
I deleted the XML-file and used the new
Configurator.initialize(new DefaultConfiguration());
Configurator.setRootLevel(Level.INFO);
And now it works at least in so far as it prints to the console. However, I am still not able to make it use the log4j2.xml file. I tried naming it log4j2-test.xml, too. (Source) It did not make a difference.
Now it works. This is how I did it.
I set up a new project, with just a main-class and added a new xml-file with a file logger only at first, then added a logger to the console, too. I deleted cache in IntelliJ and deleted the Configurator-lines in the code.
This is the new XML-file log4j2.xml that made it work:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Properties>
<Property name="basePath">log/${date:yyyy-MM-dd HH-mm-ss-SSS}</Property>
</Properties>
<!-- File Logger -->
<Appenders>
<!-- Console appender configuration -->
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n
</pattern>>
</PatternLayout>
</Console>
<RollingFile name="fileLogger"
fileName="${basePath}/Azul.log"
filePattern="${basePath}/app-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<!-- Max 10 files will be created everyday -->
<DefaultRolloverStrategy max="10">
<Delete basePath="${basePath}" maxDepth="10">
<!-- Delete all files older than 30 days -->
<IfLastModified age="30d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
<appender-ref ref="fileLogger" />
<appender-ref ref="Console-Appender" level="info"/>
</Root>
</Loggers>
</Configuration>
It seems to me to have been a mistake somewhere in the xml-file that I just couldn't figure out where it is.
Can Log4j2 be configured in such a way that the filters or some other components can filter out certain values from getting printed in the log? (but should allow other fields in the same line to pass through)
Say the following lines appear in the log
[operation=DONE, userName=junitUser, tenant=Tenant [tenantID=default], needDetails=1, message=BaseMsg [version=1.0, sdk=AppSDK [version=1.3, protocols=[4aac81ca, 393ae7a0]], device=Device [id=12345, type=Pompom, info=Dot's Device]]], channel=null
[operation=DONE, userName=junitUser224, tenant=Tenant [tenantID=default], needDetails=1, message=BaseMsg [version=1.0, sdk=AppSDK [version=1.3, protocols=[4aac81ca,393ae7a0]], device=Device [id=123456, type=Mamamia, info=tom's Device]]], channel=null
Now can I filter out the "userName" field in such a way that the log lines now do not contain it as shown below?
[operation=DONE, tenant=Tenant [tenantID=default], needDetails=1, message=BaseMsg [version=1.0, sdk=AppSDK [version=1.3, protocols=[4aac81ca, 393ae7a0]], device=Device [id=12345, type=Pompom, info=Dot's Device]]], channel=null
[operation=DONE, tenant=Tenant [tenantID=default], needDetails=1, message=BaseMsg [version=1.0, sdk=AppSDK [version=1.3, protocols=[4aac81ca,393ae7a0]], device=Device [id=123456, type=Mamamia, info=tom's Device]]], channel=null
Here is my log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="RollingFile" fileName="/Users/dunston/logs/app.log"
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
<RegexFilter regex=".* zinger_log .*" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<TimeBasedTriggeringPolicy />
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
This can be accomplished with a RewriteAppender.
You may need to write a custom RewritePolicy that inspects the LogEvent's Message and replaces the Message with another instance if the formatted message contains a regular expression that you want to filter out.
Your custom RewitePolicy can be configured in the configuration like any other standard Log4j2 plugin.
I have been trying to archive my application logs file which are older than a certain period. Noticed that since log4j 2.5 we have a Deletetag which let's you define the criteria based on which we can delete/archive our logs. Tried using this but I am somehow not able to crack it. Tried with a 30day 30d value and that isn't working on my server and neither is a 20 second policy PT20S working in my Dev Machine.
Any direction is greatly appreciated.
XML is as below:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<RollingFile name="RollingFile" fileName="C://logs///test.log" filePattern="C://logs//test-%d{MM-dd-yyyy}.log.gz" ignoreExceptions="false">
<PatternLayout pattern="%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
<TimeBasedTriggeringPolicy />
<DefaultRolloverStrategy>
<Delete basePath="C://logs//" maxDepth="2">
<IfFileName glob="*/test-*.log.gz" />
<IfLastModified age="PT20S" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console" />
<AppenderRef ref="RollingFile" />
</Root>
</Loggers>
</Configuration>
If you're using Windows the file and filePattern of the RollingFile appender can use single slashes. The double slashes may confuse it.
You can debug by setting <Configuration status="trace"> in the beginning of the configuration file.
Update:
The rolled over files end up in the c:/logs directory (filePattern="C://logs//test-%d{MM-dd-yyyy}.log.gz").
However, the Delete action is configured to only look at files ending in "log.gz" that are in subdirectories of c:/logs. Files in the c:/logs directory itself are not matched by glob="*/test-*.log.gz".
To fix this, use glob="test-*.log.gz".
It was mentioned in the comments that changing glob to regex also resolved the problem.
I am using log4j 2. I am trying to determine why my log file is not being written to, but my console is. This is the output I have to the console:
2016-04-25 12:26:07,142 INFO [main] helperCode.LogPlus (LogPlus.java:50) -
----------------------------------------------------------------------------
------------ The test is starting now at 2016-04-25-12-26-07-135 -----------
----------------------------------------------------------------------------
2016-04-25 12:26:07,151 INFO [main] helperCode.LogPlus (LogPlus.java:50) -
--------------------------------------------------------------------------
------------ METHOD loginBadPasswordGoodUsername_3 starting: ------------
--------------------------------------------------------------------------
The issues I've considered already:
The output is not repeating itself, so the log output being redirected is not an issue.
I am NOT using java.util.logging.Logger anywhere in my project;
The output of the log file is formatted in log4j style rather than JUL style, so I know that JUL is not overriding it;
Here is my XML config file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="FileLogger" fileName="${sys:logFilePath}" append="false">
<PatternLayout pattern="%d %t %-5p %c{2} - %m%n" />
</File>
<Async name="Async">
<AppenderRef ref="FileLogger" />
</Async>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="automationFramework" level="trace">
<AppenderRef ref="FileLogger" />
</Logger>
<Root level="trace">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
I am directing the output to the file located at the system variable "logFilePath".
I am not sure what is going on, and the config files shown on answers for similar questions are not in XML format, so I am not sure how to commute the config file code to XML.
In your case as mentioned in the comment you do not have the package called applicatiionFramework. So change the name attribute by the package name of the classes where you want to record log events.
<Logger name="your package" level="trace">
<AppenderRef ref="FileLogger" />
<Root level="trace">
<AppenderRef ref="STDOUT" />
</Root>
</Logger>
For more information visit log4j-manual-configuration
Glad the other answer helped. Do you need the named logger though? Why not just have the root logger? Also, you declared an Async Appender but are not using it. Is that on purpose? This is what I would suggest:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="FileLogger" fileName="${sys:logFilePath}" append="false">
<PatternLayout pattern="%d %t %-5p %c{2} - %m%n" />
</File>
<Async name="Async">
<AppenderRef ref="FileLogger" />
</Async>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="STDOUT" level="info" />
<AppenderRef ref="Async" />
</Root>
</Loggers>
</Configuration>
Note that you can also specify a level on the AppenderRef. I made the Console Appender level INFO to illustrate this point.
If you want the log to show location information and use Async loggers or appenders then you need to specify includeLocation="true" on the Async Appender.
For the complete noob, like myself, this line in Unknown's answer above:
<Logger name="your package" level="trace">
is the key. When it says "your package" it really means the "package foo.bar" you declared at the top of the .java file where you created the Logger, not the class name you passed to create the Logger, like:
LOGGER = LogManager.getLogger(MyClass.class.getName());
It took me a ridiculous amount of time today to get my log4j2 output going to a file, playing with various "name" values until the light bulb went on.
This is my log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF">
<Appenders>
<!-- Generate STDOUT in console -->
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</Console>
<!-- Generate rolling log for router with per hour interval policy -->
<RollingFile name="RouterRollingFile" fileName="/apps/bea/mb-logs/router.log"
immediateFlush="false" filePattern="/apps/bea/mb-logs/router.%d{yyyy-MM-dd-HH}-%i.log">
<PatternLayout>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %5p [%t] (%F:%L) - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- <DefaultRolloverStrategy fileIndex="max" max="24" /> -->
</RollingFile>
</Appenders>
<Loggers>
<AsyncLogger name="com.tritronik.mb.router" level="info"
additivity="false" includeLocation="true">
<AppenderRef ref="RouterRollingFile" />
</AsyncLogger>
<!-- <Root level="info">
<appender-ref ref="CONSOLE" />
</Root> -->
</Loggers>
I want to achieve daily rolling file with per hour rolling, so far I haven't been able to produce the log with proper format, and as I remember, the interval parameter seems like to increment by day not hour.
I want to achieve this:
router.log --> currently written file
router.log.2014-06-20-00
router.log.2014-06-20-01
...
router.log.2014-06-20-23
router.log.2014-06-21-00
...
Instead I achieve this:
router.log
router.log.2014-06-20-1 --> One day worth of logs
I've been able to do this using usual log4j, but the io performance goes down and force me to use log4j2, but I stumble into this problem.
Where do I have it wrong? Or is it true that log4j2 doesn't support this yet?
Thank you
You may have found a bug.
Is this only happening with Async Loggers or also when you configure a plain (synchronous) logger?
Also, have you tried using a filePattern that looks like this:
filePattern="/apps/bea/mb-logs/$${date:yyyy-MM-dd}/router.%d{yyyy-MM-dd-HH}.log"?
I have a (admittedly vague) suspicion that the $${date:...} part might be related.
If neither of the above makes any difference, could you please file a Jira ticket on the log4j2 issue tracker? https://issues.apache.org/jira/browse/LOG4J2