0

I need to get a username parameter to my ConsoleAppender in every LoggingEvent (or LogEvent in log4j2).

How can I recreate this implementation of altering the doAppend method of my CustomConsoleAppender in log4j when migrating to log4j2:

public class CustomConsoleAppender extends ConsoleAppender
{
    public void doAppend(LoggingEvent event)
    {
        String username = SecurityContextHelper.getLogonUsername();
        if (username != null)
            MDC.put("userId", username);
        else
            MDC.put("userId", "system");
        super.doAppend(event);
    }
}

The value is then retrieved in the log4j2.properties in the PatternLayout of the corresponding appender by using the pattern: %X{userId}

  • Why don't you just call `ThreadContext#put` in a [`ServletRequestListener`](https://jakarta.ee/specifications/platform/8/apidocs/javax/servlet/servletrequestlistener)? This way you can just use the standard Log4j 2.x components. – Piotr P. Karwasz Jan 12 '22 at 15:13

1 Answers1

0

Found a solution here: https://stackoverflow.com/a/45039509/17913034

By using the LogEventFactory (see implementation details in solution 2 of the link above) and also replacing MDC with ThreadContext (because of log4j2):

public class MyLogEventFactory implements LogEventFactory {

@Override
public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message message,
        List<Property> properties, Throwable t) {
    { // In my case i wanted "log.error(new Exception(msg))"
      // to pass the exception properly to the event,
      // as if "log.error(msg, new Exception(msg))" was called.
        if (t == null && message instanceof ObjectMessage) {
            ObjectMessage msg = (ObjectMessage) message;
            t = msg.getThrowable();
        }
    }
    // my adjustments here:
    String username = SecurityContextHelper.getLogonUsername();
        if (username != null)
            ThreadContext.put("userId", username);
        else
            ThreadContext.put("userId", "system");
        return new Log4jLogEvent(loggerName, marker, fqcn, level, message, properties, t);
    }

}