扩展Log4j级别,实现邮件提醒

log4j想必大家都很熟了,它是apache组织旗下的一个开源项目,用于记录程序运行时的一些信息,这些信息有助于我们分析程序的性能找出bug。log4j共有六个级别,按级别升序排序分别是


TRACK 记录比debug级别还要详细的信息(finer-grained 细颗粒度) DEBUG 记录程序运行时一些有用的信息,用来分析程序的性能,发现bug(finer-grained 细颗粒度) INFO 记录程序运行时正常输出的提示信息(coarse-grained 粗颗粒度) WARN 指明程序运行状态处在欠佳状态,可能会出现异常情况。 ERROR 指明程序发生了错误,但还可以允许程序继续运行。 FATAL 指明程序发生了非常重大的错误,并引导程序停止运行。

 

一般情况下这几个级别已经够用,但在一些情况下并不能满足我们的要求,例如在我开发的自动跟踪定位程序中,要每间隔10秒针钟查询一次数据库,取出当前时间需要定位的终端然后发起定位,每定一次位需要从账户中扣除一定的费用,如果费用被扣完,则要向客服及市场部发送提醒邮件,提醒xxx企业已经欠费,请联系该企业及时充值。这实现这样的功能,这几个级别显然不能满足我们的要求的,所以要自定义一个级别,专门用来发送提醒邮件的

1、自定义级别类

package com.tdt.log4j.extend;



import org.apache.log4j.Level;



/**

 * @project MRMAutoloc

 * @author sunnylocus

 * @vresion 1.0 2009-7-22

 * @description 自定义级别REMIND,该级别用来发送提醒邮件,级别要比INFO低

 */

public class TDTLevel extends Level {

 private static final long serialVersionUID = 7288304330257085144L;



 static public final int REMIND_INT = Level.INFO_INT - 1;

 static public final int LETHAL_INT = Level.FATAL_INT + 1;



 private static String REMIND_STR = "REMIND";

 private static String LETHAL_STR = "LETHAL";



 public static final TDTLevel REMIND = new TDTLevel(REMIND_INT, REMIND_STR,7);

 public static final TDTLevel LETHAL = new TDTLevel(LETHAL_INT, LETHAL_STR,0);



 protected TDTLevel(int level, String strLevel, int syslogEquiv) {

  super(level, strLevel, syslogEquiv);

 }



 /**

  * Convert the string passed as argument to a level. If the conversion

  * fails, then this method returns {@link #REMIND}.

  */

 public static Level toLevel(String sArg) {

  return (Level) toLevel(sArg, TDTLevel.REMIND);

 }



 public static Level toLevel(String sArg, Level defaultValue) {

  if (sArg == null) {

   return defaultValue;

  }

  String stringVal = sArg.toUpperCase();



  if (stringVal.equals(REMIND_STR)) {

   return TDTLevel.REMIND;

  } else if (stringVal.equals(LETHAL_STR)) {

   return TDTLevel.LETHAL;

  }



  return Level.toLevel(sArg, (Level) defaultValue);

 }

 public static Level toLevel(int i) throws IllegalArgumentException {

  switch (i) {

  case REMIND_INT:

   return TDTLevel.REMIND;

  case LETHAL_INT:

   return TDTLevel.LETHAL;

  }

  return Level.toLevel(i);

 }



}

 

写好自定义级别,还要作邮件发送策略的处理

2、邮件发送处理类

 

package com.tdt.log4j.extend;



import org.apache.log4j.Logger;

import org.apache.log4j.spi.LoggingEvent;

import org.apache.log4j.spi.TriggeringEventEvaluator;



import com.tdt.util.DateUtil;



public final class MockTriggeringEventEvaluator  {

  //处理程序出错邮件提醒

  public final static class ErrorMockTriggeringEventEvaluator implements TriggeringEventEvaluator{

   private static boolean isSended = false;//是否已发送邮件

