3 回答
TA贡献1880条经验 获得超4个赞
有一个简单的答案:处理异常不是捕获异常。
即使您将异常转换为 400 错误,您的异常仍未被捕获...这就是为什么 symfony 记录它并在此处完成。
如果您不想记录任何内容DomainException,只需重写该logException()方法,以便在它是 DomainException 的实例时跳过记录。
这是一个例子:
namespace App\EventListener;
use Symfony\Component\HttpKernel\EventListener\ErrorListener;
class ExceptionListener extends ErrorListener
{
protected function logException(\Exception $exception, string $message): void
{
if ($exception instanceof DomainException) {
return;
}
parent::logException($exception, $message);
}
}
最后你需要告诉 Symfony 使用这个类而不是 Symfony 的那个。由于服务定义没有类参数,exception_listener我建议使用编译器传递来替换类。
namespace App;
use App\EventListener\ExceptionListener;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class OverrideServiceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('exception_listener');
$definition->setClass(ExceptionListener::class);
}
}
有关更多详细信息,请参阅捆绑覆盖。
或者,只需用您自己的服务装饰服务exception_listener,不需要编译器传递:
App\EventListener\ExceptionListener:
decorates: 'exception_listener'
TA贡献1864条经验 获得超6个赞
我在虚拟应用程序上对其进行了测试,得到:
4 月 11 日 21:36:11 |批评| REQUES Uncaught PHP Exception App\Exception\DomainException: "This is no more logged" at D:\www\campagne\src\DataPersister\StationDataPersister.php line 53 Apr 11 23:36:12 |警告 | 服务器发布 (400) /api/stations
您可以实施自己的日志激活策略:
本代码基于HttpCode激活策略
namespace App\Log
use App\Exception\DomainException;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Activation strategy for logs
*/
class LogActivationStrategy extends ErrorLevelActivationStrategy
{
public function __construct()
{
parent::__construct('error');
}
public function isHandlerActivated(array $record): bool
{
$isActivated = parent::isHandlerActivated($record);
if ($isActivated && isset($record['context']['exception'])) {
$exception = $record['context']['exception'];
// This is a domain exception, I don't log it
return !$exception instanceof DomainException;
// OR if code could be different from 400
if ($exception instanceof DomainException) {
// This is a domain exception
// You log it when status code is different from 400.
return 400 !== $exception->getStatusCode();
}
}
return $isActivated;
}
}
我们还需要告诉 Monolog 使用我们的 ActivationStrategy
monolog:
handlers:
main:
type: fingers_crossed
action_level: info
handler: nested
activation_strategy: App\Log\LogActivationStrategy
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: info
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]
现在我的日志只包含:
4 月 11 日 23:41:07 |警告 | 服务器发布 (400) /api/stations
就像@yivi,我不喜欢我的解决方案,因为每次应用程序都会尝试记录一些东西,你会在这个函数上浪费时间......而且这个方法不会改变日志,它会删除它。
TA贡献1111条经验 获得超0个赞
在 Monolog 中,当使用fingers_crossed
日志处理程序时,将允许您从以特定状态响应的日志记录请求中排除,它只会在异常是以下实例时这样做HttpException
:
我通过实现订阅者将异常转换为BadRequestHttpException
.
final class DomainToHttpExceptionSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): iterable
{
return [ KernelEvents::EXCEPTION => 'convertException'];
}
public function convertException(ExceptionEvent $event): void
{
$exception = $event->getThrowable();
if ($exception instanceof DomainException) {
$event->setThrowable(
new BadRequestHttpException(
$exception->getMessage(),
$exception
)
);
}
}
}
这与这个独白配置相结合就可以了:
monolog:
handlers:
fingers:
type: fingers_crossed
action_level: warning
excluded_http_codes:
- 404
- 400
我从GitHub 问题的这个答案中得到了这个。它有效,但我不喜欢这个解决方案。希望有其他答案可以对此进行改进。
- 3 回答
- 0 关注
- 138 浏览
添加回答
举报