Java代码
public class Log4jSendMail {
public static void main(String args[]) throws InterruptedException {
// 读取Log4j.properties配置文件
PropertyConfigurator.configure(Log4jSendMail.class.getResource("/log4j.properties"));
Logger logger = Logger.getLogger(Log4jSendMail.class);
try {
int a = 1 / 0;
} catch (Exception e) {
logger.error("error:", e);
}
}
}
邮件打印信息:
红色区域打印的就是异常栈信息。
Error方法
public
void error(Object message, Throwable t) {
if(repository.isDisabled(Level.ERROR_INT))
return;
if(Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel()))
forcedLog(FQCN, Level.ERROR, message, t);
}
继续向下跟踪,forcedLog方法
protected void forcedLog(String fqcn, Priority level, Object message, Throwable t) {
callAppenders(new LoggingEvent(fqcn, this, level, message, t));
}
在创建LoggingEvent对象时,将异常信息封装,继续跟踪new LoggingEvent
public LoggingEvent(String fqnOfCategoryClass, Category logger,
Priority level, Object message, Throwable throwable){
this.fqnOfCategoryClass = fqnOfCategoryClass;
this.logger = logger;
this.categoryName = logger.getName();
this.level = level;
this.message = message;
if(throwable != null) {
this.throwableInfo = new ThrowableInformation(throwable);
}
timeStamp = System.currentTimeMillis();
}
异常信息存入throwableInfo属性中。
发送邮件时,调用properties中配置的类
SMTPAppender:处理邮件发送,可以自定义。
HTMLLayout:处理邮件样式的,可以自定义。
SMTPAppender类中的sendBuffer方法
protected void sendBuffer() {
// Note: this code already owns the monitor for this
// appender. This frees us from needing to synchronize on 'cb'.
try {
MimeBodyPart part = new MimeBodyPart();
StringBuffer sbuf = new StringBuffer();
String t = layout.getHeader();
if(t != null)
sbuf.append(t);
int len = cb.length();
for(int i = 0; i < len; i++) {
//sbuf.append(MimeUtility.encodeText(layout.format(cb.get())));
LoggingEvent event = cb.get();
sbuf.append(layout.format(event));
if(layout.ignoresThrowable()) {
String[] s = event.getThrowableStrRep();
if (s != null) {
for(int j = 0; j < s.length; j++) {
sbuf.append(s[j]);
sbuf.append(Layout.LINE_SEP);
}
}
}
}
t = layout.getFooter();
if(t != null)
sbuf.append(t);
part.setContent(sbuf.toString(), layout.getContentType());
Multipart mp = new MimeMultipart();
mp.addBodyPart(part);
msg.setContent(mp);
msg.setSentDate(new Date());
Transport.send(msg);
} catch(Exception e) {
LogLog.error("Error occured while sending e-mail notification.", e);
}
}
layout.format(event),调用HTMLLayout中的format方法,format方法中如下段落拼装异常信息内容。
String[] s = event.getThrowableStrRep();
if(s != null) {
sbuf.append("<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : xx-small;\" colspan=\"6\">");
appendThrowableAsHTML(s, sbuf);
sbuf.append("</td></tr>" + Layout.LINE_SEP);
}
event.getThrowableStrRep()方法,获得上面封装的异常栈信息
public String[] getThrowableStrRep() {
if(throwableInfo == null)
return null;
else
return throwableInfo.getThrowableStrRep();
}
调用getThrowableStrRep()方法
public String[] getThrowableStrRep() {
if(rep != null) {
return (String[]) rep.clone();
} else {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
pw.flush();
LineNumberReader reader = new LineNumberReader(
new StringReader(sw.toString()));
ArrayList lines = new ArrayList();
try {
String line = reader.readLine();
while(line != null) {
lines.add(line);
line = reader.readLine();
}
} catch(IOException ex) {
lines.add(ex.toString());
}
rep = new String[lines.size()];
lines.toArray(rep);
}
return rep;
}
OK,这个方法就是将throwableInfo属性封装的异常类的异常栈信息转换为Sting数组。