工作生活

2019-07-03 log4j2 自定义ElasticSear

2019-07-03  本文已影响0人  DoubleFooker

简易自定义ElasticSearchAppender

通过自定义appender可实现日志系统日志直接存储到ES

AbstractAppender

log4j2 提供了抽象类AbstractAppender,通过继承抽线类可实现自定义appender

例如:实现ElasticSearchAppender保存日志

@Plugin(name = "EsAppender", category = "Core", elementType = "appender", printObject = true)
public class EsAppender extends AbstractAppender {
    private static String host;
    private static Integer port;
    private static String index;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    protected EsAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions) {
        super(name, filter, layout, ignoreExceptions);
    }
    // 自定义log操作,存储到es
    @Override
    public void append(LogEvent event) {
        JSONObject jsonObject = new JSONObject();
        ThrowableProxy thrownProxy = event.getThrownProxy();
        jsonObject.put("time", sdf.format(new Date()));
        jsonObject.put("className", event.getLoggerName());
        jsonObject.put("methodName", event.getSource().getMethodName());
        jsonObject.put("logMessage", event.getMessage().getFormattedMessage());
        try {
            jsonObject.put("ip", InetAddress.getLocalHost());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        jsonObject.put("logLevel", event.getLevel().name());
        jsonObject.put("logThread", event.getThreadName());
        jsonObject.put("errorMsg", thrownProxy == null ? "" : thrownProxy.getMessage());
        jsonObject.put("exception", thrownProxy == null ? "" : thrownProxy.getName());
        jsonObject.put("stackTrace", thrownProxy == null ? "" : parseException(thrownProxy.getStackTrace()));
        EsClient esClient = new EsClient();
        esClient.send(jsonObject.toJSONString());
    }

    public String parseException(StackTraceElement[] stackTrace) {
        StringBuffer sb = new StringBuffer();
        sb.append("\n");
        Arrays.stream(stackTrace).forEach((e) -> sb.append(e.getClassName()).append(".").append(e.getMethodName()).append("(").append(e.getFileName()).append(":").append(e.getLineNumber()).append(")").append("\n")
        );
        return sb.toString();
    }

    /**
     * 接收配置文件中的参数
     *
     * @param name
     * @param filter
     * @param layout
     * @return
     */
    @PluginFactory
    public static EsAppender createAppender(@PluginAttribute("name") String name,
        @PluginElement("Filter") final Filter filter,
        @PluginElement("Layout") Layout<? extends Serializable> layout,
        @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
        @PluginAttribute("host") String host,
        @PluginAttribute("port") Integer port,
        @PluginAttribute("index") String index
    ) {
        if (name == null) {
            LOGGER.error("No name provided for ESAppender");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        EsAppender.host = host;
        EsAppender.port = port;
        EsAppender.index = index;
        return new EsAppender(name, filter, layout, ignoreExceptions);
    }
}

@Plugin

@Plugin注解实现定义appender名称,即log4j2.xml配置文件中配置时使用的appender名称,例:

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="info" monitorInterval="30">
    <appenders>
        <!--这个输出控制台的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="%{[ %p ] [%-d{yyyy-MM-dd HH:mm:ss}] [%l] %m%n}"/>
        </console>
        <!-- 这个就是自定义的Appender -->
        <EsAppender name="es" >
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%-5p] {%F:%L} - %m%n" />
        </EsAppender>
    </appenders>

    <loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <root level="debug">
            <appender-ref ref="Console"/>
            <appender-ref ref="es"/>
        </root>
    </loggers>
</configuration>

@PluginFactory

插件构建注解,定义创建appender逻辑。通过@PluginAttribute、@PluginElement 定义配置文件可传入的参数值。

append方法

通过重写append方法实现自定义日志操作,例如日志格式化,存储逻辑自定义。

简单的自定义appender实现方式,实际封装还可以考虑异步收集,批量收集、失败重试等功能完善。

上一篇 下一篇

猜你喜欢

热点阅读