1

We have a huge application using our custom RollingFileAppender (extended from org.apache.log4j.RollingFileAppender in log4j 1.x). We have overridden few methods, but two major methods are rollOver() and subAppend() as follows:

    public void rollOver()
    {
        // Custom Code to specify how rolled-over files should be numbered and which file should be 
        // overwritten when MaxBackupIndex is reached
    }

    public void subAppend(LoggingEvent event)
    {
       // Custom Code to encrypt message before writing it
       String data = this.layout.format(event);
       if (isEncryptionOn())
        {
            data = PlatformEncryptDecrypt.encrypt2Way(data);
            data = toUnicodeHexString(data);
        }
        this.qw.write(data);
        .
        .
        .
        // Other code taken from parent class
        .
        .
        .
    }

While migrating this to log4j2, I want to leverage log4j2's RollingFileAppender as much as possible, while overriding only selected methods. Since RollingFileAppender is final class, I would prefer to use builder for creating custom appender. I went through few other similar posts, but they are talking about logging few extra attributes with RollingFileAppender.

What would be the best way to achieve this using current latest version of log4j2 i.e. 2.13? Any help is highly appreciated.

keenUser
  • 1,279
  • 3
  • 16
  • 33

1 Answers1

1

If you are just wanting to encrypt the data then don't override the RollingFileAppender. Implement your own Layout instead. In fact, I would be open to adding an EncryptingLayout that wraps another Layout if you would create a Jira issue with your requirements.

In the meantime, just create a Layout that accepts another Layout as a configuration attribute. Then the methods in your Layout call that Layout's corresponding method and then encrypt the result.

rgoers
  • 8,696
  • 1
  • 22
  • 24
  • What about rollover() method? Is it advisable to do something along the lines of https://stackoverflow.com/questions/30412710/how-to-create-a-rolling-file-appender-plugin-in-log4j2 this post? – keenUser Dec 24 '19 at 06:31
  • That would depend on why you feel you need to do it. If it is just for encryption then my advice above still stands. Create a Layout. – rgoers Dec 27 '19 at 15:00
  • Could you please give an example of how can I create a wrapper on top of PatternLayout? I would want to have all of its functionality, while only encrypting the message as part of toSerializable() method I guess? – keenUser Dec 31 '19 at 14:51
  • 1
    If you only want to encrypt just the message using PatternLayout then you would create a PatternConverter and use it like %encrypt(%msg). See https://github.com/apache/logging-log4j2/blob/master/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverter.java for an example. The main difference would be you would encrypt the data in the StringBuilder instead of doing a regex replacement. – rgoers Jan 02 '20 at 05:18
  • Thanks a lot. I could successfully create a PatternConverter which would encrypt just the message conditionally (based on whether encryption setting is ON or OFF). However, since I have a bunch of ThreadContext Attributes used into log pattern, parsing the pattern string would create around 25-30 tokens (PatternFormatters). Substituting these tokens for each log statement would be a performance hit, isn't it?...... (continued in next comment) – keenUser Jan 02 '20 at 15:17
  • Moreover, these operations are needless when encryption settings are off. So, if I say rather than encrypting only msg, I would like to encrypt entire pattern string. I can do this using custom layout's toSerializable() method. Which way should I go to get minimum performance hit? Your help is highly appreciated. – keenUser Jan 02 '20 at 15:17
  • 1
    You can certainly do either depending on your needs. However, there is no reason your pattern converter couldn't wrap the whole pattern so as to encrypt the whole string instead of just the message. Also, you should look at the PatternSelector. It allows different patterns to be used based on conditions. – rgoers Jan 08 '20 at 03:03