Same log4j2.xml for different java processes with separate log level - java

Problem
I want to standardize my log4j2.xml setup for several Java processes that I run on different linux servers. My hard condition: a single log4j2.xml for all servers.
Sometimes it is needed that I change my loglevel from INFO to DEBUG while the Java process is running. You can do this by changing the logLevel in the log4j2.xml, while you have monitorInterval configured.
However, this changes the loglevel of ALL processes that are running on that server! I need a solution that I can change the logLevel for a single process.
My first try
I thought that I would move the logLevel to the properties. Suppose I have the log4j2.xml (as an example):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Configuration monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %t %-5p %-32c{1} - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="${bundle:logger:logLevel}">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Next to this, I also have the file logger.properties on the classpath:
logLevel=INFO
Now when I change my log4j2.xml (by just adding a space somewhere) and updating this property file, the logging changes. However, as mentioned it changes the logLevel of ALL processes.
What I want
I want to be able to have a logger.properties that looks like this:
process1LogLevel=INFO
process2LogLevel=DEBUG
And then something in the log4j2.xml that configures this property dynamically:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Configuration monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %t %-5p %-32c{1} - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="${bundle:logger:<something based on the process name>}">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
However, this "flexible" property doesn't really work. Do you have any idea for a solution?
Note
If you have a different idea that looks a little bit different but achieves my goals, that is also fine! Any out-of-the-box solution is always appreciated :)

Found it. You can nest properties. If you specify -Dname=process1 for example, you can use it like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Configuration monitorInterval="1">
<Properties>
<Property name="process1">DEBUG</Property>
<Property name="process2">INFO</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %t %-5p %-32c{1} - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="${${sys:name}}">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

Related

Log4j doesn't display process PID

I just installed and configured log4j.
It works, but doesn't show process PID, instead prints ${sys:PID} instead of, for example, 12941.
My log4j-config:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout
disableAnsi="false"
pattern="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %highlight{${LOG_LEVEL_PATTERN:-%5p}}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} %style{${sys:PID}}{magenta} --- [%15.15t] %style{%-40.40C{1.}}{cyan} : %m%n%ex"/>
</Console>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
And
console output
So, how can I fix this?
I replaced sys:PID with %pid and it started working.
I took that from github issue

Issue in log4j2 Custom Filter

I am trying to implement custom filter as mentioned in post Log4j2 custom filter .My lo4j2.xml is as follows
<?xml version="1.0" encoding="UTF-8"?>
<!-- Logger configuration when running outside of docker -->
<Configuration status="trace" packages=“com.rest.server_common.logging">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p [%t] %c{1}:%L - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="DEBUG">
<com.rest.server_common.logging.MyCustomFilter level="DEBUG"/>
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
When I start my jetty server,I get the error
main ERROR Root contains an invalid element or attribute "com.rest.server_common.logging.MyCustomFilter"
What is the problem here?
I have even tried moving filter line
<com.rest.server_common.logging.MyCustomFilter level="DEBUG"/>
after Configuration element but I still get the error
Just to close.The package was in different module so the filter was not getting recognised.

Can you redirect stdout, stderr to a fileappender in log4j2 v2.3?

This is my log4j2.xml configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT" ignoreExceptions="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="Log4JFile" fileName="/log/Log4JFile.log">
<PatternLayout>
<Pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="Console"/>
<AppenderRef ref="Log4JFile"/>
</Root>
</Loggers>
</Configuration>
I'm using Jboss and if you do not include a configuration file, log4j logs everything to server.log. I need to log all of the levels of log4j plus stdout and stderr to a separate file that is not the default one. How can I accomplish this without overriding the print method in Java?
You cannot redirect from the Log4j ConsoleAppender to a Log4j FileAppender.
What you can do is in the scripts/commands that start your application, redirect the output of that command to a file. The syntax for this is OS dependent but usually looks something like command > file. Multiple > characters can append to an existing file rather than overwrite it. (Also OS dependent.)

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.

How to write logs to two different loggers?

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.

Categories

Resources