How to write logs to two different loggers? - java

Im able to create two logs using log4j2 and im able to write the log to a single log file. how to write logs to a two different loggers?
i modified the log4j2.xml file to have two loggers.
Any sample example?

Instead of configuring multiple loggers, you may want to configure multiple appenders. Example:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
<File name="Other" fileName="logs/other.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="MyFile" level="trace"/>
<AppenderRef ref="Other" level="debug"/>
</Root>
</Loggers>
</Configuration>

Point 1
I guess you're asking to write one log into different destinations, ex. different files. As Remko has mentioned, you could configure different appenders to handle each of the log file.
As I don't have enough reputations for commenting Remko's answer, here're some of my additional examples:
If you use the level of DEBUG for your logs, calling logger.debug("your message") and configure your log4j2.xml like the below, you'll see "your message" logged in both file1.log and file2.log.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="File1" fileName="logs/file1.log">
<PatternLayout>
<Pattern>"Add your pattern here"</Pattern>
</PatternLayout>
</File>
<File name="File2" fileName="logs/file2.log">
<PatternLayout>
<Pattern>"Add your pattern here"</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="debug">
<!--This will write the same log into both of the files -->
<AppenderRef ref="File1" level="debug"/>
<AppenderRef ref="File2" level="debug"/>
</Root>
</Loggers>
</Configuration>
Point 2
we should notice that, in Remko's example, all logs go into Other will also be written into MyFile. See more in Log4j2 Documentation, example 6 for explaination. In short, as TRACE is a lower lever than DEBUG, all logs with DEBUG levels could be passed in TRACE and logged.
Point 3
Another possibility of writing into different destinations is through Appender Additivity.
Each enabled logging request for a given logger will be forwarded to
all the apprenders in that Logger's LoggerConfig as well as the
Apprenders of the LoggerConfig's parents.

Related

Log4j set a different logging level for each appender

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

How to configure java application having 2 log4j2.xml files so that both configurations work fine

We are running a Java file named Calc.java and for this application, we are using log4j2.xml file for logging to a file named LogCalc.txt. Our Calc.java is using a .jar file named Addition.Jar, which is composed of Add.java, which also uses log4j2.xml file for its own logging to a file named LogAdd.txt.
The question here is, when we run Calc.java and access a method from Addition.Jar, logging is only happening in LogCalc.txt, the configurations in log4j2.xml of Calc.java is taken into account and log4j2.xml of LogAdd.txt is not taken into account. Due to this I am not able to get logs from Addition.jar, LogAdd.txt is empty.
How can we change our configurations such that we can see both logs from Calc.java in LogCalc.txt as well as from Add.java in LogAdd.txt, i.e., both XML configurations must work fine in our application and both of them logging to different files with their own configurations taken from respective XML files).
Our aim here is to make a project where main app uses log4j2.xml and also the included .jar in this project is using log4j2.xml, but we should get logs from both of them to their respective appenders separately without any problem.
Our Xml files look like this. log4j2.xml used in Addition.jar is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="A1" fileName="A1.log" append="false">
<PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="debug">
<AppenderRef ref="A1"/>
</Logger>
<Root level="warn">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
The log4j2.xml file used with Calc.java is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="A1" fileName="A1.log" append="false">
<PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="debug">
<AppenderRef ref="A1"/>
</Logger>
<Root level="info">
<AppenderRef ref="A1"/>
</Root>
</Loggers>
</Configuration>
Log4j will locate the first log4j2.xml that it finds on the classpath and use that for configuration. It does not currently support multiple configurations, although work is in progress to allow it to. Even if it did it would not work the way your configuration won't work because the loggers are the same.
I suggest you review the log4j guide online. Log4j does not log on the basis of jar files but by comparing the names of the loggers you are using against what is configured. If you want everything in one jar to go to one file then use a logger name such as Calc for the first jar and a logger name of LogCalc for the second jar. Then have your configuration route the events for each of the loggers to the appropriate files.

Convert log4j 1.2 configuration related to JUL to log4j 2 configuration

I'm converting an application from log4j 1.2 to log4j2. In the log4j.properties file I found follwoing configurations which relats to Java util logging.
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=SEVERE
How can I convert this configurations to log4j2 configuration ?
Thanks!
Log4j2 provides a bridge to route all calls to the java.util.logging API to Log4j2. To activate this, set the system property java.util.logging.manager to org.apache.logging.log4j.jul.LogManager and add the Log4j2 JUL adapter jar to your classpath (see "which jars FAQ").
Then you configure log4j2 as usual. The log4j2 manual provides many example configurations.
The configuration snippet you provide might translate to something like the below (I added a FileAppender as an example).
<Configuration status="warn"><!-- use status="trace" for troubleshooting -->
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
<File name="FILE" fileName="myapp.log">
<PatternLayout>
<pattern>%d %p [%t] %c{1.} %m%n</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="STDOUT" level="ERROR" />
<AppenderRef ref="FILE" />
</Root>
</Loggers>
</Configuration>

Log4j2 Silence specific package

I've just updated to Log4. Now i have some small issues configurating my new setup.
The log4j2.xml is quite small and simple, but i'm not sure how i can disable logs (or at least set them to ERROR) for all jersey packages.
Here's my log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
</Console>
<File name="FILE" fileName="/logs/m2m/error.log">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
</File>
<Async name="ASYNC">
<AppenderRef ref="FILE" />
<AppenderRef ref="CONSOLE" />
</Async>
</Appenders>
<Loggers>
<Logger name="org.glassfish.jersey.servlet" level="ERROR" additivity="false">
<AppenderRef ref="ASYNC" />
</Logger>
<Root level="DEBUG">
<AppenderRef ref="ASYNC" />
</Root>
</Loggers>
</Configuration>
And here's the log-output i try to silence:
Jan 24, 2014 8:21:12 AM org.glassfish.jersey.servlet.WebComponent filterFormParameters
WARNING: A servlet request to the URI #### contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
Thanks
Based on the format of the output I suspect that the log output shown above is actually produced by JUL (java.util.logging) and not by log4j.
It is possible to route calls made to the java.util.logging API to the log4j2 implementation. Your log4j2 configuration (which looks correct) should then filter out WARN-level log events emitted by any class in the org.glassfish.jersey.servlet package.
This involves adding a few more jars to the classpath: see the FAQ.
If you want to do with Logback, here I explain how to do it:
Excessive warning messages from Jersey 2.x

Log4j2 saving file (using RollingFile appender)

I am trying log4j2 to create log file to the system I am developing right, I have followed the instruction on their site and there is no error occurred when I run it, but the log is not saved on where I set it (ex. "D:\logs\app.log").
Here is My log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="OFF">
<appenders>
<RollingFile name="MyRollingFile" fileName="D:/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>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</appenders>
<loggers>
<logger name="Log_RollingFile" level="TRACE" additivity="false">
<appender-ref ref="MyRollingFile"/>
</logger>
<root level="ERROR">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
I tried to :
delete app.log to see if my configuration (D:\logs\app.log) works. When I run the application it creates app.log so I think it means that it sees the configuration and the only thing is it is NOT SAVING the log.info that I did in java application
Change root level to "TRACE", and it prints the log.info.
[EDIT:]
I have also these libraries on my classpath
log4j-api-2.0-beta3.jar
log4j-core-2.0-beta3.jar
Am I missing something on RollingFile configuration or a library (maybe)?
Thanks in advance.
Your logger name is incorrect.
As explained in the configuration instructions you linked to, the logger should be named according to the package/classes you wish to capture logging for.
In their example the logger named com.foo.Bar would log everything from the Bar class in package com.foo with TRACE level.

Categories

Resources