LOG4J: Modify logged message using custom appender

前端 未结 4 593
一生所求
一生所求 2020-12-01 06:41

For security reasons, I need to look at every logged message in my app and possibly modify it before it goes to the log file. I figured I could write a custom appender (exte

4条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-01 07:40

    I'm not entirely sure why creating a new LoggingEvent is so onerous. This seems to work for me:

    package test.logging;
    
    import org.apache.log4j.DailyRollingFileAppender;
    import org.apache.log4j.spi.LoggingEvent;
    
    public class MyDailyRollingFileAppender extends DailyRollingFileAppender {
    
        @Override
        protected void subAppend(LoggingEvent event) {
            String modifiedMessage = String.format("**** Message modified by MyDailyRollingFileAppender ****\n\n%s\n\n**** Finished modified message ****", event.getMessage());
            LoggingEvent modifiedEvent = new LoggingEvent(event.getFQNOfLoggerClass(), event.getLogger(), event.getTimeStamp(), event.getLevel(), modifiedMessage,
                                                          event.getThreadName(), event.getThrowableInformation(), event.getNDC(), event.getLocationInformation(),
                                                          event.getProperties());
    
            super.subAppend(modifiedEvent);
        }
    
    }
    

    With this test:

    package test;
    
    import org.apache.log4j.Logger;
    
    public class TestLogging {
    
        public static void main(String[] args) {
            Logger log = Logger.getLogger(TestLogging.class);
            log.info("I am testing my logging");
            log.info("Here is an exception", new Exception());
        }
    
    }
    

    and this configuration:

    
    
    
    
    
        
            
            
            
            
                
            
        
    
        
            
            
        
    
    
    

    I am getting the following output:

    2011-10-14 10:09:09,322 INFO  () [main] TestLogging - **** Message modified by MyDailyRollingFileAppender ****
    
    I am testing my logging
    
    **** Finished modified message ****
    2011-10-14 10:09:09,333 INFO  () [main] TestLogging - **** Message modified by MyDailyRollingFileAppender ****
    
    Here is an exception
    
    **** Finished modified message ****
    java.lang.Exception
        at test.TestLogging.main(TestLogging.java:10)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
    

    Although I have done something similar to this, I used a slightly different approach. Instead of writing subclasses of each type of Appender I wanted to use, I created an Appender which wraps other Appender objects, and modifies the message before sending to the wrapped Appenders. Something like this:

    package test.logging;
    
    import org.apache.log4j.Appender;
    import org.apache.log4j.AppenderSkeleton;
    import org.apache.log4j.spi.AppenderAttachable;
    import org.apache.log4j.spi.LoggingEvent;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Enumeration;
    import java.util.Iterator;
    import java.util.List;
    
    public class MyAppenderWrapper extends AppenderSkeleton implements AppenderAttachable {
    
        private final List appenders = new ArrayList();
    
        public void close() {
            synchronized (appenders) {
                for (Appender appender : appenders) {
                    appender.close();
                }
            }
        }
    
        public boolean requiresLayout() {
            return false;
        }
    
        public void addAppender(Appender appender) {
            synchronized (appenders) {
                appenders.add(appender);
            }
        }
    
        public Enumeration getAllAppenders() {
            return Collections.enumeration(appenders);
        }
    
        public Appender getAppender(String name) {
            synchronized (appenders) {
                for (Appender appender : appenders) {
                    if (appender.getName().equals(name)) {
                        return appender;
                    }
                }
            }
            return null;
        }
    
        public boolean isAttached(Appender appender) {
            synchronized (appenders) {
                for (Appender wrapped : appenders) {
                    if (wrapped.equals(appender)) {
                        return true;
                    }
                }
                return false;
            }
        }
    
        public void removeAllAppenders() {
            synchronized (appenders) {
                appenders.clear();
            }
        }
    
        public void removeAppender(Appender appender) {
            synchronized (appenders) {
                for (Iterator i = appenders.iterator(); i.hasNext(); ) {
                    if (i.next().equals(appender)) {
                        i.remove();
                    }
                }
            }
        }
    
        public void removeAppender(String name) {
            synchronized (appenders) {
                for (Iterator i = appenders.iterator(); i.hasNext(); ) {
                    if (i.next().getName().equals(name)) {
                        i.remove();
                    }
                }
            }
        }
    
        @Override
        protected void append(LoggingEvent event) {
            String modifiedMessage = String.format("**** Message modified by MyAppenderWrapper ****\n\n%s\n\n**** Finished modified message ****", event.getMessage());
            LoggingEvent modifiedEvent = new LoggingEvent(event.getFQNOfLoggerClass(), event.getLogger(), event.getTimeStamp(), event.getLevel(), modifiedMessage,
                                                          event.getThreadName(), event.getThrowableInformation(), event.getNDC(), event.getLocationInformation(),
                                                          event.getProperties());
    
            synchronized (appenders) {
                for (Appender appender : appenders) {
                    appender.doAppend(modifiedEvent);
                }
            }
        }
    
    }
    

    Which you could configure like:

    
    
    
    
    
        
            
                
            
        
    
        
            
            
            
            
                
            
        
    
        
            
            
        
    
        
            
            
        
    
    
    

    That way the message is still sent to the original appenders but with the modified message.

提交回复
热议问题