【发布时间】:2019-04-29 11:12:06
【问题描述】:
我正在 Symfony 中创建一个微服务,我需要使用 RabbitMQ 来使用消息来创建一个文档。消费者正在工作,但每当抛出异常时,我想以某种格式和单独的日志文件记录异常。
我使用的是 Symfony 4.2,所有抛出的异常都记录在 dev.log 中。我在 Monolog 中创建了一个新频道并调用了异常,以便我可以管理我的日志记录。
对于这种方式,我使用了 ExceptionListener 并按照 Symfony 文档中的说明进行操作。
我的消费者设置如下
public function execute(AMQPMessage $msg): int
{
try {
return $this->documentService->createDocument($this->serializer->deserialize($msg->body, 'array', 'json'));
} catch (\Exception $e) {
$this->logger->error($e);
return ConsumerInterface::MSG_REJECT;
}
}
在服务中我有以下内容:
try {
...
$template = $this->templateRepository->findOneByName($messageData['template']);
if ($template === null) throw new \Exception('Template does not exist');
...
return ConsumerInterface::MSG_ACK;
} catch (\Exception $e) {
$this->logger->error($e);
return ConsumerInterface::MSG_REJECT;
}
我正在登录这两个类,但是当抛出异常时,我在控制台中得到了异常,但侦听器没有捕获到 ExceptionEvent。
我尝试了不同的事件并将 http-kernel 包添加到 Symfony,因为我使用的是 Symfony Flex,所以我没有所有包。
我在 services.yaml 中注册了我的监听器,如下所示:
App\EventListener\DocumentExceptionListener:
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
arguments:
$logger: '@monolog.logger.exception' # Log all exceptions to a separate log file
我的 ExceptionListener 如下:
public function __construct(LoggerInterface $logger, SerializerInterface $serializer)
{
$this->logger = $logger;
$this->serializer = $serializer;
$this->logger->info('Starting to listen...');
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$this->logger->info('currently listening...');
$this->log($event->getException());
}
private function log(\Exception $exception)
{
$log = [
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
'called' => [
'file' => $exception->getTrace()[0]['file'],
'line' => $exception->getTrace()[0]['line'],
],
'occurred' => [
'file' => $exception->getFile(),
'line' => $exception->getLine(),
],
];
if ($exception->getPrevious() instanceof Exception) {
$log += [
'previous' => [
'message' => $exception->getPrevious()->getMessage(),
'exception' => get_class($exception->getPrevious()),
'file' => $exception->getPrevious()->getFile(),
'line' => $exception->getPrevious()->getLine(),
],
];
}
$this->logger->error($this->serializer->serialize($log, 'json'));
}
我现在的输出是:
exception.INFO: Starting to listen... [] []
【问题讨论】:
-
由于您已经在服务中捕获了异常,因此永远不会使用第二个 catch 块(在您的使用者中)。从外观上看,您只在 Consumer 中使用自定义记录器,并且由于未调用 catch 块,因此永远不会使用它。
-
也不使用 ExceptionListener,因为您在侦听器可以处理异常之前捕获它。您必须重新抛出异常或确保您的服务已经使用新的记录器
-
我更新了我的代码,并从我的服务和我的消费者中删除了 Try Catch 语句......但侦听器仍然没有捕获。
-
即使我在函数的第一行添加了一个 throw,我的 Listener 也不会进入 onKernelException 方法
-
是的,ExceptionListener 仅适用于应用程序内部未捕获的异常。每当您抓住它们时,它都不会触发。也许不是让 ExceptionListener 尝试像
$this->logger->log($e->getMessage(), ['exception' => $e]);这样的东西,这将记录消息和完整的堆栈跟踪,而不需要特殊的侦听器
标签: php symfony error-handling rabbitmq consumer