Log4j,Stat4j,SMTPAppender集成–汇总错误日志以发送太多电子邮件

我们的开发团队希望在生产系统出现问题时尽快得到通知,这是一个每天为成千上万的客户提供服务的关键Java Web应用程序。 这个想法是让它在出现太多错误时向我们发送电子邮件,这些错误通常表明数据库,外部Web服务存在问题,或者应用程序本身确实存在问题。

在本文中,我想介绍一个简单的解决方案,我们已经使用基于Stats4j和SMTPAppender的自定义Log4J Appender实现了(这比您预期的配置和故障排除更加困难)。

挑战

我们在日志方面面临以下挑战:

  • 不幸的是,有一定数量的例外情况是正常的(客户选择没有结果的搜索条件,外部服务的暂时性,不重要的中断等),因此我们当然不希望被发送垃圾邮件。 因此,解决方案必须具有可配置的阈值,并且仅在超出阈值时发送警报。
  • 故障率应该在可配置的时间内进行计算(足够长的时间不会因几分钟的中断而触发警报,而足够短的时间可以在发生严重事件时尽快通知团队)。
  • 发送警报后,一段时间内(最好在解决原始问题之前)不应再发送其他警报,我们不希望因为我们已经知道的问题而被发送垃圾邮件。

解决方案

我们基于Lara D'Abreo的Stat4J解决方案,该解决方案提供了一个自定义Log4J附加程序,该附加程序使用日志来计算可配置的度量,并在超出警告或严重阈值时触发警报。 它有几年历史了,具有alpha质量(关于通用性和灵活性)的开源库,幸运的是,它足够简单,可以轻松地根据需要进行修改。

因此,我们对Stat4J进行了调整,以在警报数量超过阈值时生成警报,此后保持安静,然后将其与Log4J SMTPAppender结合使用, 后者侦听警报并将其通过电子邮件发送给团队。

Stat4J调整

Stat4J的关键组件包括用于Log4J的Stat4jAppender,用于汇总单个日志的计算器(度量)(例如,通过对它们进行计数或从中提取一些数字),用于定义要通过正则表达式考虑的日志以及如何通过以下方式处理的统计信息:引用计算器,最后在统计信息的值超出其限制时发出警告,并记录警告。 您可以在介绍Stat4J的文章中了解更多信息 。

我们已经实现了一个自定义的度量计算器, RunningRate (以计算最近N分钟内的失败数),并修改了Stat4J,如下所示:

  • 我们增强了Alert来支持新属性quietperiod,以便一旦触发,随后的警报将在该持续时间内被忽略(除非以前的警报只是警告,而新警报是关键警报)
  • 我们修改了附加器, 将日志的Throwable与日志消息一起包含,然后将其传递给各个统计计算器,以便我们可以更精确地过滤要计数的内容
  • 最后,我们修改了Alert,将警报记录为错误而不是警告,以使SMTPAppender不会忽略它们

从GitHub (我们的源代码或编译的jar )中获取我们修改后的Stat4j 。 免责声明:这是一天的工作,我对代码并不感到骄傲。

Stat4J配置

以stat4j.properties为例 ,并将其放在类路径中。 它已经配置了正确的计算器,统计信息和警报。 看到这部分:

### JAKUB HOLY - MY CONFIG
calculator.minuteRate.classname=net.sourceforge.stat4j.calculators.RunningRate
# Period is in [ms] 1000 * 60 * 10 = 10 min:
calculator.minuteRate.period=600000statistic.RunningErrorRate.description=Errors per 10 minutes
statistic.RunningErrorRate.calculator=minuteRate
# Regular expression to match "<throwable.toString> <- <original log message>"
statistic.RunningErrorRate.first.match=.*Exception.*# Error Rate
alert.TooManyErrorsRecently.description=Too many errors in the log
alert.TooManyErrorsRecently.statistic=RunningErrorRate
alert.TooManyErrorsRecently.warn= >=3
alert.TooManyErrorsRecently.critical= >=10
alert.TooManyErrorsRecently.category=alerts
# Ignore following warnings (or criticals, after the first critical) for the given amount of time:
# 1000 * 60 * 100 = 100 min
alert.TooManyErrorsRecently.quietperiod=6000000

