spring-bootlog4j

Extend Log4j to capture log arguments


I aim to extend log4j in Spring Boot 3 to intercept log arguments and hide sensitive data when logging automatically. Since I had a difficult time to find a solution, I am opening and answering my own question, hoping it will help someone else.


Solution

  • Add the dependency org.apache.logging.log4j:log4j-api:2.24.2.

    Then create a custom LogFactory class by extending org.apache.logging.log4j.message.MessageFactory2 and implement all the methods (yes, they are many but implementation is easy). Example:

    class MyLogFactory : MessageFactory2 {
    
      override fun newMessage(charSequence: CharSequence?): Message {
        return charSequence?.let {
          ParameterizedMessage(it.toString())
        } ?: ParameterizedMessage("")
      }
    
      override fun newMessage(message: String?, p0: Any?): Message {
        return ParameterizedMessage(
          message,
          hideSensitiveData(arrayOf(p0))
        )
      }
    
      override fun newMessage(message: String?, p0: Any?, p1: Any?): Message {
        return ParameterizedMessage(
          message,
          hideSensitiveData(arrayOf(p0, p1))
        )
      }
    
      // and so on
    }
    
    

    Then when creating the logger, specific to use the custom LogFactory:

    Logger log = LogManager.getLogger(MyCurrentClass.class, new MyLogFactory());
    

    If you prefer to use the custom log factory by default for any class, then you can specify it by defining a file under resources named log4j2.properties:

    log4j2.loggerFactory=com.example.MyLogFactory