简易自定义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实现方式,实际封装还可以考虑异步收集,批量收集、失败重试等功能完善。
网友评论