重要的配置参数是

  • Calculator.minuteRate.period (以毫秒为单位)–在此期间计算错误,在其结束时重置计数; 合理的值可能是10分钟
  • alert.TooManyErrorsRecently.warnalert.TooManyErrorsRecently.critical –在此期间遇到如此多的错误时触发警报。 合理的值取决于您应用程序的正常错误率
  • alert.TooManyErrorsRecently.quietperiod (以毫秒为单位)–在此期间,在持续失败的情况下,不要发送进一步的警报以防止垃圾邮件; 合理的值取决于您通常解决问题的速度,对我来说1个小时似乎还可以

Log4J配置

现在,我们需要告诉Log4J使用Stat4j附加程序来计算错误发生次数并通过电子邮件发送警报:

log4j.rootCategory=DEBUG, Console, FileAppender, Stat4jAppender
...
### Stat4jAppender & EmailAlertsAppender ###
# Collects statistics about logs and sends alerts when there
# were too many failures in cooperation with the EmailAlertsAppender## Stat4jAppender
log4j.appender.Stat4jAppender=net.sourceforge.stat4j.log4j.Stat4jAppender
log4j.appender.Stat4jAppender.Threshold=ERROR
# For configuration see stat4j.properties## EmailAlertsAppender
# BEWARE: SMTPAppender ignores its Thresholds and only evers sends ERROR or higher messages
log4j.category.alerts=ERROR, EmailAlertsAppender
log4j.appender.EmailAlertsAppender=org.apache.log4j.net.SMTPAppender
log4j.appender.EmailAlertsAppender.To=dummy@example.com
# BEWARE: The address below must have a valid domain or some receivers will reject it (e.g. GMail)
log4j.appender.EmailAlertsAppender.From=noreply-stat4j@google.no
log4j.appender.EmailAlertsAppender.SMTPHost=172.20.20.70
log4j.appender.EmailAlertsAppender.BufferSize=1
log4j.appender.EmailAlertsAppender.Subject=[Stat4j] Too many exceptions in log
log4j.appender.EmailAlertsAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.EmailAlertsAppender.layout.ConversionPattern=%d{ISO8601} %-5p %X{clientIdentifier} %c %x - %m%n

注释

  • #8指定Stat4J附加程序
  • #9仅向Stat4J发送错误,我们对不太严重的异常不感兴趣
  • #14“警报”是Stat4jAppender用于记录警报的日志类别(与您通过Logger.getLogger(“ alerts”)创建的类别)相同; 如前所述,SMTPAppender将不考虑配置而仅处理错误和更高级别

SMTPAppender的问题

使SMTPAppender工作非常棘手。 一些陷阱:

  • SMTPAppender忽略所有非ERROR或更高级别的日志,而不考虑您如何设置阈值
  • 如果您指定了“不存在的发件人”域,则某些收件人的邮件服务器可以将其作为垃圾邮件删除(例如,GMail)
  • 要发送电子邮件,您当然需要mail.jar(对于旧版JVM也需要activation.jar),这是Tomcat的说明。

一个$ 100的提示:要对其进行调试,请在调试模式下运行您的应用程序,并在javax.mail.Transport#send上设置方法断点(不需要源代码),然后在其中设置this.session.debug为如果为true,则会在服务器日志中获得以下SMTP通信的非常详细的日志。

边注

本文基于Log4J的事实并不意味着我会亲自选择它,它只是随项目一起提供的。 我至少会考虑使用更新的和闪亮的Logback代替:-)。

结论

Stat4j + SMTPAppender是基于日志和电子邮件的相当灵活的自行完成警报系统的良好基础。 您可以使用Hyperic HQ plus开箱即用地实现相同的功能。

参考: 当错误日志太多时,聚集错误日志以发送警告电子邮件–来自The Holy Java Blog的 JCG合作伙伴 JakubHolý的 Log4j,Stat4j,SMTPAppender 。

