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



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

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

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

我的问题是:每当我抛出一个异常,这是由中间件捕获的,我的日志(Log::Log4perl)丢失了,我既找不到Catalyst的web服务器perl脚本输出的痕迹也找不到错误。

每当我抛出错误时,没有被我的异常类封装,而是罕见的字符串(如die "BOOM!"),将写入日志输出并记录错误(显然,错误被Catalyst捕获并且不会重新抛出)。

我怎么能告诉Catalyst保持日志请求,即使异常必须被重新抛出到中间件?

这个问题似乎有两个部分,但我认为这涵盖了它。它实际上更多的是设置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。实际上,在加载催化剂配置时,我通过psgi_middleware配置键来做到这一点。所以在配置行中没有什么比"Log4perl"更多的了,因为一切都已经在"Plack::Middleware"上下文路径中。

第二部分将"拾取"加载的"log4perl"实例并将其分配给psgi.logger,以便任何PSGI组件都可以根据需要访问日志记录器。

那么,任何将在代码中被"重新抛出"的后续语句,例如:

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

实际上将在"log4perl"输出中拾取,以及任何原始的die语句。

至少在Catalyst 5.90060及以上版本是这样的。对于HTTP::Exception类型的类,还有一些额外的细节需要添加。

尽管Neil的答案包含了几个正确的语句,我将它们应用到我的Catalyst应用程序中,但我没有得到任何输出。我通过子类化Catalyst::Engine来解决这个问题。这个子类只重新定义finalize_error,其余的功能保持不变。在找到自己的异常类型的情况下,我设置了一个单独的响应体和状态代码,以获得与重新抛出异常"the ladder up"相同的结果。

相关内容

  • 没有找到相关文章

最新更新