如果指定的日志文件有问题,Monolog的StreamHandler将抛出一个\UnexpectedValueException。
在我的代码中,我试图捕获\UnexpectedValueException,但我一直无法捕获。
我的代码是:
<?php
namespace myNamespace;
use Monolog\Logger as Monolog;
use Monolog\Handler\StreamHandler;
class Logger {
private static $instance;
private static function init()
{
if (!self::$instance)
{
$logger = new Monolog(MY_LOG_CHANNEL);
try
{
$logger->pushHandler(new StreamHandler(MY_LOG_PATH . "/" .
MY_LOG_NAME, Monolog::NOTICE));
}
catch (\UnexpectedValueException $e)
{
writeln("Error starting logger" . $e->getMessage());
die;
}
// and so on不管用,我明白了:
Fatal error: Uncaught exception 'UnexpectedValueException' with message 'The stream or
file [somefile.log] could not be opened: failed to open stream: No such file or
directory' in [path to src/Monolog/Handler/StreamHandler.php ]据我所知,他们已经逃到了全局名称空间,所以我应该能够在那里找到它。为什么不行?我尝试了命名空间\myNamesace\UnexpectedValueException的所有组合,甚至Monolog\UnexpectedValueException是全局的或本地的,但都没有效果。
很明显我漏掉了什么东西,请问是什么?
编辑:
在另一堂课上,我正在做一个if (file_exists($fileName)) /** do file_get_contents() etc */ else Logger::error($filename . "does not exist")
当我调用Logger::error()时,会在self::init()中触发错误
导致此错误的原因是我(有意)咀嚼了日志文件路径,如果它是有效的日志文件路径,则代码运行良好。显然,我想要捕获该错误,因此尝试/捕获。
跟踪的下一行是上面代码中的一行:$logger->pushHandler(new StreamHandler(MY_LOG_PATH . "/" . MY_LOG_NAME, Monolog::NOTICE));
有趣的是,如果我故意拼写文件名var、file_get_contents barfs和标准的catch (Exception $e),那么唯一能捕捉到异常的地方(目前这只是脚手架代码,还没有业务逻辑)就在file_get_contents()位中。
发布于 2015-01-28 20:25:54
这是一个很老的问题,很可能在这段时间内得到了解决。但是,为了将来的访问者,我想指出,当日志条目将被写入给定的文件时,而不是在构建时,就会抛出异常。
按照try { } catch () {}设置的方式,在创建StreamHandler时预期会出现异常。然而,当您试图通过$logger->error("Error message")这样的调用发送到日志时,真正的异常就会发生,因此您应该在那里捕获异常。
另一方面,我认为从日志库中抛出异常是最愚蠢的事情之一。日志记录应该是幂等的,不影响正在运行的应用程序的状态。
发布于 2019-12-11 11:13:50
在一个旧的silex应用程序中,我也遇到了这个问题。我想登录到logstash实例,但是如果logstash不可用,它不应该中断。
幸运的是,我的应用程序只使用针对Psr\Log\LoggerInterface输入的记录器,因此我可以编写一个装饰器,防止异常在一个地方中断应用程序,而不是在代码库中的每个调用上添加一个尝试和捕捉调用。
看起来是这样的:
<?php
namespace Dreamlines\DirectBookingForm\ServiceProvider;
use Psr\Log\LoggerInterface;
/**
* DontThrowLoggerDecorator
*
* Monolog will break on info, error, etc. calls
* This decorator wrap the LoggerInterface and ensures that failure to log won't break the app
**/
class DontThrowLoggerDecorator implements LoggerInterface
{
/**
* @var LoggerInterface
*/
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* @inheritDoc
*/
public function emergency($message, array $context = array())
{
try {
$this->logger->emergency($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function alert($message, array $context = array())
{
try {
$this->logger->alert($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function critical($message, array $context = array())
{
try {
$this->logger->critical($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function error($message, array $context = array())
{
try {
$this->logger->error($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function warning($message, array $context = array())
{
try {
$this->logger->warning($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function notice($message, array $context = array())
{
try {
$this->logger->notice($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function info($message, array $context = array())
{
try {
$this->logger->info($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function debug($message, array $context = array())
{
try {
$this->logger->debug($message, $context);
} catch (\Exception $e) {
}
}
/**
* @inheritDoc
*/
public function log($level, $message, array $context = array())
{
try {
$this->logger->log($level, $message, $context);
} catch (\Exception $e) {
}
}
}在我的silex应用程序中,我只是将我的记录器实例包装了一次,如下所示:
$app['NOT_BREAKING_LOGGER'] = $app->share(
function () use ($app) {
return new DontThrowLoggerDecorator($app['monolog']);
}
);我将NOT_BREAKING_LOGGER注入到我的每个服务中,而不是单一的服务。
https://stackoverflow.com/questions/20130380
复制相似问题