在Symfony 2中记录警告和通知

时间:2013-02-28 09:52:34

标签: php logging symfony

在开发环境中,警告由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);
}

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

2 个答案:

答案 0 :(得分: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\ErrorHandler注册记录器以查找错误,未处理的异常和致命错误。

答案 1 :(得分:0)

您必须通过告诉内核以调试模式运行来自定义您的环境。

new AppKernel('prod', true);
  

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

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