用LOG4J对项目进行监控,增加EMAIL日志监控

LOG4J用了common logging的标准接口。。。所以用LOG4J的时候得引用common logging的包哦。。

 

当然如果要在LOG4J中用EMAIL的话,得把javamail和jaf包引用进来。。。

 

OK。。原理我就不啰嗦了。。直接上代码和配置。

import org.apache.commons.logging.Log;   
  
import org.apache.commons.logging.LogFactory;   
  
public class TestLog {   
       
    private static Log log = LogFactory.getLog(TestLog.class);   
       
    public void test() {   
        log.debug("This is the debug message.");   
        log.info("This is the info message.");   
        log.warn("This is the warn message.");   
        log.error("This is the error message.");   
        log.fatal("This is the fatal message.");   
    }   
  
    public static void main(String[] args) {   
        TestLog testLog = new TestLog();   
        testLog.test();   
    }   
  
}  

 

 

配置:

log4j.rootLogger = info,stdout,RF,MAIL   
  
#There is 3 appender,you can use any of them according to you requirement.   

#Set the variable
pattern=Happened Time[%d]    Log Type[%p](%F:%L) - %m%n

#appender1[name=stdout]   log to console   
log4j.appender.stdout = org.apache.log4j.ConsoleAppender    
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout   
log4j.appender.stdout.layout.ConversionPattern =${pattern}
  
#appender2[name=RF]   log to file   
log4j.appender.RF = org.apache.log4j.RollingFileAppender    
log4j.appender.RF.File = d:/logs/pfingoopenapi2.log    
log4j.appender.RF.MaxFileSize = 10000KB    
log4j.appender.RF.MaxBackupIndex = 1  
  
log4j.appender.RF.layout=org.apache.log4j.PatternLayout   
log4j.appender.RF.layout.ConversionPattern=${pattern}   
  
  
#appender3[name=MAIL]  log to email   
log4j.appender.MAIL = com.gftech.log4j.SMTPExtAppender   
log4j.appender.MAIL.Threshold=ERROR  
log4j.appender.MAIL.BufferSize=512  
log4j.appender.MAIL.SMTPHost=smtp.qq.com   
log4j.appender.MAIL.to=wangking717@qq.com   
log4j.appender.MAIL.from=wangking717@qq.com   
#custom by myself[using auth]
log4j.appender.MAIL.SMTPAuth=true  
#custom by myself[using auth]   
log4j.appender.MAIL.SMTPUsername=wangking717  
#custom by myself[using auth]   
log4j.appender.MAIL.SMTPPassword=your password here   
log4j.appender.MAIL.Subject=Log4J Message   
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout   
log4j.appender.MAIL.layout.ConversionPattern=${pattern} 

 

 

 

因为大部分的邮件服务器都是需要认证的,而LOG4J大牛们却没有把认证加进去。。那么就只有自己来改进它吧。。

 

由于SMTPAppender的属性都是私有的,没有给我们留下继承的可能,所以我们选择直接从它的父类AppenderSkeleton来继承,然后把SMTPAppender的源代码全部COPY过来,增加如下EMAIL用户名、密码和是否需要认证的标记:

    // Define auth info   
    private String smtpUsername;   
  
    private String smtpPassword;   
  
    private String smtpAuth;  

 

 

 

在activateOptions()方法中增加验证的代码:

/* ADD auth code */  
        if (smtpAuth != null && smtpAuth.trim().equals("true")) ...{   
            props.put("mail.smtp.auth", "true");   
            authenticator = new Authenticator() ...{   
                protected PasswordAuthentication getPasswordAuthentication() ...{   
                    return new PasswordAuthentication(smtpUsername, smtpPassword);   
                }   
            };   
        }   
  
        // Session session = Session.getInstance(props, null);   
        Session session = Session.getInstance(props, authenticator);  

 

 

