在Catalyst中使用Plack :: Middleware兼容的异常时,日志输出丢失

时间:2014-03-28 13:24:39

标签: perl exception-handling catalyst plack

对于我的Catalyst项目,我使用自己的基于Moose的异常类型,它与Catalyst和我的命令行应用程序兼容。

为了向Catalyst REST接口的客户端提供错误消息,我实现了一个code子例程,它提供了http状态代码作为我的异常类的一部分。这样,我想使用Plack::Middleware的pod文档中描述的Plack::Middleware::HTTPExceptions

一切正常。异常以我希望返回的方式返回给客户端。

我的问题是:每当我抛出一个异常时,就会被中间件抓住,我的日志记录(Log::Log4perl)就会丢失,我在Catalyst'中找不到任何痕迹或错误。 s web服务器perl脚本输出。

每当我抛出错误时,我的异常类都没有封装,但是稀有字符串(如die "BOOM!"),会写入日志输出并记录错误(显然,错误是由{{1}捕获的并且不会被重新抛出。)

如果必须将异常重新抛给中间件,我如何告诉Catalyst保留日志记录请求?

2 个答案:

答案 0 :(得分:0)

这个问题似乎有两个部分,但我认为这涵盖了它。这确实是设置Log4perl以记录错误的问题,但有Catalyst和Plack考虑因素。

首先,这将是我将拥有的典型log4perl配置设置:

log4perl.logger                       = DEBUG, FileAppndr, Screen, DebugPanel
log4perl.appender.FileAppndr          = Log::Log4perl::Appender::File
log4perl.appender.FileAppndr.filename = log/server.log
log4perl.appender.FileAppndr.autoflush = 1
log4perl.appender.FileAppndr.stderr   = 1
log4perl.appender.FileAppndr.layout   = PatternLayout
log4perl.appender.FileAppndr.layout.ConversionPattern=%d [%p] - %m%n

log4perl.appender.Screen              = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.stderr       = 1
log4perl.appender.Screen.autoflush    = 1
log4perl.appender.Screen.layout       = PatternLayout
log4perl.appender.Screen.layout.ConversionPattern=%d [%p] - %m%n

请注意stderr值包含在1中。因此,这告诉log4perl捕获stderr以进行日志记录。

在Catalyst方面,我实际上有一些非常自定义的上下文初始化代码,但基本上设置了两件事情;

  1. 主要通过$c->log

  2. 将上下文记录器设置为Log::Log4perl::Catalyst
  3. 加载PSGI中间件Plack::Middleware::Log4perl。我实际上在加载catalyst配置时通过psgi_middleware配置键执行此操作。所以在配置行中没有比#34; Log4perl"因为一切都已经在" Plack :: Middleware"上下文路径。

  4. 第二部分将有#34;接送"加载的" log4perl"实例并分配给psgi.logger,以便任何PSGI组件可以根据需要访问记录器。

    那么,任何后来的陈述将会重新抛出"在这样的代码中:

      my $e = HTTP::Exception->new(404);
      $e->status_message("BOOM!!");
      $e->throw;
    

    实际上会在" log4perl"输出,以及任何原始die语句。

    至少在Catalyst 5.90060及更高版本上就是这种情况。关于HTTP :: Exception类型类,还有一些额外的细节需要添加。

答案 1 :(得分:0)

即使Neil的回答包含几个正确的陈述,我应用于我的Catalyst应用程序,但我没有得到任何输出。我通过子类Catalyst::Engine来解决这个问题。此子类仅重新定义finalize_error,并保持其余功能不变。在找到我自己的异常类型的情况下,我设置了一个单独的响应主体和状态代码,以通过重新抛出异常"梯形图来实现与我相同的结果"。