   private static String senedTime ="";//发送时间

   @Override

   public boolean isTriggeringEvent(LoggingEvent arg0) {

    if(!isSended) {

     isSended = true;////标记邮件已发送

     senedTime = DateUtil.currentTime();

     Logger.getLogger(getClass()).info("已发送程序出错提醒邮件!");

     

     return true;

    } 

    String currentTime = DateUtil.currentTime();

    if(DateUtil.calculateTimeoutByMinute(senedTime, currentTime) > 10) { //距上次发送邮件已超过10分名钟,再次发送邮件

     return true;

    }

    return false;

   }

  }

  //处理企业欠费邮件提醒 

  public final static class RemindMockTriggeringEventEvaluator implements TriggeringEventEvaluator{

   public boolean isTriggeringEvent(LoggingEvent arg0) {

    Logger.getLogger(getClass()).info("已发送企业欠费提醒邮件!");

    return true; //欠费邮件不作处理,直接发送

   }

  }

 }

 
3、日期工具类

package com.tdt.util;

 

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

 

 

/**

 * @project MRMAutoloc

 * @author sunnylocus

 * @vresion 1.0 2009-7-13

 * @description  日期工具类,提供日期的加减及比较

 */

public class DateUtil {

      

                /** 

                 *@return String 当前时间(格式yyyyMMddHHmmss)

  */

 public static String currentTime(){

  SimpleDateFormat formate = new SimpleDateFormat("yyyyMMddHHmmss");

  Calendar calendar = Calendar.getInstance();

  return formate.format(calendar.getTime());

 }

       /**

  * 计算两个时间之间相差多少分钟

  * @param pretiem 之前的时间 (格式:yyyyMMddHHmmss)

  * @param currentTime 现在的时间 (格式:yyyyMMddHHmmss)

  * @return int 相差多少分钟

  */

 public  static int calculateTimeoutByMinute(String pretiem,String currentTime) {

  try {

   //设置时间

   SimpleDateFormat formate = new SimpleDateFormat("yyyyMMddHHmmss");

   Calendar calendar = Calendar.getInstance();

   calendar.setTime(formate.parse(pretiem));

   int pre =calendar.get(Calendar.MINUTE);

   calendar.setTime(formate.parse(currentTime));

   int curr = calendar.get(Calendar.MINUTE);

   

   return (curr - pre);

  } catch (ParseException e) {

   throw new IllegalArgumentException(e);

  }

 }

}

 

测试

 

package com.tdt.test;

 

import org.apache.log4j.Logger;

 

import com.tdt.log4j.extend.TDTLevel;

 

 

public class TestSendMail {

 static Logger log = Logger.getLogger(TestSendMail.class);

 

 public static void main(String[] args) {

  log.log(TDTLevel.REMIND, "测试,xxx,企业欠费,该企业所属终端的定位请求将被过滤");

  log.error("测试,程序运行发生了一个错误");

  log.error("测试,程序运行发生了一个错误");

 }

}



 

log4j.xml

 

然后在log4j.xml配置我们自定义的级别。大家最好用xml配置log4j的参数,因为properties的方式已经过时,log4j不推荐使用。


收到两封邮件

 

对错误邮件的发送,间隔控制在10分钟,如果不作控制一旦程序(多线程情况下)出错,每个线程会发送相同内容的邮件,会把你的信箱填满。

 

对邮件正文出现乱码解决的方案

将org.apache.log4j.Layout类

public String getContentType() {
return "text/plain";
}

 

改为

public String getContentType() {
return "text/plain;charset=UTF-8";
}

 

然后重新编译,将编译后的类替换原来的class文件


本文来自: ★JAVA开发者 - 原创博文★ http://www.5lone.com 详细出处参考:http://www.hezubbs.cn/html/java/200907/kuozhanLog4jjibie-shixianyoujiantixing-_8339.html

你可能感兴趣的:(apache,多线程,log4j,xml)