如果发送的日志信息涉及到中文字符,还必须设定发送内容的编码,在sendBuffer()方法如修改设置content为如下所示,把编码方式指定为GB2312格式:

part.setContent(sbuf.toString(), layout.getContentType()+";charset=GB2312");  

 

 

最后添加三个新加属性的GETTER和SETTER,全部源代码如下所示:

package com.gftech.log4j;   
  
import java.util.Date;   
import java.util.Properties;   
  
import javax.mail.Authenticator;   
import javax.mail.Message;   
import javax.mail.MessagingException;   
import javax.mail.Multipart;   
import javax.mail.PasswordAuthentication;   
import javax.mail.Session;   
import javax.mail.Transport;   
import javax.mail.internet.AddressException;   
import javax.mail.internet.InternetAddress;   
import javax.mail.internet.MimeBodyPart;   
import javax.mail.internet.MimeMessage;   
import javax.mail.internet.MimeMultipart;   
  
import org.apache.log4j.AppenderSkeleton;   
import org.apache.log4j.Level;   
import org.apache.log4j.helpers.CyclicBuffer;   
import org.apache.log4j.helpers.LogLog;   
import org.apache.log4j.helpers.OptionConverter;   
import org.apache.log4j.spi.ErrorCode;   
import org.apache.log4j.spi.LoggingEvent;   
import org.apache.log4j.spi.TriggeringEventEvaluator;   
  
/**  
 * SMTP Appender扩展,增加对邮件认证的支持  
 *   
 * @author lenovo  
 *   
 */  
public class SMTPExtAppender extends AppenderSkeleton {   
    private String to;   
  
    private String from;   
  
    private String subject;   
  
    private String smtpHost;   
  
    // define auth info   
    private String smtpUsername;   
  
    private String smtpPassword;   
  
    private String smtpAuth;   
  
    // --------------------------   
  
    private int bufferSize = 512;   
  
    private boolean locationInfo = false;   
  
    protected CyclicBuffer cb = new CyclicBuffer(bufferSize);   
  
    protected Message msg;   
  
    protected TriggeringEventEvaluator evaluator;   
  
    /**  
     * The default constructor will instantiate the appender with a  
     * {@link TriggeringEventEvaluator} that will trigger on events with level  
     * ERROR or higher.  
     */  
    public SMTPExtAppender() {   
        this(new DefaultEvaluator());   
    }   
  
    /**  
     * Use <code>evaluator</code> passed as parameter as the {@link  
     * TriggeringEventEvaluator} for this SMTPAppender.  
     */  
    public SMTPExtAppender(TriggeringEventEvaluator evaluator) {   
        this.evaluator = evaluator;   
    }   
  
    /**  
     * Activate the specified options, such as the smtp host, the recipient,  
     * from, etc.  
     */  
    public void activateOptions() {   
        Properties props = new Properties(System.getProperties());   
        Authenticator authenticator = null;   
  
        if (smtpHost != null)   
            props.put("mail.smtp.host", smtpHost);   
  
        /**//* ADD auth code */  
        if (smtpAuth != null && smtpAuth.trim().equals("true")) {   
            props.put("mail.smtp.auth", "true");   
            authenticator = new Authenticator() {   
                protected PasswordAuthentication getPasswordAuthentication() {   
                    return new PasswordAuthentication(smtpUsername,   
                            smtpPassword);   
                }   
            };   
        }   
  
        // Session session = Session.getInstance(props, null);   
        Session session = Session.getInstance(props, authenticator);   
  
        // session.setDebug(true);   
        msg = new MimeMessage(session);   
  
        try {   
            if (from != null)   
                msg.setFrom(getAddress(from));   
            else  
                msg.setFrom();   
  
            msg.setRecipients(Message.RecipientType.TO, parseAddress(to));   
            if (subject != null)   
                msg.setSubject(subject);   
        } catch (MessagingException e) {   
            LogLog.error("Could not activate SMTPAppender options.", e);   
        }   
    }   
  
    /**  
     * Perform SMTPAppender specific appending actions, mainly adding the event  
     * to a cyclic buffer and checking if the event triggers an e-mail to be  
     * sent.  
     */  
    public void append(LoggingEvent event) {   
  
        if (!checkEntryConditions()) {   
            return;   
        }   
  
        event.getThreadName();   
        event.getNDC();   
        if (locationInfo) {   
            event.getLocationInformation();   
        }   
        cb.add(event);   
        if (evaluator.isTriggeringEvent(event)) {   
            sendBuffer();   
        }   
    }   
  
    /**  
     * This method determines if there is a sense in attempting to append.  
     *   
     * <p>  
     * It checks whether there is a set output target and also if there is a set  
     * layout. If these checks fail, then the boolean value <code>false</code>  
     * is returned.  
     */  
    protected boolean checkEntryConditions() {   
        if (this.msg == null) {   
            errorHandler.error("Message object not configured.");   
            return false;   
        }   
  
        if (this.evaluator == null) {   
            errorHandler   
                    .error("No TriggeringEventEvaluator is set for appender ["  
                            + name + "].");   
            return false;   
        }   
  
        if (this.layout == null) {   
            errorHandler.error("No layout set for appender named [" + name   
                    + "].");   
            return false;   
        }   
        return true;   
    }   
  
    synchronized public void close() {   
        this.closed = true;   
    }   
  
    InternetAddress getAddress(String addressStr) {   
        try {   
            return new InternetAddress(addressStr);   
        } catch (AddressException e) {   
            errorHandler.error("Could not parse address [" + addressStr + "].",   
                    e, ErrorCode.ADDRESS_PARSE_FAILURE);   
            return null;   
        }   
    }   
  
    InternetAddress[] parseAddress(String addressStr) {   
        try {   
            return InternetAddress.parse(addressStr, true);   
        } catch (AddressException e) {   
            errorHandler.error("Could not parse address [" + addressStr + "].",   
                    e, ErrorCode.ADDRESS_PARSE_FAILURE);   
            return null;   
        }   
    }   
  
    /**  
     * Returns value of the <b>To</b> option.  
     */  
    public String getTo() {   
        return to;   
    }   
  
    /**  
     * The <code>SMTPAppender</code> requires a  
     * {@link org.apache.log4j.Layout layout}.  
     */  
    public boolean requiresLayout() {   
        return true;   
    }   
  
