簡(jiǎn)易自定義ElasticSearchAppender
通過(guò)自定義appender可實(shí)現(xiàn)日志系統(tǒng)日志直接存儲(chǔ)到ES
AbstractAppender
log4j2 提供了抽象類(lèi)AbstractAppender饲梭,通過(guò)繼承抽線類(lèi)可實(shí)現(xiàn)自定義appender
例如:實(shí)現(xiàn)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操作冶忱,存儲(chǔ)到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();
}
/**
* 接收配置文件中的參數(shù)
*
* @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注解實(shí)現(xiàn)定義appender名稱(chēng),即log4j2.xml配置文件中配置時(shí)使用的appender名稱(chēng),例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="info" monitorInterval="30">
<appenders>
<!--這個(gè)輸出控制臺(tái)的配置-->
<console name="Console" target="SYSTEM_OUT">
<!--輸出日志的格式-->
<PatternLayout pattern="%{[ %p ] [%-d{yyyy-MM-dd HH:mm:ss}] [%l] %m%n}"/>
</console>
<!-- 這個(gè)就是自定義的Appender -->
<EsAppender name="es" >
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%-5p] {%F:%L} - %m%n" />
</EsAppender>
</appenders>
<loggers>
<!--過(guò)濾掉spring和mybatis的一些無(wú)用的DEBUG信息-->
<root level="debug">
<appender-ref ref="Console"/>
<appender-ref ref="es"/>
</root>
</loggers>
</configuration>
@PluginFactory
插件構(gòu)建注解,定義創(chuàng)建appender邏輯。通過(guò)@PluginAttribute盾鳞、@PluginElement 定義配置文件可傳入的參數(shù)值。
append方法
通過(guò)重寫(xiě)append方法實(shí)現(xiàn)自定義日志操作瞻离,例如日志格式化腾仅,存儲(chǔ)邏輯自定義。
簡(jiǎn)單的自定義appender實(shí)現(xiàn)方式套利,實(shí)際封裝還可以考慮異步收集推励,批量收集、失敗重試等功能完善肉迫。