相关文章 :
  • 首先记录异常的根本原因
  • Java日志混乱
  • 正确记录应用程序的10个技巧
  • 使用Java发送电子邮件
  • Spring,Quartz和JavaMail集成教程
  • 使用Spring使用Java发送电子邮件– GMail SMTP服务器示例
  • Java教程和Android教程列表

翻译自: https://www.javacodegeeks.com/2011/10/log4j-stat4j-smtpappender-integration.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374251.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C排序算法:(一)直接排序

最简单的排序方法。 如果从大到小排序&#xff0c;那么从[0]元素开始&#xff0c;和后面的元素进行对比&#xff0c;如果后面元素大&#xff0c;则和[0]元素交换。 核心思想&#xff1a;选定基准元素&#xff0c;和其他元素对比。 #include <stdio.h>unsigned char buff…

数据库抽象类PDOStatement对象使用

1.预处理语句中使用占位符,分为 索引方式 和 关联方式 a.索引方式&#xff1a; $pdonew PDO($dns,$username,$password,$options); $sqlselect * from tests where username?,password?; $stmt$pdo->prepare($sql); $stmt->execute(array($username,$password)); b.关联…

c语言 链表_C语言编程第22讲——单向有序链表的C语言实现

1、单向有序链表的含义单向有序链表可以解析为四个名词&#xff1a;表&#xff1a;一组元素&#xff1b;链表&#xff1a;表中的元素不是从前往后一个挨着一个&#xff0c;而是通过一个元素才能找到另一个元素&#xff1b;单向&#xff1a;表中的元素只能从前往后访问&#xff…

Spring 3.1和Hibernate的持久层

1.概述 本文将展示如何使用Spring和Hibernate实现DAO 。 有关核心的Hibernate配置&#xff0c;请参阅有关带​​有Spring的Hibernate 3和Hibernate 4的文章。 2.没有更多的春天模板 从Spring 3.0和Hibernate 3.0.1开始&#xff0c; 不再需要Spring HibernateTemplate来管理Hib…

C排序算法:(二)冒泡排序

冒泡排序就是从左至右比较相邻的两个数值大小&#xff0c;如果右侧的数值较小&#xff0c;则交换两个数值的位置&#xff0c;较大的数值就会像泡泡一样一路向右漂浮。 #include <stdio.h>//small to big void Bubble_Sort(unsigned char *input_data, unsigned int inpu…

C语言之猜数游戏

#include<stdio.h>#include<stdlib.h>#include<time.h>int main(){ srand(time(0)); int count0,thought; int numrand()%1001; printf("%d\n",num); do { printf("请猜这个数在1-100之间\n"); scanf("%d",&thought); cou…

pythonturtle画点的指令_简述python的turtle绘画命令及解释

一 基础认识 turtle库是python的标准库之一&#xff0c;它是一个直观有趣的图形绘制数据库&#xff0c;turtle(海龟&#xff09;图形绘制的概念诞生1969年。它的应用十分广&#xff0c;而且使用简单&#xff0c;只要在编写python程序时写上import turtle即可。 1.绘图窗口设置命…

算法—振兴中华(C语言版)

