Log4j/Log4j2自定义Appender来实现日志级别计数统计及监控
一、简述
本文主要讲如何基于Log4j2来实现自定义的Appender。一般用途是用于Log4j2自带的Appender不足以满足我们的需求,或者需要我们对日志进行拦截统计等操作时,需要我们自定义Appender。
二、自定义Appender
方法:实现一个类,让它继承自Log4j2的AbstractAppender,然后你重写其append方法,并添加一个@PluginFactory标记的createAppender方法。
举例:例如,我们要实现一个通过日志输出的Level来统计计数来实现监控的一个Appender,并需要在配置日志时,实现对一些附加属性的配置,可以如下实现。
package com.test.utils.logs; 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; @Plugin(name = "Statistics", category = "Core", elementType = "appender", printObject = true)
public class StatisticsAppender extends AbstractAppender {
/** 日志级别大于等于此级别及以上会进行判断错误。默认:ERROR */
private String failedOnLogLevel;
/** 指定时间内,出现多少次该日志级别,会被认为是错误。默认:10 */
private Integer failedOnLogLevelCount;
/** 该日志级别以上持续出现多长时间,会被认为是错误。默认:30000 */
private Integer failedOnLogLevelInMisSecond;
/** 当连续小于该日志级别多长时间后,恢复为正常状态。默认:120000 */
private Integer recoveryOnLessLogLevelInMisSecond; protected StatisticsAppender(String name, Filter filter, Layout<? extends Serializable> layout,
String failedOnLogLevel,
Integer failedOnLogLevelCount,
Integer failedOnLogLevelInMisSecond,
Integer recoveryOnLessLogLevelInMisSecond) {
super(name, filter, layout);
this.failedOnLogLevel = failedOnLogLevel;
this.failedOnLogLevelCount = failedOnLogLevelCount;
this.failedOnLogLevelInMisSecond = failedOnLogLevelInMisSecond;
this.recoveryOnLessLogLevelInMisSecond = recoveryOnLessLogLevelInMisSecond;
} @Override
public void append(LogEvent logEvent) {
//此处省略告警过滤统计代码。
// .....
String msg = logEvent.getMessage().getFormattedMessage();
System.out.println(msg);
} @PluginFactory
public static StatisticsAppender createAppender(@PluginAttribute("name") String name,
@PluginElement("Filter") final Filter filter,
@PluginElement("Layout") Layout<? extends Serializable> layout,
@PluginAttribute("failedOnLogLevel") String failedOnLogLevel,
@PluginAttribute("failedOnLogLevelCount") Integer failedOnLogLevelCount,
@PluginAttribute("failedOnLogLevelInMisSecond") Integer failedOnLogLevelInMisSecond,
@PluginAttribute("recoveryOnLessLogLevelInMisSecond") Integer recoveryOnLessLogLevelInMisSecond) {
if (name == null) {
LOGGER.error("No name provided for MyCustomAppenderImpl");
return null;
}
if (layout == null) {
layout = PatternLayout.createDefaultLayout();
}
if (failedOnLogLevel == null) {
failedOnLogLevel = "ERROR";
}
if (failedOnLogLevelCount == null) {
failedOnLogLevelCount = 10;
}
if (failedOnLogLevelInMisSecond == null) {
failedOnLogLevelInMisSecond = 30000;
}
if (recoveryOnLessLogLevelInMisSecond == null) {
recoveryOnLessLogLevelInMisSecond = 120000;
}
return new StatisticsAppender(name, filter, layout, failedOnLogLevel, failedOnLogLevelCount, failedOnLogLevelInMisSecond, recoveryOnLessLogLevelInMisSecond);
} }
说明:注意黄色区域的地方,另外createAppender方法中,红色的参数表示XML中要配置的Appender属性。
三、配置log4j2.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="ON" packages="org.apache.logging.log4j.core,io.sentry.log4j2,com.test.utils.logs">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="RollingFile" fileName="datamerge-logs/app.log"
filePattern="datamerge-logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
<SizeBasedTriggeringPolicy size="300 MB"/>
</RollingFile>
<Sentry name="Sentry"/>
<Statistics name="StatisticsMonitor" failedOnLogLevel="ERROR" failedOnLogLevelCount="10"
failedOnLogLevelInMisSecond="30000" recoveryOnLessLogLevelInMisSecond="120000"/>
</appenders>
<loggers>
<root level="INFO">
<appender-ref ref="Console"/>
<!--<appender-ref ref="RollingFile"/>-->
<!--<appender-ref ref="Sentry" level="ERROR" />-->
<appender-ref ref="StatisticsMonitor"/>
</root>
</loggers>
</configuration>
说明,请仔细阅读黄色区域的内容。packages中要标注Appender所在的包名(不同的包名请使用","分隔)
四、调用
正常调用日志即可。需要说明的是,Appender会在程序启动后第一次调用日志时,实例化一次Appender,之后就不会再实例化了。之后会多次调用append方法。
Log4j/Log4j2自定义Appender来实现日志级别计数统计及监控的更多相关文章
- log4j2自定义Appender(输出到文件/RPC服务中)
1.背景 虽然log4j很强大,可以将日志输出到文件.DB.ES等.但是有时候确难免完全适合自己,此时我们就需要自定义Appender,使日志输出到指定的位置上. 本文,将通过两个例子说明自定义APP ...
- log4j2和logback动态修改日志级别工具类
工作中,在排查线上问题时,有以下场景在不重新部署或重启服务的情况下,需要动态调整线上日志级别 1.线上有些日志打印过多干扰有用的日志,需要动态修改线上日志记录器的打印日志级别,调高一些日志级别,打印出 ...
- SpringBoot | 第二十五章:日志管理之自定义Appender
前言 前面两章节我们介绍了一些日志框架的常见配置及使用实践.一般上,在开发过程中,像log4j2.logback日志框架都提供了很多Appender,基本上可以满足大部分的业务需求了.但在一些特殊需求 ...
- springboot中动态修改log4j2日志级别
springboot中动态修改log4j2日志级别 在spring boot中使用log4j2日志时,项目运行中,想要修改日志级别. 1.pom.xml依赖: <dependency> & ...
- 自定义log4j日志级别
转载自: http://blog.csdn.net/seven_cm/article/details/26849821 自定义log4j日志级别 参考了网上资料:http://www.360doc. ...
- log4j.xml配置,包含自定义log4j日志级别及输出日志到不同文件
一.配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configura ...
- 详解log4j2(下) - Async/MongoDB/Flume Appender 按日志级别区分文件输出
1. 按日志级别区分文件输出 有些人习惯按日志信息级别输出到不同名称的文件中,如info.log,error.log,warn.log等,在log4j2中可通过配置Filters来实现. 假定需求是把 ...
- Log4j,Log4j2,logback,slf4j日志学习
日志学习笔记 Log4j Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条 ...
- log4j2动态修改日志级别及拓展性使用
一.供参考的完整日志配置 <?xml version="1.0" encoding="UTF-8"?> <!-- 配置LoggerConfig ...
随机推荐
- C#基础:委托之Action<T>和Func<T>的用法
- Qt界面设计基础
一.安装Qt相关基本组件: 在ubuntu上安装,可以直接使用如下的命令来安装: sudo apt-get install ubuntu-sdk 详细的安装方法可以参考这篇文章:https://blo ...
- Scala-Unit5-Scala面对对象与模式匹配
Java中的面向对象:万物皆对象. 我们要封装数据,定义模板等操作,素以我们需要面向对象. ====================================================== ...
- HDU 2389 Rain on your Parade 最大匹配(模板题)【HK算法】
<题目链接> 题目大意:有m个宾客,n把雨伞,预计时间t后将会下大雨,告诉你每个宾客的位置和速度,每把雨伞的位置,问你最多几个宾客能够拿到伞. 解题分析: 本题就是要我们求人与伞之间的最大 ...
- DDL DML概念 --- Msysql常用命令
一.DML DML(data manipulation language)数据操纵语言: 就是我们最经常用到的 SELECT.UPDATE.INSERT.DELETE. 主要用来对数据库的数据进行一些 ...
- 基于Ardalis.GuardClauses守卫组件的拓展
在我们写程序的时候,经常会需要判断数据的是空值还是null值,基本上十个方法函数,八个要做这样的判断,因此我们很有必要拓展出来一个类来做监控,在这里我们使用一个简单地,可拓展的第三方组件:Ardali ...
- Compiling U-Boot
To configure and build U-Boot for a target board "cd" to, or copy the source tree to somew ...
- hihoCoder 1143 : 骨牌覆盖问题·一(递推,矩阵快速幂)
[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形 ...
- 2017.07.07【NOIP提高组】模拟赛B组
Summary 因为某种无法抗拒的原因,今天没有打比赛,所以也就没有那种心态.今天的题目有状压DP和二分,这套题不难也不简单,适中,适合我这种渣渣来做.在改题时,发现了许多问题.我连欧拉函数的计算都记 ...
- Java 构造器 考虑用静态构造方法代替构造器
类可以提供一个公有的静态工厂方法,它是一个返回类的实例的静态方法.静态工厂方法与设计模式中的工厂方法模式不同. 优势: 静态工厂方法与构造器不同的第一大优势在于,它们有名称.一个类只能有一个带有指定签 ...