14

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 [] []
4

6 に答える 6

8

うまくいくものを見つけました。kernel.exeptionイベントのSymfony2内部ドキュメントには、イベントに応答を設定できると記載されており、GetResponseForExceptionEventドキュメントには次のように記載されています。

このイベントの伝播は、応答が設定されるとすぐに停止されます。

私は自分がやりたいことをしているように見えるリスナーを一緒に石畳にしました:

<?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());
  }

}
于 2012-07-03T00:54:33.113 に答える
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"
于 2013-03-18T19:09:09.283 に答える
6

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を参照してください

于 2016-10-17T07:54:40.787 に答える
1

エラーレベルのアクティビティ戦略を使用することもできます(実際には、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;
    }
}

https://gist.github.com/sobstel/d791d0347ee1f4e47b6e

于 2016-03-02T10:01:16.630 に答える
1

Tarjeiの答えに基づくSymfony5ソリューション:

SymfonyErrorListenerをオーバーライドする新しいErrorListenerを作成します。

App \ EventListener \ ErrorListener.php

<?php
declare(strict_types=1);

namespace App\EventListener;

use Symfony\Component\HttpKernel\EventListener\ErrorListener as BaseListener;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ErrorListener extends BaseListener
{
    /**
     * Logs an exception.
     *
     * @param \Exception $exception The original \Exception instance
     * @param string     $message   The error message to log
     */
    protected function logException(\Throwable $exception, string $message): void
    {
        $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);
                }
            }
        }
    }
}

services.yaml

services:
    App\EventListener\ErrorListener: '@exception_listener'

    exception_listener:
        autowire: false
        class: App\EventListener\ErrorListener
        arguments:
            $controller: '%kernel.error_controller%'
            $logger: '@logger'
            $debug: '%kernel.debug%'
于 2020-06-13T03:22:10.960 に答える
0

Symfony 3.3では、excluded_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));
        }
    }
}
于 2018-06-21T21:49:23.960 に答える