使用Google App Engine(GAE)进行回溯访问

时间:2021-12-20 23:15:52

I am working on a project that uses GAE as the backend for a mobile app. We want to have really good logging implemented in the project. I have spent a lot of time reading about log4j, logback-classic, logback-access, java.util.logging (JUL) and slf4j.

我正在开发一个使用GAE作为移动应用程序后端的项目。我们希望在项目中实现非常好的日志记录。我花了很多时间阅读有关log4j,logback-classic,logback-access,java.util.logging(JUL)和slf4j的文章。

My conclusion is that I want to use logback-access since it has some nice features when it comes to logging http related stuff (e.g. logging full-request-data upon errors etc.).

我的结论是我想使用logback-access,因为它在记录http相关内容时有一些很好的功能(例如,在出错时记录完整的请求数据等)。

Since GAE only supports the log levels for JUL and logback-access does not support slf4j, I thought that I should just install logback-access and make sure it writes all logs through JUL to GAE.

由于GAE仅支持JUL的日志级别,并且logback-access不支持slf4j,我认为我应该只安装logback-access并确保它将所有日志通过JUL写入GAE。

Is this possible? Has anyone done this and can guide me when it comes to the configuration files for logback-access and JUL? Can logback-access communicate directly through JUL, whithout me having to add a custom Appender (I am thinking about the connection to ch.qos.logback.access.jetty.RequestLogImpl that can be added to the configuration according to the docs)? Or does the logback-access configuration for Jetty not apply for GAE? Have I gotten something wrong?

这可能吗?有没有人这样做,并可以指导我在logback-access和JUL的配置文件?可以通过JUL直接进行logback-access通信,而不必添加自定义Appender(我正在考虑可以根据文档添加到配置中的ch.qos.logback.access.jetty.RequestLogImpl的连接)?或者Jetty的logback-access配置是否不适用于GAE?我弄错了什么?

Any tips are welcome!

欢迎任何提示!

1 个解决方案

#1


3  

We did that and stayed with logback for two years. The short story is that you will end up mixing JUL and logback settings, since your application will be using logback and Google classes will be using JUL directly (and you cannot redirect JUL into logback in GAE).

我们做到了这一点,并且退回了两年。简短的故事是,您最终会混合使用JUL和logback设置,因为您的应用程序将使用logback,而Google类将直接使用JUL(并且您无法将JUL重定向到GAE中的logback)。

After two years we switched to a slf4j + JUL configuration, it's easier and a single point of configuration. It is not easy, though (warning: tons of code follow):

两年后我们切换到slf4j + JUL配置,它更容易和单点配置。但这并不容易(警告:大量代码如下):

logging.properties:

.level = INFO
handlers = com.acme.log.InfoHandler,com.acme.log.ErrorHandler

# these should work, but they don't. See 
# http://code.google.com/p/googleappengine/issues/detail?id=7467
com.acme.log.InfoHandler.level=ALL
com.acme.log.ErrorHandler.level=WARNING

# Example of log level setup for a single class
# workaround http://code.google.com/p/google-guice/issues/detail?id=488
com.google.inject.internal.util.level = WARNING

InfoHandler.java:

/**
 * Logs {@link Level#INFO} to {@link System#out}.
 * This class is inspired by {@link ConsoleHandler}
 */
public class InfoHandler extends StreamHandler {

    public InfoHandler() {
        setOutputStream(System.out);
        setFilter(new MaxLevelFilter(Level.WARNING));
    }

    @Override
    public void publish(LogRecord record) {
        super.publish(record);  
        flush();
    }

    @Override
    public void close() {
        flush();
    }

}

ErrorHandler.java:

public class ErrorHandler extends StreamHandler {

    public ErrorHandler() {
        setOutputStream(System.err);
    }

    @Override
    public void publish(LogRecord record) {
        super.publish(record);  
        flush();
    }

    @Override
    public void close() {
        flush();
    }

}

MaxLevel.java:

public class MaxLevelFilter implements Filter {

    private final Level maxLevel;

    public MaxLevelFilter(Level level) {
        this.maxLevel = level;
    }

    @Override
    public boolean isLoggable(LogRecord record) {
        return maxLevel.intValue() > record.getLevel().intValue();
    }

}

You should also apply the workaround explained here at some application listener when the server starts.

您还应该在服务器启动时在某些应用程序侦听器中应用此处说明的解决方法。

#1


3  

We did that and stayed with logback for two years. The short story is that you will end up mixing JUL and logback settings, since your application will be using logback and Google classes will be using JUL directly (and you cannot redirect JUL into logback in GAE).

我们做到了这一点,并且退回了两年。简短的故事是,您最终会混合使用JUL和logback设置,因为您的应用程序将使用logback,而Google类将直接使用JUL(并且您无法将JUL重定向到GAE中的logback)。

After two years we switched to a slf4j + JUL configuration, it's easier and a single point of configuration. It is not easy, though (warning: tons of code follow):

两年后我们切换到slf4j + JUL配置,它更容易和单点配置。但这并不容易(警告:大量代码如下):

logging.properties:

.level = INFO
handlers = com.acme.log.InfoHandler,com.acme.log.ErrorHandler

# these should work, but they don't. See 
# http://code.google.com/p/googleappengine/issues/detail?id=7467
com.acme.log.InfoHandler.level=ALL
com.acme.log.ErrorHandler.level=WARNING

# Example of log level setup for a single class
# workaround http://code.google.com/p/google-guice/issues/detail?id=488
com.google.inject.internal.util.level = WARNING

InfoHandler.java:

/**
 * Logs {@link Level#INFO} to {@link System#out}.
 * This class is inspired by {@link ConsoleHandler}
 */
public class InfoHandler extends StreamHandler {

    public InfoHandler() {
        setOutputStream(System.out);
        setFilter(new MaxLevelFilter(Level.WARNING));
    }

    @Override
    public void publish(LogRecord record) {
        super.publish(record);  
        flush();
    }

    @Override
    public void close() {
        flush();
    }

}

ErrorHandler.java:

public class ErrorHandler extends StreamHandler {

    public ErrorHandler() {
        setOutputStream(System.err);
    }

    @Override
    public void publish(LogRecord record) {
        super.publish(record);  
        flush();
    }

    @Override
    public void close() {
        flush();
    }

}

MaxLevel.java:

public class MaxLevelFilter implements Filter {

    private final Level maxLevel;

    public MaxLevelFilter(Level level) {
        this.maxLevel = level;
    }

    @Override
    public boolean isLoggable(LogRecord record) {
        return maxLevel.intValue() > record.getLevel().intValue();
    }

}

You should also apply the workaround explained here at some application listener when the server starts.

您还应该在服务器启动时在某些应用程序侦听器中应用此处说明的解决方法。