简体   繁体   中英

How to escape only message instead of all row in log4j?

I have the following PatternLayout:

public class EscapedEnhancedPatternLayout extends EnhancedPatternLayout {
    @Override
    public String format(LoggingEvent event) {
        return StringEscapeUtils.escapeJava(super.format(event));
    }
}

but this escapes full logging row.

I want to have something like this but only for message.

but LoggingEvent class has not setMessage and setRenderedMessage methods.

And I don't see copy constructor at LoggingEvent . If LoggingEvent had copy constructor I can inherited from LoggingEvent and override methods mentioned below.

Please advise me how to solve my issue.

You're right, there is no LoggingEvent(LoggingEvent other) constructor, but you can pass the event's values to the LoggingEvent constructor in your format method like this:

@Override
public String format(LoggingEvent event) {
    Object msgObj = event.getMessage();

    LoggingEvent newEvent = new LoggingEvent(
        event.getFQNOfLoggerClass(),
        event.getLogger(), event.getTimeStamp(),
        event.getLevel(),
        StringEscapeUtils.escapeJava(msgObj != null ? msgObj.toString() : null),
        event.getThreadName(),
        event.getThrowableInformation(),
        event.getNDC(),
        event.getLocationInformation(),
        event.getProperties());

    return super.format(newEvent);
}

This will create a new LoggingEvent from the old one with all values set. The StringEscapeUtils.escapeJava method can now modify the the message without affecting the other properties and you can still use super.format

An alternative approach could be to create a customized LogEventFactory . A LogEventFactory is used to generate LogEvents. Applications may replace the standard LogEventFactory by setting the value of the system property Log4jLogEventFactory to the name of the custom LogEventFactory class.

The method that will be called to create a instance of LogEvent is as follows:

LogEvent createEvent(String loggerName,
               org.apache.logging.log4j.Marker marker,
               String fqcn,
               org.apache.logging.log4j.Level level,
               org.apache.logging.log4j.message.Message data,
               List<Property> properties,
               Throwable t)

and DefaultLogEventFactory is the basic implementation for log4j. In your case you could extend the basic implementation and escape the message after which you call the default implementation. It would become something like this:

public class MyCustomLogEventFactory extends DefaultLogEventFactory {

    /**
     * Creates a log event.
     *
     * @param loggerName The name of the Logger.
     * @param marker An optional Marker.
     * @param fqcn The fully qualified class name of the caller.
     * @param level The event Level.
     * @param data The Message.
     * @param properties Properties to be added to the log event.
     * @param t An optional Throwable.
     * @return The LogEvent.
     */
     @Override
    public LogEvent createEvent(final String loggerName, final Marker marker,
                             final String fqcn, final Level level, final Message data,
                             final List<Property> properties, final Throwable t) {
        super.createEvent(loggerName, marker, fqcn, level, StringEscapeUtils.escapeJava(data != null ? data.toString() : null), properties, t);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM