【问题标题】:Google App Engine - Configure default logger to send emailGoogle App Engine - 配置默认记录器以发送电子邮件
【发布时间】:2011-06-10 15:27:14
【问题描述】:

在我的 GAE/J 应用程序中,如何配置默认记录器以通过电子邮件报告错误?

【问题讨论】:

    标签: java google-app-engine logging smtp java.util.logging


    【解决方案1】:

    一个 SMTPHandler 已经存在,但由于不满足的依赖关系而不能与 GAE/J 一起使用。看一下SMTPHandler的源码,适配GAE/J。

    【讨论】:

    • 我希望我不必走这条路。感谢您的回复。
    【解决方案2】:

    JavaMail 1.5.3 and later 中包含的MailHandler 已内置在support for Google App Engine 中。确保您使用的是最新版本的 JavaMail。

    对于 GAE/J,您可以下载 logging-mailhandler.jar 并将其包含在您的项目中。

    <dependency>
        <groupId>com.sun.mail</groupId>  
        <artifactId>logging-mailhandler</artifactId>  
        <version>1.5.3</version> 
        <scope>system</scope>
        <systemPath>FILE_PATH_TO/logging-mailhandler.jar</systemPath>
    </dependency>
    

    否则,可以使用java.net Maven repository 或Maven Central 并通过 groupid=com.sun.mail 和 artifactId=logging-mailhandler 拉取依赖项。

    <dependency>
        <groupId>com.sun.mail</groupId>  
        <artifactId>logging-mailhandler</artifactId>  
        <version>1.5.3</version> 
    </dependency>
    

    设置依赖项后,配置您的 logging.properties 以包含正确的日志设置和电子邮件信封。这是一个示例 logging.properties 文件:

        # A default java.util.logging configuration.
        # (All App Engine logging is through java.util.logging by default).
        #
        # To use this configuration, copy it into your application's WEB-INF
        # folder and add the following to your appengine-web.xml:
        # 
        # <system-properties>
        #   <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
        # </system-properties>
        #
    
        # Set the default logging level for all loggers to INFO
        .level = INFO
        java.util.logging.MemoryHandler.level=ALL
        java.util.logging.MemoryHandler.push=WARNING
        #com.sun.mail.util.logging.CompactFormatter.format=%1$tc %2$s%n%4$s: %5$s%6$s%n
        #com.sun.mail.util.logging.MailHandler.formatter=com.sun.mail.util.logging.CompactFormatter
        com.sun.mail.util.logging.MailHandler.level=WARNING
        com.sun.mail.util.logging.MailHandler.mail.from=me@example.com
        com.sun.mail.util.logging.MailHandler.mail.to=me@example.com
        #com.sun.mail.util.logging.MailHandler.pushLevel=OFF
        #com.sun.mail.util.logging.MailHandler.subject=com.sun.mail.util.logging.CollectorFormatter
        com.sun.mail.util.logging.MailHandler.verify=limited
    

    下一个create code to install the MailHandler,因为LogManager won't be able to see the logging-mailhandler.jar。

    这是一个 ServletContextListener 示例,它将在根记录器上安装 MailHandler。

    /**
     * Modify web.xml to include
     *  <listener>
     *       <description>Install MailHandler on root logger.</description>
     *       <listener-class>PACKAGE_NAME_FOR.MailHandlerConfig</listener-class>
     *  </listener>
     */
        import com.sun.mail.util.logging.*;
        import static com.google.appengine.api.ThreadManager.backgroundThreadFactory;
        import java.util.Arrays;
        import static java.util.concurrent.Executors.newScheduledThreadPool;
        import java.util.concurrent.Future;
        import java.util.concurrent.ScheduledExecutorService;
        import java.util.concurrent.TimeUnit;
        import java.util.logging.Formatter;
        import java.util.logging.Handler;
        import java.util.logging.Level;
        import java.util.logging.Logger;
        import java.util.logging.MemoryHandler;
        import javax.servlet.ServletContextEvent;
        import javax.servlet.ServletContextListener;
    
        public class MailHandlerConfig implements ServletContextListener, Runnable {
    
            private static final String LOGGER_NAME = "";
            private static final Logger logger = Logger.getLogger(LOGGER_NAME);
            private volatile ScheduledExecutorService ses;
            private volatile Future<?> task;
            private volatile Handler handler;
    
            @Override
            public void contextInitialized(ServletContextEvent sce) {
                MailHandler mh = new MailHandler();
                mh.setSubject(defaultSubject());
                handler = mh;
                try {
                    handler = new MemoryHandler(mh, mh.getCapacity(), mh.getPushLevel());
                    ses = newScheduledThreadPool(1, backgroundThreadFactory());
                    task = ses.scheduleAtFixedRate(this, 30L, 30L, TimeUnit.MINUTES);
                } catch (RuntimeException | LinkageError re) {
                    logger.log(Level.WARNING, "Unable to create push thread.", re);
                    Level lvl = mh.getLevel();
                    if (lvl.intValue() < mh.getPushLevel().intValue()) {
                        mh.setPushLevel(lvl);
                        handler = mh;
                        logger.log(Level.WARNING, "Forcing push level to {0}.", lvl);
                    }
                }
                logger.addHandler(handler);
                logger.log(Level.INFO, "Application initialized. {0}",
                        Arrays.toString(logger.getHandlers()));
            }
    
            @Override
            public void contextDestroyed(ServletContextEvent sce) {
                //Never called under GAE.
                try {
                    Future<?> f = task;
                    if (f != null) {
                        f.cancel(false);
                    }
                } catch (RuntimeException ignore) {
                }
    
                try {
                    ScheduledExecutorService e = this.ses;
                    if (e != null) {
                        e.shutdown();
                    }
                } catch (RuntimeException ignore) {
                }
    
                try {
                    Handler h = handler;
                    if (h != null) {
                        h.close();
                        logger.removeHandler(h);
                    }
                } catch (RuntimeException ignore) {
                }
                run();
            }
    
            @Override
            public void run() {
                for (Handler h : logger.getHandlers()) {
                    try {
                        if (h instanceof MemoryHandler) {
                            ((MemoryHandler) h).push();
                        }
                        h.flush();
                    } catch (RuntimeException ignore) {
                    }
                }
            }
    
            private static Formatter defaultSubject() {
                return new CollectorFormatter(
                        "{0}{1}{2}{4,choice,-1#|0#|0<... {4,number,integer} more}",
                        new CompactFormatter("%7$#.160s"),
                        new SeverityComparator());
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2010-10-27
      • 2016-12-04
      • 2012-10-11
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 2012-04-10
      • 2015-02-25
      • 2011-03-21
      相关资源
      最近更新 更多