Search code examples
logginglogbackslf4jembedded-jetty

How to Log HTTP GET and HTTP Post to separate files


How can I log HTTP @GET and @POST to separate files. Basically we just want to have separate log files for read ( GET) and write( PUT, POST , DELETE). I and using Slf4j with logback with embedded jetty.

one solution is to have two loggers in class and use them accordingly . i.e.

private final static Logger log = LoggerFactory.getLogger(Controller.class);
private final static Logger writeLog = LoggerFactory.getLogger("WRITE");

Now as per the requirement use the above logger, Define Appender and Logger.

<appender name="APPENDER_READ"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${HOME}/logs/read.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>read.%i.log.zip</fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>3</maxIndex>
        </rollingPolicy>
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
            <pattern>%date{YYYY-MM-dd HH:mm:ss} %level [%thread] %X{TaskKey} %msg%n</pattern>
        </encoder>
    </appender>



 <appender name="APPENDER_WRITE"
            class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${HOME}/logs/write.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
                <fileNamePattern>logs/write.%i.log.zip</fileNamePattern>
                <minIndex>1</minIndex>
                <maxIndex>3</maxIndex>
            </rollingPolicy>
            <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
                <maxFileSize>5MB</maxFileSize>
            </triggeringPolicy>
            <encoder>
                <pattern>%date{YYYY-MM-dd HH:mm:ss} %level [%thread] %X{TaskKey} %msg%n</pattern>
            </encoder>
        </appender>


    <logger name="WRITE" level="warn" additivity="false">
        <appender-ref ref="APPENDER_WRITE" />
    </logger>


    <root level="WARN">
        <appender-ref ref="APPENDER_READ" />
    </root>

But I am looking for some better solution that can start logging not from controller but from the Handler level ( as soon as request enters).


Solution

  • You should put the request method (GET, POST, etc...) into Logback's MDC (mapped diagnostic context). Indeed, you should do this as early as possible, for example in a Filter, like this:

    import javax.servlet.Filter;
    
    import org.slf4j.MDC;
    
    public class MDCFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            MDC.put("METHOD", ((HttpServletRequest)req).getMethod());
            try {
                chain.doFilter(req, resp);
            } finally {
                MDC.remove("METHOD");
            }
        }
    }
    

    Then you can direct logging into different files based on the value of the MDC key 'METHOD' with Logback's SiftingAppender.

    Very good example for that: https://www.mkyong.com/logging/logback-different-log-file-for-each-thread/ (just use 'METHOD' instead of 'logFileName')