4

在开发环境中,symfony ErrorHandler 可以捕获警告,这很好。在 prod env 中,symfony 忽略警告,我只在 php 错误日志中得到它们。现在我希望这些错误也被记录下来。

由于根本没有处理这些错误,因此对日志级别进行脱脂不起作用。那么如何在 Symfony prod 环境中记录这些错误呢?

我正在使用 Symfony 2.0

编辑:好的,我看到不处于调试模式(Kernel.php)时甚至没有错误处理程序:

if ($this->debug) {
        ini_set('display_errors', 1);
        error_reporting(-1);

        DebugUniversalClassLoader::enable();
        ErrorHandler::register();
        if ('cli' !== php_sapi_name()) {
            ExceptionHandler::register();
        }
} else {
    ini_set('display_errors', 0);
}

那么在不违反框架的情况下实现这一点的最佳方法是什么?

4

2 回答 2

2

您可以通过实现自定义ErrorHandler和覆盖某些AppKernel方法来做到这一点。例如:

class AppKernel
{
    protected $prodErrorHandler;
    public function init()
    {
        if ($this->debug) {
            ini_set('display_errors', 1);
            error_reporting(-1);

            DebugUniversalClassLoader::enable();
            ErrorHandler::register();
            if ('cli' !== php_sapi_name()) {
                ExceptionHandler::register();
            }
        } else {
            ini_set('display_errors', 0);
            error_reporting(-1);
            $this->prodErrorHandler = new CustomErrorHandler();
            set_error_handler(array($this->prodErrorHandler, 'handle'));
        }
    }
    public function boot()
    {
        $booted = $this->booted;
        parent::boot();
        if (!$booted && $this->prodErrorHandler !== null && $this->container->has('logger')) {
            $this->prodErrorHandler->setLogger($this->container->get('logger'));
        }
    }
    // ... other methods
}
class CustomErrorHandler
{
    protected $logger;
    protected $buffer = array();
    public function setLogger($logger)
    {
        $this->logger = $logger;
        foreach ($this->buffer as $error) {
            $this->logger->warning($error);
        }
        $this->buffer = array();
    }
    public function handle($level, $message, $file, $line, $context)
    {
        if (error_reporting() & $level) {
            $error = new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line));
            if ($this->logger !== null) {
                $this->logger->warning($error);
            } else {
                $this->buffer[] = $error;
            }
            return true;    // this would skip logging to file etc. Return false to just log and pass error handling to other handlers
        } else {
            return false;
        }
    }
}

类似的事情也可以用单独的 Bundle 完成,但它可以“跳过”在 bundle 注册之前发生的一些错误。

如果您使用Monolog 1.6或更高版本,您还可以使用Monolog\ErrorHandlerlogger 来注册错误、未处理的异常和致命错误。

于 2013-11-05T08:44:07.807 回答
0

您必须通过告诉内核在调试模式下运行来自定义您的环境来执行此操作。

new AppKernel('prod', true);

重要但与环境主题无关的是上面前端控制器第 8 行的错误键。这指定应用程序是否应在“调试模式”下运行。无论环境如何,Symfony2 应用程序都可以在调试模式设置为 true 或 false 的情况下运行。这会影响应用程序中的许多事情,例如是否应显示错误或是否在每个请求上动态重建缓存文件。尽管不是必需的,但调试模式通常设置为开发和测试环境的 true 和 prod 环境的 false。

http://symfony.com/doc/2.0/cookbook/configuration/environments.html

于 2013-03-05T19:13:20.747 回答