Log4j的邮件发送类SMTPAppender改造
在开发过程中,我们有时需要将重要的错误日志通过邮件发送给相关的责任人,这样能即时发现错误,即时解决。如使用Log4J,一般会做如下配置:
log4j.rootLogger = debug,mail
# 发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=INFO
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From=from@qq.com
log4j.appender.mail.To=to@163.com
log4j.appender.mail.SMTPHost=smtp.qq.com
#发送邮件箱的用户
log4j.appender.mail.SMTPUsername=from@qq.com
#邮箱的授权码
log4j.appender.mail.SMTPPassword=
但是我在使用过程中发现标准的org.apache.log4j.net.SMTPAppender有如下几个问题。
- 同步发送邮件。这样会阻塞业务正常进行(比如等待一个SQL查询,需要等待邮件发送后才显示结果,显然不能忍受)
解决办法: 使用线程池的方式,将发送邮件包装成Runnable任务,送到线程池中执行。同步队列我选择的是设置了固定大小的LinkedBlockingQueue,设置固定大小是因为需要发邮件的重要日志不是太多,二是不能因为邮件任务占用了太多的内存;选择LinkedBlockingQueue,是因为LinkedBlockingQueue读写锁分离,可以边添加任务,边发送邮件;核心线程数和最大线程数,可以根据业务量和CPU核数设定。
- 缓存大小bufferSize(日志事件的个数)只是设置缓存大小,并不能等到缓存满时才发送(其实是只要有发生ERROR级别及以上的的事件时就将缓存中保存的所有满足threshold级别的日志都发送,在发送之前缓存满时会从头开始,新的日志覆盖旧的)
解决办法: 去掉默认实现类CyclicBuffer,改成同步队列;因为CyclicBuffer线程不安全,添加日志和获取日志并不是同一个线程,所以采用了线程安全的同步队列,而且还需要实现当同步队列中日志快满时将触发发送邮件;所以需要自定义同步队列,加上一个阀值factor,当同步队列中的日志个数达到bufferSize*factor时就发送邮件,这样可以预留一部分空间存放后添加进来的日志;同步队列我选择的是 LinkedBlockingQueue,可以边添加日志,边读取日志,吞吐量比较大。目前发送邮件触发的条件是:发生了 ERROR 或 ERROR以上级别 的错误时发送邮件,改成当缓存同步队列中元素个数大于或等于 bufferSize*factor 时,触发回调函数,启动发送邮件任务。
改造步骤:
- 定义回调接口AlertWillBeFull
- 自定义同步队列 AlertLinkedBlockingQueue ,继承 LinkedBlockingQueue ,添加成员变量factor及回调接口,在所有添加动作之前进行判断是否达到阀值。
- 去掉SMTPAppender类中的实现类DefaultEvaluator及所有调用它的地方
- 在创建缓存同步队列时,传入回调对象,等待同步队列调用
- 添加日志到缓存同步队列和从缓存同步队列读取日志分别使用offer和poll方法,不阻塞线程也不抛异常,以免影响实际业务进行,而且少少量日志影响也不大。
- 发送的日志比较杂乱,需要排除某些包下的日志(比如有些不重要的日志,或者只想看某些包下的日志
解决方法:添加成员变量excludePackage和includePackage,修改checkEntryConditions方法逻辑
这样就能在log4j.properties配置文件中配置缓存大小,以及添加排除或只关心的记录日志的包,也可以添加多个发送邮件的配置,将不同包下的日志发送给不同的责任人。
最终配置如下:
log4j.rootLogger = debug,mail
# 发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
#排除的包(多个包,以英文逗号隔开)
#log4j.appender.mail.excludePackage=com.alibaba.druid
#仅关心的包,一般excludePackage与includePackage任选一即可,多个包以英文逗号隔开
log4j.appender.mail.includePackage=cn.yang.practise.service,cn.yang.practise.controller,com.alibaba.druid
log4j.appender.mail.Threshold=INFO
log4j.appender.mail.BufferSize=16
log4j.appender.mail.From=from@qq.com
log4j.appender.mail.To=to@163.com
log4j.appender.mail.SMTPHost=smtp.qq.com
#发送邮件箱的用户
log4j.appender.mail.SMTPUsername=from@qq.com
#邮箱的授权码
log4j.appender.mail.SMTPPassword=
改造后完整后的org.apache.log4j.net.SMTPAppender,AlertLinkedBlockingQueue
Log4j的邮件发送类SMTPAppender改造的更多相关文章
- PHP 邮件发送类
mail.php <?php /** * 邮件发送类 * 支持发送纯文本邮件和HTML格式的邮件,可以多收件人,多抄送,多秘密抄送,带附件的邮件 * 需要的php扩展,sockets和Filei ...
- C#邮件发送类 简单实用 可自定义发件人名称
上图看效果 MailHelper: public class MailHelper { public bool SendMail(MailSender sender,out string errorM ...
- asp.net 邮件发送类
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- 关于 PHPMailer 邮件发送类的使用心得(含多文件上传)
This is important for send mail PHPMailer 核心文件 class.phpmailer.php class.phpmaileroauth.php class.ph ...
- 关于.NET 的邮件发送类
.NET 类库中已经有现成的封好的类库了,只要引用System.Net.Mail命名空间即可实现发邮件的功能 以下是代码 public class SendMail { private string ...
- 利用phpmailer类邮件发送
<?php require("class.phpmailer.php"); //下载的文件必须放在该文件所在目录 $mail = new PHPMailer(); //建立邮 ...
- 【Thinkphp 5】 整合邮箱类 phpmailer实现邮件发送
第一步:下载phpmailer文件,主要用到的文件只有箭头指向的两个,thinkphp5中,把class.phpmailer.php改成了phpmailer.php 第二步: 将phpmailer文件 ...
- 一个用于发送HTML格式邮件的类
以下类是在网上孙钰佳的版本上改写而来,主要变化了三点:1.去掉了附件部分:2.形式从纯Java类改成可注入方式:3.to,cc和bcc都变成了一堆人,以前是一个人. 以下是Java类的代码: impo ...
- J2EE 邮件发送那些事儿
距离自己写的关于java邮件发送的第一篇博客已经有很长一段时间了,现在回过头看看.虽然代码质量方面有待提高,整体结构也不怎样,但是基本思路和过程还是比较纯的.现在有空写写J2EE中邮件发送的开发,实际 ...
随机推荐
- 压力测试 mac ab
apache ab:http://blog.chinaunix.net/uid-20382003-id-3032167.html 简单用法: ab -n 3000 -c 3000 http://www ...
- 2.mongodb可视化工具
(1)去robomongo官方网址下载,官网地址(https://robomongo.org/)选择相应的版本. (2) tar -xzf robo3t-1.2.1-linux-x86_64-3e50 ...
- Delphi cxGrid使用汇总(一)
1. 去掉cxGrid中台头的Box解决:在tableview1的ptionsview的groupbybox=false; 2.统计功能解决:(1) tableview1. tableview1的op ...
- 数据单位bit byte kb Mb Gb
8 bit = 1 byte 2^10 bytes = 1 kb 2^10 kb = 1 Mb 2^10 Mb = 1Gb 2^32 bit = 2^2 * 2^10 * 2^10 * 2^10 bi ...
- 改变PowerDesigner数据模型字体大小
一 改变左侧菜单字体大小Tools----->General------->Fonts-------->根据item选项的不同改变字体的大小 二 改变数据模型Table的字体大小To ...
- Docker学习笔记——制作容器与容器概念
Docker能做些什么? 1.docker能够解决虚拟机能够解决的问题 2.隔离应用依赖 3.创建应用镜像并复制 4.创建容易分发的即启即用的应用 5.docker的想法是创建软件程序可移植的轻量容器 ...
- SpringBoot使用ModelAndView时配置视图解析器
spring boot 使用视图modelandview 原文:https://www.cnblogs.com/liyafei/p/7955943.html 1:springboot使用视图解析器,添 ...
- pip指定网址安装
用pip安装库的有时候很慢都动不了 ,访问速度很慢,不稳定等缺陷 所以呢为了解决这个问题只能指定网址源下载的话速度就很快了 pip安装默认访问的是https://pypi.Python.org/sim ...
- cpu负载的探讨 (转)
文章出处:http://blog.chinaunix.net/uid-12693781-id-368837.html 摘要:确定cpu的负载的定义,帮助管理员设置cpu负载阀值,推测可能的导致cpu负 ...
- numpy.random.randn()与numpy.random.rand()的区别(转)
numpy中有一些常用的用来产生随机数的函数,randn()和rand()就属于这其中. numpy.random.randn(d0, d1, …, dn)是从标准正态分布中返回一个或多个样本值. n ...