mfn提供的解决方案:
在通道数组中添加formatter
:
'formatter' => \Monolog\Formatter\MongoDBFormatter::class,
同时创建自定义格式化程序类,因为当前Laravel版本中使用的mongo formatter已经过时。
<?php
namespace Monolog\Formatter;
class MongoDBFormatter implements FormatterInterface
{
private $exceptionTraceAsString;
private $maxNestingLevel;
public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = true)
{
$this->maxNestingLevel = max($maxNestingLevel, 0);
$this->exceptionTraceAsString = (bool) $exceptionTraceAsString;
}
public function format(array $record)
{
return $this->formatArray($record);
}
public function formatBatch(array $records)
{
foreach ($records as $key => $record) {
$records[$key] = $this->format($record);
}
return $records;
}
protected function formatArray(array $record, $nestingLevel = 0)
{
if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) {
foreach ($record as $name => $value) {
if ($value instanceof \DateTime) {
$record[$name] = $this->formatDate($value, $nestingLevel + 1);
} elseif ($value instanceof \Exception) {
$record[$name] = $this->formatException($value, $nestingLevel + 1);
} elseif (is_array($value)) {
$record[$name] = $this->formatArray($value, $nestingLevel + 1);
} elseif (is_object($value)) {
$record[$name] = $this->formatObject($value, $nestingLevel + 1);
}
}
} else {
$record = '[...]';
}
return $record;
}
protected function formatObject($value, $nestingLevel)
{
$objectVars = get_object_vars($value);
$objectVars['class'] = get_class($value);
return $this->formatArray($objectVars, $nestingLevel);
}
protected function formatException(\Exception $exception, $nestingLevel)
{
$formattedException = array(
'class' => get_class($exception),
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
'file' => $exception->getFile() . ':' . $exception->getLine(),
);
if ($this->exceptionTraceAsString === true) {
$formattedException['trace'] = $exception->getTraceAsString();
} else {
$formattedException['trace'] = $exception->getTrace();
}
return $this->formatArray($formattedException, $nestingLevel);
}
protected function formatDate(\DateTime $value, $nestingLevel)
{
return new UTCDateTime($value->getTimestamp());
}
}
更新
目前我的自有实现:
config/logging.php
:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => [... , 'mongo'],
],
...
'mongo' => [
'driver' => 'custom',
'handler' => \Monolog\Handler\MongoDBHandler::class,
'via' => \App\Logging\MongoLogger::class,
'name' => 'mongo',
'host' => env('MONGODB_HOST'),
'port' => env('MONGODB_PORT'),
'database' => env('MONGODB_DATABASE'),
'collection' => env('MONGODB_COLLECTION')
]
],
MongoLogger
类:
<?php
namespace App\Logging;
use App\MongoDBFormatter;
use MongoDB\Client;
use Monolog\Handler\MongoDBHandler;
use Monolog\Logger;
class MongoLogger
{
public function __invoke(array $config)
{
$handler = new MongoDBHandler(
new Client('mongodb://'.$config['host'].':'.$config['port']),
$config['database'],
$config['collection']
);
$handler->setFormatter(new MongoDBFormatter());
return new Logger($config['name'], [$handler]);
}
}
MongoDBFormatter
类(稍作修改,顺便提一下,原版中有一些已弃用的类):
<?php
namespace App;
use Monolog\Formatter\FormatterInterface;
class MongoDBFormatter implements FormatterInterface
{
private $exceptionTraceAsString;
private $maxNestingLevel;
public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = true)
{
$this->maxNestingLevel = max($maxNestingLevel, 0);
$this->exceptionTraceAsString = (bool) $exceptionTraceAsString;
}
public function format(array $record)
{
return $this->formatArray($record);
}
public function formatBatch(array $records)
{
foreach ($records as $key => $record) {
$records[$key] = $this->format($record);
}
return $records;
}
protected function formatArray(array $record, $nestingLevel = 0)
{
if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) {
foreach ($record as $name => $value) {
if ($value instanceof \DateTime) {
$record[$name] = $this->formatDate($value, $nestingLevel + 1);
} elseif ($value instanceof \Exception) {
$record[$name] = $this->formatException($value, $nestingLevel + 1);
} elseif (is_array($value)) {
$record[$name] = $this->formatArray($value, $nestingLevel + 1);
} elseif (is_object($value)) {
$record[$name] = $this->formatObject($value, $nestingLevel + 1);
}
}
} else {
$record = '[...]';
}
return $record;
}
protected function formatObject($value, $nestingLevel)
{
$objectVars = get_object_vars($value);
$objectVars['class'] = get_class($value);
return $this->formatArray($objectVars, $nestingLevel);
}
protected function formatException(\Exception $exception, $nestingLevel)
{
$formattedException = array(
'class' => get_class($exception),
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
'file' => $exception->getFile() . ':' . $exception->getLine(),
);
if ($this->exceptionTraceAsString === true) {
$formattedException['trace'] = $exception->getTraceAsString();
} else {
$formattedException['trace'] = $exception->getTrace();
}
return $this->formatArray($formattedException, $nestingLevel);
}
protected function formatDate(\DateTime $value, $nestingLevel)
{
return $value;
}
}
答案来源。