/* 标题: 振兴中华小明参加了学校的趣味运动会&#xff0c;其中的一个项目是&#xff1a;跳格子。地上画着一些格子&#xff0c;每个格子里写一个字&#xff0c;如下所示&#xff1a;从我做起振我做起振兴做起振兴中起振兴中华比赛时&#xff0c;先站在左上角的写着“从”字的格…

OpenGL ES一些函数详解(一)

glLoadIdentity和glMultMatrix glLoadIdentity的作用是将当前模型视图矩阵转换为单位矩阵&#xff08;行数和列数相同的矩阵&#xff0c;并且矩阵的左上角至右下角的连线上的元素都为1&#xff0c;其它元素都为0&#xff09;&#xff0c;这样可以方便矩阵的乘法运算。 glMultMa…

忽略Java中的自签名证书

我在职业生涯中遇到过几次问题&#xff0c;就是我们有时希望允许自签名证书用于开发或测试目的。 Google的快速搜索显示了多年来无数Java开发人员遇到的麻烦。 根据确切的证书问题&#xff0c;您可能会收到类似以下内容之一的错误&#xff0c;尽管我几乎肯定有其他表现形式&…

C排序算法:(三)插入排序

像打扑克牌一样&#xff0c;每次摸一张牌&#xff0c;把牌插入正确位置。 #include <stdio.h>void Insert_Sort_Small_To_Big(unsigned char* input_data, unsigned int input_length) {int i 0, j 0;unsigned char temp 0;for (i 1; i < input_length; i){temp …

sqlserver中自定义函数+存储过程实现批量删除

由于项目的需要&#xff0c;很多模块都要实现批量删除的功能。为了方便模块的调用&#xff0c;把批量删除方法写成自定义函数。直接上代码。 自定义函数&#xff1a; ALTER FUNCTION [dbo].[func_SplitById] (str varchar(50),split varchar(10))--传过来的id字符串 --分割的标…

c语言选择排序_C语言——选择排序

1 选择排序&#xff08;5分&#xff09;题目内容&#xff1a;编写选择排序&#xff0c;要求排序过程调用函数实现&#xff0c;在主函数输入n个数据&#xff0c;调用函数后&#xff0c;输出排好序的元素输入格式:输入整型数n&#xff0c;并输入n个整数&#xff0c;输入数据用空格…

算法—巧排扑克牌(C语言)

/*小明刚上小学&#xff0c;学会了第一个扑克牌“魔术”&#xff0c;到处给人表演。魔术的内容是这样的&#xff1a;他手里握着一叠扑克牌&#xff1a;A&#xff0c;2&#xff0c;....J&#xff0c;Q&#xff0c;K 一共13张。他先自己精心设计它们的顺序&#xff0c;然后正面朝…

LeetCode Binary Tree Paths(简单题)

题意&#xff1a;   给出一个二叉树&#xff0c;输出根到所有叶子节点的路径。 思路&#xff1a; 直接DFS一次&#xff0c;只需要判断是否到达了叶子&#xff0c;是就收集答案。 1 /**2 * Definition for a binary tree node.3 * struct TreeNode {4 * int val;5 * …

我的测试和代码分析工具箱

上周&#xff0c;我们在LINEAS成立了一个“测试技能小组”&#xff0c;该小组用于交换有关测试的知识。 各种各样的问题反复出现的一个问题是&#xff1a;有哪些工具可以测试和分析您的代码&#xff1f; 因此&#xff0c;这是我对此的个人回答&#xff0c;按照我倾向于将其介绍…

新唐M0 KEIL环境搭建,找不到device不识别,关键:Nu-Link_Keil_Driver

公司用新唐的芯片&#xff0c;网上关于新唐的资料相对ST确实少得可怜&#xff0c;搭建环境也是搞了好久&#xff0c;去keil官网下载安装了新唐的pack 打开官方参考工程还是提示找不到device&#xff0c;option里面也没有识别出来。 百度了好久&#xff0c;尝试了各种办法&…

c语言有趣代码_【新课预知】——C语言程序设计

编者按&#xff1a;如今疫情这么严重&#xff0c;为了保护好自己&#xff0c;为了身边的人&#xff0c;大家可一定要听从国家号召——“宅”起来&#xff01;并且&#xff0c;小编们为了让大家伙“宅”得更加健康&#xff0c;可是费了不少脑筋呢&#xff0c;学哉数理公众号首次…

用R语言的quantreg包进行分位数回归

什么是分位数回归 分位数回归(Quantile Regression)是计量经济学的研究前沿方向之一&#xff0c;它利用解释变量的多个分位数&#xff08;例如四分位、十分位、百分位等&#xff09;来得到被解释变量的条件分布的相应的分位数方程。 与传统的OLS只得到均值方程相比&#xff0c;…

算法—快速排序Sqrt (C语言)

/* 快速排序 */ #include"stdio.h" #include"stdlib.h" int compare(const void* a,const void* b) {return (*(int *)a-*(int *)b); }int main() {int i,a[]{32,29,59,8,22,68,89,77},n;nsizeof(a)/sizeof(a[0]);printf("排序前:\n");for(i0;i&…