我希望在我的Symfony2应用程序中发生不良事件时收到警报。现在我只是在日志中查找ERROR
。不幸的是,“HTTP 404 - 找不到文件”(NotFoundHttpException)被记录为错误,“HTTP 403 - 禁止”(AccessDeniedHttpException)。
这不保证错误;这些应该是警告。如何将这些日志设置为不太严重的级别?
示例错误:
[2012-07-02 16:58:21] request.ERROR: Symfony\Component\HttpKernel\Exception\NotFoundHttpException: No route found for "GET /foo" (uncaught exception) at /home/user/Symfony2_v2.0.12/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/EventListener/RouterListener.php line 83 [] []
答案 0 :(得分:8)
我找到了有用的东西。 Symfony2 internals doc on the kernel.exeption event提到可以对事件设置响应,GetResponseForExceptionEvent docs说
此事件的传播会立即停止 响应设定。
我拼凑了一个看起来像我想要的听众:
<?php
namespace Acme\DemoBundle\Listener;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class ExceptionLoggingListener {
private $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function onKernelException(GetResponseForExceptionEvent $event) {
if(!$event) {
$this->logger->err("Unknown kernel.exception in ".__CLASS__);
return;
}
$notFoundException = '\Symfony\Component\HttpKernel\Exception\NotFoundHttpException';
$e = $event->getException();
$type = get_class($e);
if ($e instanceof $notFoundException) {
$this->logger->info($e->getMessage());
$response = new Response(Response::$statusTexts[404], 404);
$event->setResponse($response);
return;
}
$accessDeniedException = '\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException';
if ($e instanceof $accessDeniedException) {
$this->logger->info($e->getMessage());
$response = new Response(Response::$statusTexts[403], 403);
$event->setResponse($response);
return;
}
$this->logger->err("kernel.exception of type $type. Message: '".$e->getMessage()."'\nFile: ".$e->getFile().", line ".$e->getLine()."\nTrace: ".$e->getTraceAsString());
}
}
答案 1 :(得分:6)
这是一种代码较少的方式:)
<强> 1。扩展Symfonys ExceptionListner类并覆盖日志记录方法:
<?php
use Symfony\Component\HttpKernel\EventListener\ExceptionListener as BaseListener;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ExceptionListener extends BaseListener
{
/**
* Logs an exception.
*
* @param \Exception $exception The original \Exception instance
* @param string $message The error message to log
* @param Boolean $original False when the handling of the exception thrown another exception
*/
protected function logException(\Exception $exception, $message, $original = true)
{
$isCritical = !$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500;
if (null !== $this->logger) {
if ($isCritical) {
$this->logger->critical($message);
} else {
if ($exception instanceof NotFoundHttpException) {
$this->logger->info($message);
} else {
$this->logger->error($message);
}
}
} elseif (!$original || $isCritical) {
error_log($message);
}
}
}
<强> 2。配置twig.exception_listener.class参数:
parameters:
twig.exception_listener.class: "MyBundle\EventListener\ExceptionListener"
答案 2 :(得分:5)
只需在您的配置中添加excluded_404s
:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_404s:
- ^/
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
请参阅http://symfony.com/doc/current/logging/monolog_regex_based_excludes.html以获取参考资料
答案 3 :(得分:1)
基于Tarjei答案的Symfony 5解决方案:
创建一个覆盖Symfony ErrorListener的新ErrorListener。
App \ EventListener \ ErrorListener.php
services:
App\EventListener\ErrorListener: '@exception_listener'
exception_listener:
autowire: false
class: App\EventListener\ErrorListener
arguments:
$controller: '%kernel.error_controller%'
$logger: '@logger'
$debug: '%kernel.debug%'
services.yaml
"Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[JIRA.Objects.DeletedWorkLog]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'values', line 1, position 10."
答案 4 :(得分:0)
您还可以使用错误级别活动策略(实际上Symfony的内置404错误排除是使用此操作完成的,所以我想这是一种正确的方法)。
<强> config.yml 强>
monolog:
handlers:
main:
type: fingers_crossed
handler: loggly
activation_strategy: 'mybundle.monolog.fingers_crossed.activation_strategy'
loggly:
type: loggly
token: %loggly_token%
level: error
tag: %loggly_tag%
services.yml (请注意,此处设置了操作级别,而不是在config.yml中设置)
services:
mybundle.monolog.fingers_crossed.activation_strategy:
class: MyBundle\Handler\FingersCrossed\ErrorLevelActivationStrategy
arguments:
- '@request_stack'
- 'error'
ErrorLevelActivationStrategy.php
<?php
namespace MyBundle\Handler\FingersCrossed;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy as BaseErrorLevelActivationStrategy;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Activation strategy that ignores client errors (4xx)
*/
class ErrorLevelActivationStrategy extends BaseErrorLevelActivationStrategy
{
protected $requestStack;
public function __construct(RequestStack $requestStack, $actionLevel)
{
parent::__construct($actionLevel);
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
public function isHandlerActivated(array $record)
{
$isActivated = parent::isHandlerActivated($record);
if (
$isActivated
&& isset($record['context']['exception'])
&& $record['context']['exception'] instanceof HttpException
&& $record['context']['exception']->getStatusCode() >= 400
&& $record['context']['exception']->getStatusCode() <= 499
&& ($request = $this->requestStack->getMasterRequest())
) {
$isActivated = false;
}
return $isActivated;
}
}
答案 5 :(得分:0)
在Symfony 3.3中首选此参数,而不是exclude_404s参数。
app / config / services.yml
exception_listener:
class: AppBundle\Listener\ExceptionListener
arguments: ["@logger", "@templating"]
tags:
- { name: kernel.event_listener, event: kernel.exception}
src / AppBundle / Listener / ExceptionListener.php
<?php
namespace AppBundle\Listener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Bridge\Monolog\Logger;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Templating\EngineInterface;
class ExceptionListener
{
private $logger;
private $templateEngine;
public function __construct(Logger $logger, EngineInterface $templateEngine)
{
$this->logger = $logger;
$this->templateEngine = $templateEngine;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof NotFoundHttpException)
{
$this->logger->info($exception->getMessage());
// default twig error app/config/Resources/TwigBundle/views/Exception/error.html.twig
$response = $this->templateEngine->render('TwigBundle:Exception:error.html.twig');
$event->setResponse(new Response($response));
}
}
}