    /**  
     * Send the contents of the cyclic buffer as an e-mail message.  
     */  
    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]);   
                        }   
                    }   
                }   
            }   
            t = layout.getFooter();   
            if (t != null)   
                sbuf.append(t);   
            part.setContent(sbuf.toString(), layout.getContentType()   
                    + ";charset=GB2312");   
  
            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);   
        }   
    }   
  
    /**  
     * Returns value of the <b>EvaluatorClass</b> option.  
     */  
    public String getEvaluatorClass() {   
        return evaluator == null ? null : evaluator.getClass().getName();   
    }   
  
    /**  
     * Returns value of the <b>From</b> option.  
     */  
    public String getFrom() {   
        return from;   
    }   
  
    /**  
     * Returns value of the <b>Subject</b> option.  
     */  
    public String getSubject() {   
        return subject;   
    }   
  
    /**  
     * The <b>From</b> option takes a string value which should be a e-mail  
     * address of the sender.  
     */  
    public void setFrom(String from) {   
        this.from = from;   
    }   
  
    /**  
     * The <b>Subject</b> option takes a string value which should be a the  
     * subject of the e-mail message.  
     */  
    public void setSubject(String subject) {   
        this.subject = subject;   
    }   
  
    /**  
     * The <b>BufferSize</b> option takes a positive integer representing the  
     * maximum number of logging events to collect in a cyclic buffer. When the  
     * <code>BufferSize</code> is reached, oldest events are deleted as new  
     * events are added to the buffer. By default the size of the cyclic buffer  
     * is 512 events.  
     */  
    public void setBufferSize(int bufferSize) {   
        this.bufferSize = bufferSize;   
        cb.resize(bufferSize);   
    }   
  
    /**  
     * The <b>SMTPHost</b> option takes a string value which should be a the  
     * host name of the SMTP server that will send the e-mail message.  
     */  
    public void setSMTPHost(String smtpHost) {   
        this.smtpHost = smtpHost;   
    }   
  
    /**  
     * Returns value of the <b>SMTPHost</b> option.  
     */  
    public String getSMTPHost() {   
        return smtpHost;   
    }   
  
  
    /**  
     * The <b>To</b> option takes a string value which should be a comma  
     * separated list of e-mail address of the recipients.  
     */  
    public void setTo(String to) {   
        this.to = to;   
    }   
  
  
    /**  
     * Returns value of the <b>BufferSize</b> option.  
     */  
    public int getBufferSize() {   
        return bufferSize;   
    }   
  
  
    /**  
     * The <b>EvaluatorClass</b> option takes a string value representing the  
     * name of the class implementing the {@link TriggeringEventEvaluator}  
     * interface. A corresponding object will be instantiated and assigned as  
     * the triggering event evaluator for the SMTPAppender.  
     */  
    public void setEvaluatorClass(String value) {   
        evaluator = (TriggeringEventEvaluator) OptionConverter   
                .instantiateByClassName(value, TriggeringEventEvaluator.class,   
                        evaluator);   
    }   
  
  
    /**  
     * The <b>LocationInfo</b> option takes a boolean value. By default, it is  
     * set to false which means there will be no effort to extract the location  
     * information related to the event. As a result, the layout that formats  
     * the events as they are sent out in an e-mail is likely to place the wrong  
     * location information (if present in the format).  
     *   
     * <p>  
     * Location information extraction is comparatively very slow and should be  
     * avoided unless performance is not a concern.  
     */  
    public void setLocationInfo(boolean locationInfo) {   
        this.locationInfo = locationInfo;   
    }   
  
  
    /**  
     * Returns value of the <b>LocationInfo</b> option.  
     */  
    public boolean getLocationInfo() {   
        return locationInfo;   
    }   
  
    public String getSMTPAuth() {   
        return smtpAuth;   
    }   
  
  
    /**  
     * 设置是否进行SMTP认证。  
     */  
    public void setSMTPAuth(String smtpAuth) {   
        this.smtpAuth = smtpAuth;   
    }   
  
  
    /**  
     * Returns value of the <b>SMTPPassword</b> option.  
     *   
     * @return <b>SMTPPassword</b>  
     */  
    public String getSMTPPassword() {   
        return smtpPassword;   
    }   
  
  
    /**  
     * 设置访问SMTP服务器的密码。  
     */  
    public void setSMTPPassword(String smtpPassword) {   
        this.smtpPassword = smtpPassword;   
    }   
  
  
    /**  
     * Returns value of the <b>SMTPUsername</b> option.  
     *   
     * @return <b>SMTPUsername</b>  
     */  
    public String getSMTPUsername() {   
        return smtpUsername;   
    }   
  
  
    /**  
     * 设置访问SMTP服务器的用户名。  
     */  
    public void setSMTPUsername(String smtpUsername) {   
        this.smtpUsername = smtpUsername;   
    }   
  
}   
  
class DefaultEvaluator implements TriggeringEventEvaluator {   
  
    /**  
     * Is this <code>event</code> the e-mail triggering event?  
     *   
     * <p>  
     * This method returns <code>true</code>, if the event level has ERROR  
     * level or higher. Otherwise it returns <code>false</code>.  
     */  
    public boolean isTriggeringEvent(LoggingEvent event) {   
        return event.getLevel().isGreaterOrEqual(Level.ERROR);   
    }   
}  

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值