I have a problem applying the log4j2.xml auto configuration properly, and I think it has something to do with my folder arrangement.
I'm using maven to add log4j2 libs and arrange my projects as follows:
- one project to contain all "common" classes, used by server and client side of my system.
- another "core" project - the server side application.
Both projects use the same general package hierarchy (like com.foo.specific.package)
In the Common project I define a logger wrapper:
public class LogWrapper
{
static Logger systemParentLogger = LogManager.getLogger("com.foo");
public static Logger getLogger(Class<?> cls)
{
return LogManager.getLogger(cls.getName());
}
}
Moreover, the Common project contains the log4j2.xml file under META-INF (alongside the persistence.xml file for Hibernate usage).
<?xml version="1.0" encoding="UTF-8"?>
<configuration name="PRODUCTION" status="OFF">
<appenders>
<appender type="RollingFile"
name="MyFileAppender"
fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<layout type="PatternLayout" pattern="%d %p %C{1.} [%t] %m%n"/>
</appender>
</appenders>
<loggers>
<root level="error">
<appender-ref ref="MyFileAppender"/>
</root>
<logger name="com.foo" level="info" additivity="false">
<appender-ref ref="MyFileAppender"/>
</logger>
<logger name="org.hibernate" level="error">
<appender-ref ref=MyFileAppender"/>
</logger>
</loggers>
</configuration>
While running a sample code in the Core project (using the LogWrapper I wrote and some JPA voodoo), I could still see INFO hibernate logs, and no log file was created. I should state that while debugging the code, I could see that the logger fetched was given some weird value "com.foo.core.persistence.PersistenceXMLTest:ERROR in sun.misc.Launcher$AppClassLoader#2f600492"
The log4j2.xml was placed in a "Folder" which in eclipse terms is "not on classpath".
Changing META-INF to be a "source folder" solved the problem.
In addition, the log4j2.xml file was not defined properly.
These are the modifications needed:
<?xml version="1.0" encoding="UTF-8"?>
<configuration name="PRODUCTION" status="OFF">
<appenders>
<RollingFile name="MyFileAppender"
fileName="../Logs/app.log"
filePattern="../Logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<pattern>%d %p %C{1.} [%t] %m%n</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
</appenders>
<loggers>
<root level="error">
<appender-ref ref="MyFileAppender"/>
</root>
<logger name="com.foo" level="info" additivity="false">
<appender-ref ref="MyFileAppender"/>
</logger>
</loggers>
</configuration>
Still couldn't make the org.hibernate logger to be redirected to my logs, but at least I got the logger to work
Related
I have an application where there are some custom jars added. One of the jars expects logging to be in a different pattern from the entire application's common logging pattern.
(We are using log4j2.xml way)
Now it is pretty straightforward to do it in Console logs by adding multiple appenders, with different patterns and associating them with the corresponding logger name (base package of the custom jar)
But is there a way to do it in the RollingFile Appenders in the same file ?
Consider the example below
Base application having base log pattern has Logger name = com.legacysystem.base
Custom jar within the application needing custom log pattern has logger name = com.legacysystem.custom
Log pattern for base and custom jar is defined in properties with variable names log-pattern and log-pattern
please ignore the fact that proper pattern value is not added, as i want to keep it hidden (assume log4j2-pattern.xml is present with proper log format)
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="log4j2-pattern.xml">
<xi:fallback >
<Properties>
<Property name="log-pattern">base_log_pattern</Property>
<Property name="custom-log-pattern">custom_log_pattern</Property>
</Properties>
</xi:fallback>
</xi:include>
<Appenders>
<Console name="ConsoleBaseAppender">
<PatternLayout pattern="${log-pattern}"/>
</Console>
<Console name="ConsoleCustomAppender">
<PatternLayout pattern="${custom-log-pattern}"/>
</Console>
<RollingFile name="FILE" fileName="commonFileName.log" filePattern="commonFileName-%d{yyyy-MM-dd-HH}-%i.log.gz">
<PatternLayout pattern="${log-pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="25MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="CUSTOM_FILE" fileName="commonFileName.log" filePattern="commonFileName-%d{yyyy-MM-dd-HH}-%i.log.gz">
<PatternLayout pattern="${custom-log-pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="25MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name = "com.legacysystem.custom" level="INFO" additivity="false">
<AppenderRef ref="CUSTOM_FILE" />
<AppenderRef ref="ConsoleCustomAppender" />
</Logger>
<Logger name="com.legacysystem.base" level="INFO" additivity="false">
<AppenderRef ref="FILE" />
<AppenderRef ref="ConsoleBaseAppender" />
</Logger>
<Root level="INFO">
<AppenderRef ref="FILE" />
<AppenderRef ref="ConsoleBaseAppender" />
</Root>
</Loggers>
</Configuration>
In the above example, I have succeeded in getting different log patterns in the console, but log files isn't working.
Also, is there a better way to do it without defining two rolling file appenders pointing to same file name ?
To upgrade my log4j2 from 2.6.2 to 2.15.0, I simply uses maven build to change the pom.xml log4j-core and log4j-api 's version. However, once I have deployed the java application to tomcat. Log4j 2.15.0 doesn't log to the specific file but catalina.out only. When I fallback to the previous 2.6.x without changing anything, things worked as expected. The log4j.xml I have is as shown below and The way that I get the logManager in Java is just
private static Logger log = LogManager.getLogger("Logger");
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<RollingFile name="errorLogging" fileName="/opt/app/tomcat8/logs/test.log"
filePattern="/opt/app/tomcat8/logs/test.log.%d{yyyy-MM-dd}">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
</Root>
<Logger name="Logger" level="info">
<AppenderRef ref="errorLogging" level="info"/>
</Logger>
</Loggers>
</Configuration>
This is my log4j2.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Properties>
<Property name="basePath">/folderName/logs/</Property>
</Properties>
<Appenders>
<RollingFile name="fileLogger" fileName="${basePath}/fileName.log"
filePattern="${basePath}/edf-info-%d{MM-yyyy-dd}.log">
<PatternLayout>
<pattern>%d{MM-yyyy-dd} [%-5level] %l - %msg%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingFile>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout>
<pattern>%d{MM-yyyy-dd} [%-5level] %l - %msg%n</pattern>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<Logger name="com.company.projectName" level="info" additivity="true">
<appender-ref ref="fileLogger" level="debug"/>
</Logger>
<Root level="info" additivity="false">
<appender-ref ref="console"/>
</Root>
</Loggers>
</Configuration>
When I used previous versions of Log4j2, only requests sent by my application were being written to my log file in my log folder on my computer. For example:
12-2021-27 [INFO ] com.company.projectname.controller.ClassController.methodName(ClassController.java:21) - paramName1, paramname2
12-2021-27 [INFO ] com.company.projectname.service.ClassServiceImpl.methodName(ClassServiceImpl.java:21) - paramName1, paramname2
But when I switched to the new version of Log4j, because of the vulnerability, before the messages I showed above, when my spring boot project runs, its messages also written. I mean focus on following.
12-2021-22 [INFO ] org.springframework.boot.StartupInfoLogger.logStarting(StartupInfoLogger.java:55) - Starting ProjectNameApplication using Java 1.8.0_111 on pc-name with PID 00000 (C:\Workspace\project-name\target\classes started by user.namein C:\Workspace\project-name)
12-2021-22 [INFO ] org.springframework.boot.SpringApplication.logStartupProfileInfo(SpringApplication.java:635) - No active profile set, falling back to default profiles: default
12-2021-22 [INFO ] org.springframework.boot.StartupInfoLogger.logStarted(StartupInfoLogger.java:61) - Started ProjectNameApplication in 8.858 seconds (JVM running for 12.962)
but I don't want to see these messages in my log file. I just want to write messages when request and response are generated, like before my configuration. How to solve this? I mean I want to only messages to the log file which my requests and responses.
Those unwanted messages use SpringApplication#getApplicationLog() to retrieve a logger, whose name is the fully qualified class name of your main class. The logger's name is probably a child of "com.company.projectName", hence it is sent to the file appender. You can confirm it by adding %c to your pattern layout.
Assuming your main class is called com.company.projectName.Application, you can:
either configure a com.company.projectName.Application logger that uses only the console appender:
<Logger name="com.company.projectName.Application" level="INFO" additivity="false">
<AppenderRef ref="console"/>
</Logger>
or replace the com.company.projectName logger with more specific ones:
<Logger name="com.company.projectName.controller" level="DEBUG">
<AppenderRef ref="fileLogger" />
</Logger>
<Logger name="com.company.projectName.controller" level="DEBUG">
<AppenderRef ref="fileLogger" />
</Logger>
I'm using Log4j 2 to log the events of my application. However I'm stuck at the following problem.
Currently all logging messages are being written to two different appenders. One has RollingFile type, while the other has Console type.
What I want is for the RollingFile appender to log messages with an INFO level or higher (ERROR, FATAL), and for the Console appender to log messages with an ERROR level or higher (FATAL).
Inside my log4j2.xml file I seem to be only able to declare the logging level for an entire logger (including all of its appenders). Here is my log4j2.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>%d %level %msg%n</Pattern>
</PatternLayout>
</Console>
<RollingFile name="Log" fileName="log/Log.log" filePattern="log/Log-%d{yyyy-MM-dd}-%i.log" append="false">
<PatternLayout>
<Pattern>%d %level %msg%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="Log" />
</Root>
</Loggers>
</Configuration>
Is there an easy way of doing so? I searched log4j documentation but couldn't find what I was looking for (Maybe I missed it?). If it's possible I would really prefer for the solution to be applicable on any appenders' types; not specific for RollingFile and Console.
EDIT:
I saw many questions where it was asked to write ONLY the messages from a certain level to a file, while writing the messages from a different level to a different file. In my case I need the messages with a certain level of HIGHER to be written to different files. For example in the case I provided messages with level ERROR or FATAL will be written to both the RollingFile and Console, while messages with level INFO will be written to RollingFile only.
To limit logging level on specific appender in log4j2 you should use ThresholdFilter element of an appender.
In your case log4j2.xml file will look like:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<Pattern>%d %level %msg%n</Pattern>
</PatternLayout>
</Console>
<RollingFile name="Log" fileName="log/Log.log" filePattern="log/Log-%d{yyyy-MM-dd}-%i.log" append="false">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<Pattern>%d %level %msg%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="Log" />
</Root>
</Loggers>
</Configuration>
Here is a simple test:
public class Log4jTest {
private static final Logger logger = LogManager.getLogger(Log4jTest.class);
public static void main(String[] args) {
logger.debug("Debug");
logger.info("Info");
logger.warn("Warning");
logger.error("Error");
logger.fatal("Fatal");
}
}
Console output:
2020-02-25 12:33:50,587 ERROR Error
2020-02-25 12:33:50,589 FATAL Fatal
Log.log contents:
2020-02-25 12:33:50,585 INFO Info
2020-02-25 12:33:50,587 WARN Warning
2020-02-25 12:33:50,587 ERROR Error
2020-02-25 12:33:50,589 FATAL Fatal
In first version of log4j it was Threshold property of appender. On how to solve the same in log4j see the answer on question.
With aid of filters Log4j2 allows to configure the output to a specific appender much more flexible then log4j.
This should do the trick.
<Loggers>
<Root level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Root>
<Logger name="com.project.package" level="info" additivity="false">
<AppenderRef ref="Log" />
</Logger>
</Loggers>
Alternatively, you could do it like this - Different level of logs in different log files
BTW, this is explained very nicely in the Log4j2 documentation. See - https://logging.apache.org/log4j/2.x/manual/configuration.html
I'm new to java, and I've written a simple java program to test a few things out before attempting the same things with the more complicated app that I'm almost ready to deploy. I'm using Eclipse, and I've exported the package as a jar file. When I run the jar file, everything appears to be working correctly. Log4j2 is logging properly to the console, and the application is doing what I want it to. The problem I'm having is that the log files are not being created / written to. This all works correctly when I'm running the app from Eclipse. What I was expecting is that I could move the .jar file anywhere I wanted. That I could then execute the app and a logs folder would be created in that same directory and a trace log and an error log would be created and written to.
Here is the log4j2.xml that I'm using:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
<Properties>
<Property name="log-path">logs</Property>
</Properties>
<Appenders>
<Console name="console-log" target="SYSTEM_OUT">
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/>
</Console>
<RollingFile name="trace-log" fileName="${log-path}/logging-trace.log" filePattern="${log-path}/logging-trace-%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"/>
</Policies>
</RollingFile>
<RollingFile name="error-log" fileName="${log-path}/logging-error.log" filePattern="${log-path}/logging-error-%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"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
<AppenderRef ref="console-log"/>
</Root>
<Logger name="multithreadTest" level="info" additivity="false">
<appender-ref ref="trace-log" level="debug"/>
<appender-ref ref="error-log" level="error"/>
<appender-ref ref="console-log" level="debug"/>
</Logger>
</Loggers>
</Configuration>
Here are the contents of the manifest file:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ log4j-api-2.5.jar log4j-core-2.5.jar
Class-Path: .
Rsrc-Main-Class: multithreadTest.RunTest
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
I'm executing the application like this:
java -jar mtest.jar
Any help would be greatly appreciated.
add ref to all your loogers
<Root level="info" additivity="false">
<AppenderRef ref="console-log"/>
<AppenderRef ref="trace-log"/>
<AppenderRef ref="error-log"/>
</Root>
Thanks dom farr. I changed this:
<Logger name="multithreadTest" level="info" additivity="false">
<appender-ref ref="trace-log" level="debug"/>
<appender-ref ref="error-log" level="error"/>
<appender-ref ref="console-log" level="debug"/>
</Logger>
to this:
<Logger name="multithreadTest" level="info" additivity="false">
<AppenderRef ref="trace-log" level="debug"/>
<AppenderRef ref="error-log" level="error"/>
<AppenderRef ref="console-log" level="debug"/>
</Logger>
and it is now working correctly. I'm not sure why. I guess I need to read more about the difference between the two. Not sure why it would work correctly in Eclipse if this is incorrect XML. Anyway, it is working now. Thanks again.