How to configure log4j2 RollingFileAppender?

We use log4j 1.2.x to enter our product and want to upgrade to log4j 2.x in the near future. One of the functionality that we have implemented is to register system information and other important parameters on each new minimized log file that is generated. The way we implemented in log4j 1.2.x is that we extended the RollingFileAppender class and redefined the rollOver() method, below is a snippet of the implementation fragment

 @Override public void rollOver() { super.rollOver(); //We are not modifying it default functionality but as soon as rollOver happens we apply our logic // // Logic to log required system properties and important parameters. // } 

Now that we want to switch to log4j2, we are considering a new solution to achieve the same functionality. But since I see the source code for log4j2, it is very different from the old source code. The RollingFileAppender class RollingFileAppender not contain the rollOver() method, since it was moved to the RollingManagerhelper , and it was set to private as-well.

Developing a complete new package and extending / implementing some abstract / helper classes from log4j2 is one of the possible solutions for us, but this will require a lot of coding / copying, since we are not modifying what RollingFileAppender does most likely only require a small extension. Is there a simple solution?

UPDATE

I created a custom search according to the sentence in the answers and below how I created it;

 @Plugin(name = "property", category = StrLookup.CATEGORY) public class CustomLookup extends AbstractLookup { private static AtomicLong aLong = new AtomicLong(0); @Override public String lookup(LogEvent event, String key) { if (aLong.getAndIncrement() == 0) { return "this was first call"; } if (key.equalsIgnoreCase("customKey")) { return getCustomHeader(); } else { return "non existing key"; } } private static String getCustomHeader() { // Implementation of custom header return "custom header string"; }} 

But this did not work, as mentioned; it always prints this was first call in the header. I also tried to put a breakoint in the first if state, and I noticed that it gets only once. Therefore, I am afraid that the customLookup class is initialized only at startup, when log4j2 initializes its properties from xml config. I do not know how else I could implement this custom search class.

UPDATE 2

After the implementation described above, I tried it differently, as shown below:

 private static AtomicLong aLong = new AtomicLong(0); @Override public String lookup(LogEvent event, String key) { return getCustomHeader(key); } private static String getCustomHeader(final String key) { if (aLong.getAndIncrement() == 0) { return "this was first call"; } if (key.equalsIgnoreCase("customKey")) { // Implementation for customKey return "This is custom header"; } else { return "non existing key"; } } 

But it does the same as ... well. log4j2 creates headers on initialization from its xml configuration file and then uses headers from memory. The return value of the overridden lookup() method cannot be changed dynamically, since it is only called during initialization. Any help would be greatly appreciated.

+5
source share
2 answers

An alternative to using inline queries is to create a custom search. This can be done in a few lines of code with the log4j2 plugin. Then your custom search provides the exact value that you want to show in the file header with each transition.

The plugin code will look something like this:

 package com.mycompany; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.lookup.AbstractLookup; import org.apache.logging.log4j.core.lookup.StrLookup; /** * Looks up keys from a class SomeClass which has access to all * information you want to provide in the log file header at rollover. */ @Plugin(name = "setu", category = StrLookup.CATEGORY) public class SetuLookup extends AbstractLookup { /** * Looks up the value of the specified key by invoking a * static method on SomeClass. * * @param event The current LogEvent (ignored by this StrLookup). * @param key the key to be looked up, may be null * @return The value of the specified key. */ @Override public String lookup(final LogEvent event, final String key) { return com.mycompany.SomeClass.getValue(key); } } 

Then in your configuration, you can use the template layout header to display this every time you scroll:

 <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}.log.gz"> <!-- use custom lookups to access arbitrary internal system info --> <PatternLayout header="${setu:key1} ${setu:key2}"> <Pattern>%d %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> </Policies> </RollingFile> 

The log4j2 user guide provides information on creating / deploying custom plugins . Short summary:

The easiest way is to build your own jar with Maven; this will cause the log4j2 annotation processor to create a binary index file in the bank so that your plugin can be quickly found using log4j2.

An alternative is to specify the package name of your plugin class in the packages attribute of the log4j2.xml configuration:

 <Configuration status="warn" packages="com.mycompany"> ... 

UPDATE: note that in the search implementation you can get as creative as possible. For instance:

 package com.mycompany; public class SomeClass { private static AtomicLong count = new AtomicLong(0); public static String getValue(final String key) { if (count.getAndIncrement() == 0) { // is this the first call? return ""; // don't output a value at system startup } if ("FULL".equals(key)) { // returns info to shown on rollover, nicely formatted return fullyFormattedHeader(); } return singleValue(key); } .... } 
+5
source

This can be done through configuration. You can use the template template header to display information. This will be included in each survey.

 <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}.log.gz"> <!-- use built-in lookups for system info or system properties --> <PatternLayout header="${java:runtime} - ${java:vm} - ${java:os}"> <Pattern>%d %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> </Policies> </RollingFile> 
+2
source

Source: https://habr.com/ru/post/1208253/


All Articles