헤르메스 LIFE

[Logging] Log4j, Logback, Log4j2 로 MyBatis SQL 쿼리 남기기 본문

Spring Framework

[Logging] Log4j, Logback, Log4j2 로 MyBatis SQL 쿼리 남기기

헤르메스의날개 2021. 6. 17. 00:47
728x90

사용자 Appender 생성

아래 링크를 보면 Customer Appender 를 생성할 수 있는 소스가 있습니다.

이 Customer Appender가 왜 필요하냐면... 모든 Log 를 걸러낼 수 있기 때문입니다.

MyBatis Query Log 까지도 확인할 수 있습니다.

        <Logger name="jdbc.sqltiming" level="INFO" additivity="false">
            <AppenderRef ref="sqlLog" />
            <AppenderRef ref="RollingFile" />
        </Logger>
        <Logger name="jdbc.sqlonly" level="INFO" additivity="false">
            <AppenderRef ref="console" />
            <AppenderRef ref="sqlLog" />
        </Logger>

 


package com.github.dadiyang.appender;


import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;

/**
 * @author dadiyang
 * @since 2019/4/30
 */
public class Log4jAppender extends AppenderSkeleton {
    private String appName;

    @Override
    protected void append(LoggingEvent event) {
        if (event == null || event.getMessage() == null) {
            return;
        }
        // 必须设置 appName
        if (appName == null || appName.isEmpty()) {
            return;
        }
        String level = event.getLevel().toString();
        String loggerName = event.getLoggerName();
        String msg = event.getRenderedMessage();
        String threadName = event.getThreadName();
        Throwable throwable = event.getThrowableInformation() != null ? event.getThrowableInformation().getThrowable() : null;
        // todo 这里实现自定义的日志处理逻辑
        System.out.println(appName + ": 自定义 log4j appender, threadName: " + threadName + ", level: " + level + ", loggerName: " + loggerName + ", msg: " + msg);
        if (throwable != null) {
            throwable.printStackTrace();
        }
    }

    @Override
    public void close() {

    }

    @Override
    public boolean requiresLayout() {
        return false;
    }

    /**
     * 定义 setter 方法,这样在配置文件中添加类似 log4j.appender.CustomAppender.appName=test_app_name 的配置项时,配置会被注入到这个 appender 中
     */
    public void setAppName(String appName) {
        this.appName = appName;
    }
}
package com.github.dadiyang.appender;

import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;

import java.io.Serializable;

/**
 * 自定义实现log4j2的输出源
 *
 * @author dadiyang
 * @since 2019/4/30
 */
@Plugin(name = "Log4j2Appender", category = "Core", elementType = "appender", printObject = true)
public final class Log4j2Appender extends AbstractAppender {
    private String appName;

    protected Log4j2Appender(String name, String appName, Filter filter, Layout<? extends Serializable> layout,
                             final boolean ignoreExceptions) {
        super(name, filter, layout, ignoreExceptions);
        this.appName = appName;
    }

    @Override
    public void append(LogEvent event) {
        if (event == null || event.getMessage() == null) {
            return;
        }
        // 必须设置 appName
        if (appName == null || appName.isEmpty()) {
            return;
        }
        // 此处自定义实现输出
        String level = event.getLevel().toString();
        String loggerName = event.getLoggerName();
        String msg = event.getMessage().getFormattedMessage();
        String threadName = event.getThreadName();
        Throwable throwable = event.getThrown();
        // todo 这里实现自定义的日志处理逻辑
        System.out.println(appName + ": 自定义 log4j2 appender, threadName: " + threadName + ", level: " + level + ", loggerName: " + loggerName + ", msg: " + msg);
        if (throwable != null) {
            throwable.printStackTrace();
        }
    }

    /**
     * log4j2 使用 appender 插件工厂,因此传参可以直接通过 PluginAttribute 注解注入
     */
    @PluginFactory
    public static Log4j2Appender createAppender(
            @PluginAttribute("name") String name,
            @PluginAttribute("appName") String appName,
            @PluginElement("Layout") Layout<? extends Serializable> layout,
            @PluginElement("Filter") final Filter filter) {
        if (name == null) {
            LOGGER.error("No name provided for Log4j2Appender");
            return null;
        }
        if (appName == null) {
            LOGGER.error("配置日志自定义 Appender 必须设置 appName 属性!!");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new Log4j2Appender(name, appName, filter, layout, true);
    }

}
package com.github.dadiyang.appender;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.AppenderBase;

/**
 * 自定义实现logback的输出源
 *
 * @author dadiyang
 * @since 2019/4/30
 */
public class LogbackAppender extends AppenderBase<ILoggingEvent> {
    private String appName;

    @Override
    protected void append(ILoggingEvent event) {
        if (event == null || event.getMessage() == null) {
            return;
        }
        // 必须设置 appName
        if (appName == null || appName.isEmpty()) {
            return;
        }
        String level = event.getLevel().toString();
        String loggerName = event.getLoggerName();
        String msg = event.getFormattedMessage();
        String threadName = event.getThreadName();
        Throwable throwable = event.getThrowableProxy() != null ? ((ThrowableProxy) event.getThrowableProxy()).getThrowable() : null;
        // todo 这里实现自定义的日志处理逻辑
        System.out.println(appName + ": 自定义 logback appender, threadName: " + threadName + ", level: " + level + ", loggerName: " + loggerName + ", msg: " + msg);
        if (throwable != null) {
            throwable.printStackTrace();
        }
    }

    /**
     * 定义 setter 方法,这样配置项会被注入到这个 appender 中
     */
    public void setAppName(String appName) {
        this.appName = appName;
    }
}

https://github.com/dadiyang/appender

 

dadiyang/appender

自定义的 log4j、log4j2 和 logback 等日志框架的 Appender 示例. Contribute to dadiyang/appender development by creating an account on GitHub.

github.com

 

728x90