summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Monolog/DateTimeImmutable.php64
-rw-r--r--src/Monolog/ErrorHandler.php86
-rw-r--r--src/Monolog/Formatter/ChromePHPFormatter.php17
-rw-r--r--src/Monolog/Formatter/ElasticaFormatter.php21
-rw-r--r--src/Monolog/Formatter/FlowdockFormatter.php29
-rw-r--r--src/Monolog/Formatter/FluentdFormatter.php18
-rw-r--r--src/Monolog/Formatter/FormatterInterface.php2
-rw-r--r--src/Monolog/Formatter/GelfMessageFormatter.php19
-rw-r--r--src/Monolog/Formatter/HtmlFormatter.php26
-rw-r--r--src/Monolog/Formatter/JsonFormatter.php67
-rw-r--r--src/Monolog/Formatter/LineFormatter.php36
-rw-r--r--src/Monolog/Formatter/LogglyFormatter.php12
-rw-r--r--src/Monolog/Formatter/LogmaticFormatter.php72
-rw-r--r--src/Monolog/Formatter/LogstashFormatter.php89
-rw-r--r--src/Monolog/Formatter/MongoDBFormatter.php63
-rw-r--r--src/Monolog/Formatter/NormalizerFormatter.php112
-rw-r--r--src/Monolog/Formatter/ScalarFormatter.php4
-rw-r--r--src/Monolog/Formatter/WildfireFormatter.php30
-rw-r--r--src/Monolog/Handler/AbstractHandler.php111
-rw-r--r--src/Monolog/Handler/AbstractProcessingHandler.php30
-rw-r--r--src/Monolog/Handler/AbstractSyslogHandler.php15
-rw-r--r--src/Monolog/Handler/AmqpHandler.php32
-rw-r--r--src/Monolog/Handler/BrowserConsoleHandler.php25
-rw-r--r--src/Monolog/Handler/BufferHandler.php18
-rw-r--r--src/Monolog/Handler/ChromePHPHandler.php59
-rw-r--r--src/Monolog/Handler/CouchDBHandler.php21
-rw-r--r--src/Monolog/Handler/CubeHandler.php10
-rw-r--r--src/Monolog/Handler/Curl/Util.php6
-rw-r--r--src/Monolog/Handler/DeduplicationHandler.php7
-rw-r--r--src/Monolog/Handler/DoctrineCouchDBHandler.php5
-rw-r--r--src/Monolog/Handler/DynamoDbHandler.php9
-rw-r--r--src/Monolog/Handler/ElasticSearchHandler.php16
-rw-r--r--src/Monolog/Handler/ErrorLogHandler.php22
-rw-r--r--src/Monolog/Handler/FilterHandler.php18
-rw-r--r--src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php2
-rw-r--r--src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php4
-rw-r--r--src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php2
-rw-r--r--src/Monolog/Handler/FingersCrossedHandler.php22
-rw-r--r--src/Monolog/Handler/FirePHPHandler.php45
-rw-r--r--src/Monolog/Handler/FleepHookHandler.php9
-rw-r--r--src/Monolog/Handler/FlowdockHandler.php8
-rw-r--r--src/Monolog/Handler/FormattableHandlerInterface.php37
-rw-r--r--src/Monolog/Handler/FormattableHandlerTrait.php60
-rw-r--r--src/Monolog/Handler/GelfHandler.php22
-rw-r--r--src/Monolog/Handler/GroupHandler.php16
-rw-r--r--src/Monolog/Handler/Handler.php53
-rw-r--r--src/Monolog/Handler/HandlerInterface.php38
-rw-r--r--src/Monolog/Handler/HandlerWrapper.php50
-rw-r--r--src/Monolog/Handler/HipChatHandler.php93
-rw-r--r--src/Monolog/Handler/IFTTTHandler.php10
-rw-r--r--src/Monolog/Handler/LogEntriesHandler.php2
-rw-r--r--src/Monolog/Handler/LogglyHandler.php15
-rw-r--r--src/Monolog/Handler/LogmaticHandler.php88
-rw-r--r--src/Monolog/Handler/MailHandler.php26
-rw-r--r--src/Monolog/Handler/MandrillHandler.php15
-rw-r--r--src/Monolog/Handler/MissingExtensionException.php2
-rw-r--r--src/Monolog/Handler/MongoDBHandler.php60
-rw-r--r--src/Monolog/Handler/NativeMailerHandler.php23
-rw-r--r--src/Monolog/Handler/NewRelicHandler.php5
-rw-r--r--src/Monolog/Handler/NoopHandler.php40
-rw-r--r--src/Monolog/Handler/NullHandler.php20
-rw-r--r--src/Monolog/Handler/PHPConsoleHandler.php50
-rw-r--r--src/Monolog/Handler/ProcessHandler.php202
-rw-r--r--src/Monolog/Handler/ProcessableHandlerInterface.php36
-rw-r--r--src/Monolog/Handler/ProcessableHandlerTrait.php62
-rw-r--r--src/Monolog/Handler/PsrHandler.php4
-rw-r--r--src/Monolog/Handler/PushoverHandler.php14
-rw-r--r--src/Monolog/Handler/RavenHandler.php28
-rw-r--r--src/Monolog/Handler/RedisHandler.php9
-rw-r--r--src/Monolog/Handler/RollbarHandler.php16
-rw-r--r--src/Monolog/Handler/RotatingFileHandler.php28
-rw-r--r--src/Monolog/Handler/SamplingHandler.php14
-rw-r--r--src/Monolog/Handler/SendGridHandler.php100
-rw-r--r--src/Monolog/Handler/Slack/SlackRecord.php11
-rw-r--r--src/Monolog/Handler/SlackHandler.php6
-rw-r--r--src/Monolog/Handler/SlackWebhookHandler.php26
-rw-r--r--src/Monolog/Handler/SlackbotHandler.php12
-rw-r--r--src/Monolog/Handler/SocketHandler.php17
-rw-r--r--src/Monolog/Handler/SqsHandler.php53
-rw-r--r--src/Monolog/Handler/StreamHandler.php10
-rw-r--r--src/Monolog/Handler/SwiftMailerHandler.php48
-rw-r--r--src/Monolog/Handler/SyslogHandler.php2
-rw-r--r--src/Monolog/Handler/SyslogUdp/UdpSocket.php6
-rw-r--r--src/Monolog/Handler/SyslogUdpHandler.php10
-rw-r--r--src/Monolog/Handler/TestHandler.php18
-rw-r--r--src/Monolog/Handler/WhatFailureGroupHandler.php8
-rw-r--r--src/Monolog/Handler/ZendMonitorHandler.php10
-rw-r--r--src/Monolog/Logger.php392
-rw-r--r--src/Monolog/Processor/GitProcessor.php16
-rw-r--r--src/Monolog/Processor/IntrospectionProcessor.php22
-rw-r--r--src/Monolog/Processor/MemoryPeakUsageProcessor.php8
-rw-r--r--src/Monolog/Processor/MemoryProcessor.php14
-rw-r--r--src/Monolog/Processor/MemoryUsageProcessor.php8
-rw-r--r--src/Monolog/Processor/MercurialProcessor.php19
-rw-r--r--src/Monolog/Processor/ProcessIdProcessor.php8
-rw-r--r--src/Monolog/Processor/PsrLogMessageProcessor.php20
-rw-r--r--src/Monolog/Processor/TagProcessor.php10
-rw-r--r--src/Monolog/Processor/UidProcessor.php10
-rw-r--r--src/Monolog/Processor/WebProcessor.php27
-rw-r--r--src/Monolog/Registry.php19
-rw-r--r--src/Monolog/Test/TestCase.php66
101 files changed, 1979 insertions, 1398 deletions
diff --git a/src/Monolog/DateTimeImmutable.php b/src/Monolog/DateTimeImmutable.php
new file mode 100644
index 0000000..4e9f598
--- /dev/null
+++ b/src/Monolog/DateTimeImmutable.php
@@ -0,0 +1,64 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+/**
+ * Overrides default json encoding of date time objects
+ *
+ * @author Menno Holtkamp
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
+{
+ private $useMicroseconds;
+
+ public function __construct($useMicroseconds, \DateTimeZone $timezone = null)
+ {
+ static $needsMicrosecondsHack = PHP_VERSION_ID < 70100;
+
+ $this->useMicroseconds = $useMicroseconds;
+ $date = 'now';
+
+ if ($needsMicrosecondsHack && $useMicroseconds) {
+ $timestamp = microtime(true);
+
+ // apply offset of the timezone as microtime() is always UTC
+ if ($timezone && $timezone->getName() !== 'UTC') {
+ $timestamp += (new \DateTime('now', $timezone))->getOffset();
+ }
+
+ // Circumvent DateTimeImmutable::createFromFormat() which always returns \DateTimeImmutable instead of `static`
+ // @link https://bugs.php.net/bug.php?id=60302
+ //
+ // So we create a DateTime but then format it so we
+ // can re-create one using the right class
+ $dt = self::createFromFormat('U.u', sprintf('%.6F', $timestamp));
+ $date = $dt->format('Y-m-d H:i:s.u');
+ }
+
+ parent::__construct($date, $timezone);
+ }
+
+ public function jsonSerialize(): string
+ {
+ if ($this->useMicroseconds) {
+ return $this->format('Y-m-d\TH:i:s.uP');
+ }
+
+ return $this->format('Y-m-d\TH:i:sP');
+ }
+
+ public function __toString(): string
+ {
+ return $this->jsonSerialize();
+ }
+}
diff --git a/src/Monolog/ErrorHandler.php b/src/Monolog/ErrorHandler.php
index 7bfcd83..d0b1aa6 100644
--- a/src/Monolog/ErrorHandler.php
+++ b/src/Monolog/ErrorHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -13,7 +13,6 @@ namespace Monolog;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
-use Monolog\Handler\AbstractHandler;
/**
* Monolog error handler
@@ -29,7 +28,7 @@ class ErrorHandler
private $logger;
private $previousExceptionHandler;
- private $uncaughtExceptionLevel;
+ private $uncaughtExceptionLevelMap;
private $previousErrorHandler;
private $errorLevelMap;
@@ -38,7 +37,7 @@ class ErrorHandler
private $hasFatalErrorHandler;
private $fatalLevel;
private $reservedMemory;
- private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);
+ private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
public function __construct(LoggerInterface $logger)
{
@@ -51,12 +50,12 @@ class ErrorHandler
* By default it will handle errors, exceptions and fatal errors
*
* @param LoggerInterface $logger
- * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
- * @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling
- * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling
+ * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
+ * @param array|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
+ * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling
* @return ErrorHandler
*/
- public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null)
+ public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self
{
//Forces the autoloader to run for LogLevel. Fixes an autoload issue at compile-time on PHP5.3. See https://github.com/Seldaek/monolog/pull/929
class_exists('\\Psr\\Log\\LogLevel', true);
@@ -65,8 +64,8 @@ class ErrorHandler
if ($errorLevelMap !== false) {
$handler->registerErrorHandler($errorLevelMap);
}
- if ($exceptionLevel !== false) {
- $handler->registerExceptionHandler($exceptionLevel);
+ if ($exceptionLevelMap !== false) {
+ $handler->registerExceptionHandler($exceptionLevelMap);
}
if ($fatalLevel !== false) {
$handler->registerFatalHandler($fatalLevel);
@@ -75,38 +74,57 @@ class ErrorHandler
return $handler;
}
- public function registerExceptionHandler($level = null, $callPrevious = true)
+ public function registerExceptionHandler($levelMap = [], $callPrevious = true): self
{
- $prev = set_exception_handler(array($this, 'handleException'));
- $this->uncaughtExceptionLevel = $level;
+ $prev = set_exception_handler([$this, 'handleException']);
+ $this->uncaughtExceptionLevelMap = $levelMap;
+ foreach ($this->defaultExceptionLevelMap() as $class => $level) {
+ if (!isset($this->uncaughtExceptionLevelMap[$class])) {
+ $this->uncaughtExceptionLevelMap[$class] = $level;
+ }
+ }
if ($callPrevious && $prev) {
$this->previousExceptionHandler = $prev;
}
+
+ return $this;
}
- public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true)
+ public function registerErrorHandler(array $levelMap = [], $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true): self
{
- $prev = set_error_handler(array($this, 'handleError'), $errorTypes);
+ $prev = set_error_handler([$this, 'handleError'], $errorTypes);
$this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
if ($callPrevious) {
$this->previousErrorHandler = $prev ?: true;
}
$this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
+
+ return $this;
}
- public function registerFatalHandler($level = null, $reservedMemorySize = 20)
+ public function registerFatalHandler($level = null, $reservedMemorySize = 20): self
{
- register_shutdown_function(array($this, 'handleFatalError'));
+ register_shutdown_function([$this, 'handleFatalError']);
$this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
$this->fatalLevel = $level;
$this->hasFatalErrorHandler = true;
+
+ return $this;
+ }
+
+ protected function defaultExceptionLevelMap(): array
+ {
+ return [
+ 'ParseError' => LogLevel::CRITICAL,
+ 'Throwable' => LogLevel::ERROR,
+ ];
}
- protected function defaultErrorLevelMap()
+ protected function defaultErrorLevelMap(): array
{
- return array(
+ return [
E_ERROR => LogLevel::CRITICAL,
E_WARNING => LogLevel::WARNING,
E_PARSE => LogLevel::ALERT,
@@ -122,7 +140,7 @@ class ErrorHandler
E_RECOVERABLE_ERROR => LogLevel::ERROR,
E_DEPRECATED => LogLevel::NOTICE,
E_USER_DEPRECATED => LogLevel::NOTICE,
- );
+ ];
}
/**
@@ -130,10 +148,18 @@ class ErrorHandler
*/
public function handleException($e)
{
+ $level = LogLevel::ERROR;
+ foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
+ if ($e instanceof $class) {
+ $level = $candidate;
+ break;
+ }
+ }
+
$this->logger->log(
- $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel,
+ $level,
sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()),
- array('exception' => $e)
+ ['exception' => $e]
);
if ($this->previousExceptionHandler) {
@@ -146,7 +172,7 @@ class ErrorHandler
/**
* @private
*/
- public function handleError($code, $message, $file = '', $line = 0, $context = array())
+ public function handleError($code, $message, $file = '', $line = 0, $context = [])
{
if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) {
return;
@@ -154,8 +180,8 @@ class ErrorHandler
// fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
- $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
- $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
+ $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
+ $this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
}
if ($this->previousErrorHandler === true) {
@@ -170,27 +196,25 @@ class ErrorHandler
*/
public function handleFatalError()
{
- $this->reservedMemory = null;
+ $this->reservedMemory = '';
$lastError = error_get_last();
if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) {
$this->logger->log(
$this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
- array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'])
+ ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']]
);
if ($this->logger instanceof Logger) {
foreach ($this->logger->getHandlers() as $handler) {
- if ($handler instanceof AbstractHandler) {
- $handler->close();
- }
+ $handler->close();
}
}
}
}
- private static function codeToString($code)
+ private static function codeToString($code): string
{
switch ($code) {
case E_ERROR:
diff --git a/src/Monolog/Formatter/ChromePHPFormatter.php b/src/Monolog/Formatter/ChromePHPFormatter.php
index 9beda1e..2b4d649 100644
--- a/src/Monolog/Formatter/ChromePHPFormatter.php
+++ b/src/Monolog/Formatter/ChromePHPFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -23,7 +23,7 @@ class ChromePHPFormatter implements FormatterInterface
/**
* Translates Monolog log levels to Wildfire levels.
*/
- private $logLevels = array(
+ private $logLevels = [
Logger::DEBUG => 'log',
Logger::INFO => 'info',
Logger::NOTICE => 'info',
@@ -32,7 +32,7 @@ class ChromePHPFormatter implements FormatterInterface
Logger::CRITICAL => 'error',
Logger::ALERT => 'error',
Logger::EMERGENCY => 'error',
- );
+ ];
/**
* {@inheritdoc}
@@ -46,7 +46,7 @@ class ChromePHPFormatter implements FormatterInterface
unset($record['extra']['file'], $record['extra']['line']);
}
- $message = array('message' => $record['message']);
+ $message = ['message' => $record['message']];
if ($record['context']) {
$message['context'] = $record['context'];
}
@@ -57,17 +57,20 @@ class ChromePHPFormatter implements FormatterInterface
$message = reset($message);
}
- return array(
+ return [
$record['channel'],
$message,
$backtrace,
$this->logLevels[$record['level']],
- );
+ ];
}
+ /**
+ * {@inheritdoc}
+ */
public function formatBatch(array $records)
{
- $formatted = array();
+ $formatted = [];
foreach ($records as $record) {
$formatted[] = $this->format($record);
diff --git a/src/Monolog/Formatter/ElasticaFormatter.php b/src/Monolog/Formatter/ElasticaFormatter.php
index 4c556cf..a6354f5 100644
--- a/src/Monolog/Formatter/ElasticaFormatter.php
+++ b/src/Monolog/Formatter/ElasticaFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -34,7 +34,7 @@ class ElasticaFormatter extends NormalizerFormatter
* @param string $index Elastic Search index name
* @param string $type Elastic Search document type
*/
- public function __construct($index, $type)
+ public function __construct(string $index, string $type)
{
// elasticsearch requires a ISO 8601 format date with optional millisecond precision.
parent::__construct('Y-m-d\TH:i:s.uP');
@@ -53,31 +53,20 @@ class ElasticaFormatter extends NormalizerFormatter
return $this->getDocument($record);
}
- /**
- * Getter index
- * @return string
- */
- public function getIndex()
+ public function getIndex(): string
{
return $this->index;
}
- /**
- * Getter type
- * @return string
- */
- public function getType()
+ public function getType(): string
{
return $this->type;
}
/**
* Convert a log message into an Elastica Document
- *
- * @param array $record Log message
- * @return Document
*/
- protected function getDocument($record)
+ protected function getDocument(array $record): Document
{
$document = new Document();
$document->setData($record);
diff --git a/src/Monolog/Formatter/FlowdockFormatter.php b/src/Monolog/Formatter/FlowdockFormatter.php
index 5094af3..301b74b 100644
--- a/src/Monolog/Formatter/FlowdockFormatter.php
+++ b/src/Monolog/Formatter/FlowdockFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -28,11 +28,7 @@ class FlowdockFormatter implements FormatterInterface
*/
private $sourceEmail;
- /**
- * @param string $source
- * @param string $sourceEmail
- */
- public function __construct($source, $sourceEmail)
+ public function __construct(string $source, string $sourceEmail)
{
$this->source = $source;
$this->sourceEmail = $sourceEmail;
@@ -41,13 +37,13 @@ class FlowdockFormatter implements FormatterInterface
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): array
{
- $tags = array(
+ $tags = [
'#logs',
'#' . strtolower($record['level_name']),
'#' . $record['channel'],
- );
+ ];
foreach ($record['extra'] as $value) {
$tags[] = '#' . $value;
@@ -60,14 +56,14 @@ class FlowdockFormatter implements FormatterInterface
$this->getShortMessage($record['message'])
);
- $record['flowdock'] = array(
+ $record['flowdock'] = [
'source' => $this->source,
'from_address' => $this->sourceEmail,
'subject' => $subject,
'content' => $record['message'],
'tags' => $tags,
'project' => $this->source,
- );
+ ];
return $record;
}
@@ -75,9 +71,9 @@ class FlowdockFormatter implements FormatterInterface
/**
* {@inheritdoc}
*/
- public function formatBatch(array $records)
+ public function formatBatch(array $records): array
{
- $formatted = array();
+ $formatted = [];
foreach ($records as $record) {
$formatted[] = $this->format($record);
@@ -86,12 +82,7 @@ class FlowdockFormatter implements FormatterInterface
return $formatted;
}
- /**
- * @param string $message
- *
- * @return string
- */
- public function getShortMessage($message)
+ public function getShortMessage(string $message): string
{
static $hasMbString;
diff --git a/src/Monolog/Formatter/FluentdFormatter.php b/src/Monolog/Formatter/FluentdFormatter.php
index 02632bb..a84f826 100644
--- a/src/Monolog/Formatter/FluentdFormatter.php
+++ b/src/Monolog/Formatter/FluentdFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -39,41 +39,41 @@ class FluentdFormatter implements FormatterInterface
*/
protected $levelTag = false;
- public function __construct($levelTag = false)
+ public function __construct(bool $levelTag = false)
{
if (!function_exists('json_encode')) {
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter');
}
- $this->levelTag = (bool) $levelTag;
+ $this->levelTag = $levelTag;
}
- public function isUsingLevelsInTag()
+ public function isUsingLevelsInTag(): bool
{
return $this->levelTag;
}
- public function format(array $record)
+ public function format(array $record): string
{
$tag = $record['channel'];
if ($this->levelTag) {
$tag .= '.' . strtolower($record['level_name']);
}
- $message = array(
+ $message = [
'message' => $record['message'],
'extra' => $record['extra'],
- );
+ ];
if (!$this->levelTag) {
$message['level'] = $record['level'];
$message['level_name'] = $record['level_name'];
}
- return json_encode(array($tag, $record['datetime']->getTimestamp(), $message));
+ return json_encode([$tag, $record['datetime']->getTimestamp(), $message]);
}
- public function formatBatch(array $records)
+ public function formatBatch(array $records): string
{
$message = '';
foreach ($records as $record) {
diff --git a/src/Monolog/Formatter/FormatterInterface.php b/src/Monolog/Formatter/FormatterInterface.php
index b5de751..7442134 100644
--- a/src/Monolog/Formatter/FormatterInterface.php
+++ b/src/Monolog/Formatter/FormatterInterface.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
diff --git a/src/Monolog/Formatter/GelfMessageFormatter.php b/src/Monolog/Formatter/GelfMessageFormatter.php
index 2c1b0e8..4e95a6e 100644
--- a/src/Monolog/Formatter/GelfMessageFormatter.php
+++ b/src/Monolog/Formatter/GelfMessageFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -47,7 +47,7 @@ class GelfMessageFormatter extends NormalizerFormatter
/**
* Translates Monolog log levels to Graylog2 log priorities.
*/
- private $logLevels = array(
+ private $logLevels = [
Logger::DEBUG => 7,
Logger::INFO => 6,
Logger::NOTICE => 5,
@@ -56,9 +56,9 @@ class GelfMessageFormatter extends NormalizerFormatter
Logger::CRITICAL => 2,
Logger::ALERT => 1,
Logger::EMERGENCY => 0,
- );
+ ];
- public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $maxLength = null)
+ public function __construct(string $systemName = null, string $extraPrefix = null, string $contextPrefix = 'ctxt_', int $maxLength = null)
{
parent::__construct('U.u');
@@ -72,9 +72,14 @@ class GelfMessageFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): Message
{
- $record = parent::format($record);
+ if (isset($record['context'])) {
+ $record['context'] = parent::format($record['context']);
+ }
+ if (isset($record['extra'])) {
+ $record['extra'] = parent::format($record['extra']);
+ }
if (!isset($record['datetime'], $record['message'], $record['level'])) {
throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given');
@@ -87,7 +92,7 @@ class GelfMessageFormatter extends NormalizerFormatter
->setHost($this->systemName)
->setLevel($this->logLevels[$record['level']]);
- // message length + system name length + 200 for padding / metadata
+ // message length + system name length + 200 for padding / metadata
$len = 200 + strlen((string) $record['message']) + strlen($this->systemName);
if ($len > $this->maxLength) {
diff --git a/src/Monolog/Formatter/HtmlFormatter.php b/src/Monolog/Formatter/HtmlFormatter.php
index 3eec95f..a343b06 100644
--- a/src/Monolog/Formatter/HtmlFormatter.php
+++ b/src/Monolog/Formatter/HtmlFormatter.php
@@ -1,4 +1,5 @@
-<?php
+<?php declare(strict_types=1);
+
/*
* This file is part of the Monolog package.
*
@@ -24,7 +25,7 @@ class HtmlFormatter extends NormalizerFormatter
/**
* Translates Monolog log levels to html color priorities.
*/
- protected $logLevels = array(
+ protected $logLevels = [
Logger::DEBUG => '#cccccc',
Logger::INFO => '#468847',
Logger::NOTICE => '#3a87ad',
@@ -33,12 +34,12 @@ class HtmlFormatter extends NormalizerFormatter
Logger::CRITICAL => '#FF7708',
Logger::ALERT => '#C12A19',
Logger::EMERGENCY => '#000000',
- );
+ ];
/**
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format
*/
- public function __construct($dateFormat = null)
+ public function __construct(string $dateFormat = null)
{
parent::__construct($dateFormat);
}
@@ -51,7 +52,7 @@ class HtmlFormatter extends NormalizerFormatter
* @param bool $escapeTd false if td content must not be html escaped
* @return string
*/
- protected function addRow($th, $td = ' ', $escapeTd = true)
+ protected function addRow(string $th, string $td = ' ', bool $escapeTd = true): string
{
$th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8');
if ($escapeTd) {
@@ -68,7 +69,7 @@ class HtmlFormatter extends NormalizerFormatter
* @param int $level Error level
* @return string
*/
- protected function addTitle($title, $level)
+ protected function addTitle(string $title, int $level)
{
$title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8');
@@ -81,13 +82,13 @@ class HtmlFormatter extends NormalizerFormatter
* @param array $record A record to format
* @return mixed The formatted record
*/
- public function format(array $record)
+ public function format(array $record): string
{
$output = $this->addTitle($record['level_name'], $record['level']);
$output .= '<table cellspacing="1" width="100%" class="monolog-output">';
$output .= $this->addRow('Message', (string) $record['message']);
- $output .= $this->addRow('Time', $record['datetime']->format($this->dateFormat));
+ $output .= $this->addRow('Time', $this->formatDate($record['datetime']));
$output .= $this->addRow('Channel', $record['channel']);
if ($record['context']) {
$embeddedTable = '<table cellspacing="1" width="100%">';
@@ -115,7 +116,7 @@ class HtmlFormatter extends NormalizerFormatter
* @param array $records A set of records to format
* @return mixed The formatted set of records
*/
- public function formatBatch(array $records)
+ public function formatBatch(array $records): string
{
$message = '';
foreach ($records as $record) {
@@ -125,17 +126,14 @@ class HtmlFormatter extends NormalizerFormatter
return $message;
}
- protected function convertToString($data)
+ protected function convertToString($data): string
{
if (null === $data || is_scalar($data)) {
return (string) $data;
}
$data = $this->normalize($data);
- if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
- return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
- }
- return str_replace('\\/', '/', json_encode($data));
+ return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
}
diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php
index 0782f14..8e2f2fd 100644
--- a/src/Monolog/Formatter/JsonFormatter.php
+++ b/src/Monolog/Formatter/JsonFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,7 +11,6 @@
namespace Monolog\Formatter;
-use Exception;
use Throwable;
/**
@@ -34,11 +33,7 @@ class JsonFormatter extends NormalizerFormatter
*/
protected $includeStacktraces = false;
- /**
- * @param int $batchMode
- * @param bool $appendNewline
- */
- public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true)
+ public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true)
{
$this->batchMode = $batchMode;
$this->appendNewline = $appendNewline;
@@ -50,20 +45,16 @@ class JsonFormatter extends NormalizerFormatter
* formatted as a JSON-encoded array. However, for
* compatibility with some API endpoints, alternative styles
* are available.
- *
- * @return int
*/
- public function getBatchMode()
+ public function getBatchMode(): int
{
return $this->batchMode;
}
/**
* True if newlines are appended to every formatted record
- *
- * @return bool
*/
- public function isAppendingNewlines()
+ public function isAppendingNewlines(): bool
{
return $this->appendNewline;
}
@@ -71,7 +62,7 @@ class JsonFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): string
{
return $this->toJson($this->normalize($record), true) . ($this->appendNewline ? "\n" : '');
}
@@ -79,7 +70,7 @@ class JsonFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function formatBatch(array $records)
+ public function formatBatch(array $records): string
{
switch ($this->batchMode) {
case static::BATCH_MODE_NEWLINES:
@@ -91,21 +82,15 @@ class JsonFormatter extends NormalizerFormatter
}
}
- /**
- * @param bool $include
- */
- public function includeStacktraces($include = true)
+ public function includeStacktraces(bool $include = true)
{
$this->includeStacktraces = $include;
}
/**
* Return a JSON-encoded array of records.
- *
- * @param array $records
- * @return string
*/
- protected function formatBatchJson(array $records)
+ protected function formatBatchJson(array $records): string
{
return $this->toJson($this->normalize($records), true);
}
@@ -113,11 +98,8 @@ class JsonFormatter extends NormalizerFormatter
/**
* Use new lines to separate records instead of a
* JSON-encoded array.
- *
- * @param array $records
- * @return string
*/
- protected function formatBatchNewlines(array $records)
+ protected function formatBatchNewlines(array $records): string
{
$instance = $this;
@@ -138,10 +120,14 @@ class JsonFormatter extends NormalizerFormatter
*
* @return mixed
*/
- protected function normalize($data)
+ protected function normalize($data, int $depth = 0)
{
+ if ($depth > 9) {
+ return 'Over 9 levels deep, aborting normalization';
+ }
+
if (is_array($data) || $data instanceof \Traversable) {
- $normalized = array();
+ $normalized = [];
$count = 1;
foreach ($data as $key => $value) {
@@ -149,14 +135,14 @@ class JsonFormatter extends NormalizerFormatter
$normalized['...'] = 'Over 1000 items, aborting normalization';
break;
}
- $normalized[$key] = $this->normalize($value);
+ $normalized[$key] = $this->normalize($value, $depth + 1);
}
return $normalized;
}
- if ($data instanceof Exception || $data instanceof Throwable) {
- return $this->normalizeException($data);
+ if ($data instanceof Throwable) {
+ return $this->normalizeException($data, $depth);
}
return $data;
@@ -165,24 +151,15 @@ class JsonFormatter extends NormalizerFormatter
/**
* Normalizes given exception with or without its own stack trace based on
* `includeStacktraces` property.
- *
- * @param Exception|Throwable $e
- *
- * @return array
*/
- protected function normalizeException($e)
+ protected function normalizeException(Throwable $e, int $depth = 0): array
{
- // TODO 2.0 only check for Throwable
- if (!$e instanceof Exception && !$e instanceof Throwable) {
- throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
- }
-
- $data = array(
+ $data = [
'class' => get_class($e),
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile().':'.$e->getLine(),
- );
+ ];
if ($this->includeStacktraces) {
$trace = $e->getTrace();
@@ -200,7 +177,7 @@ class JsonFormatter extends NormalizerFormatter
}
if ($previous = $e->getPrevious()) {
- $data['previous'] = $this->normalizeException($previous);
+ $data['previous'] = $this->normalizeException($previous, $depth + 1);
}
return $data;
diff --git a/src/Monolog/Formatter/LineFormatter.php b/src/Monolog/Formatter/LineFormatter.php
index d3e209e..9d4ef1d 100644
--- a/src/Monolog/Formatter/LineFormatter.php
+++ b/src/Monolog/Formatter/LineFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -34,7 +34,7 @@ class LineFormatter extends NormalizerFormatter
* @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
* @param bool $ignoreEmptyContextAndExtra
*/
- public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = false, $ignoreEmptyContextAndExtra = false)
+ public function __construct(string $format = null, string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false)
{
$this->format = $format ?: static::SIMPLE_FORMAT;
$this->allowInlineLineBreaks = $allowInlineLineBreaks;
@@ -42,7 +42,7 @@ class LineFormatter extends NormalizerFormatter
parent::__construct($dateFormat);
}
- public function includeStacktraces($include = true)
+ public function includeStacktraces(bool $include = true)
{
$this->includeStacktraces = $include;
if ($this->includeStacktraces) {
@@ -50,12 +50,12 @@ class LineFormatter extends NormalizerFormatter
}
}
- public function allowInlineLineBreaks($allow = true)
+ public function allowInlineLineBreaks(bool $allow = true)
{
$this->allowInlineLineBreaks = $allow;
}
- public function ignoreEmptyContextAndExtra($ignore = true)
+ public function ignoreEmptyContextAndExtra(bool $ignore = true)
{
$this->ignoreEmptyContextAndExtra = $ignore;
}
@@ -63,7 +63,7 @@ class LineFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): string
{
$vars = parent::format($record);
@@ -76,7 +76,6 @@ class LineFormatter extends NormalizerFormatter
}
}
-
foreach ($vars['context'] as $var => $val) {
if (false !== strpos($output, '%context.'.$var.'%')) {
$output = str_replace('%context.'.$var.'%', $this->stringify($val), $output);
@@ -110,7 +109,7 @@ class LineFormatter extends NormalizerFormatter
return $output;
}
- public function formatBatch(array $records)
+ public function formatBatch(array $records): string
{
$message = '';
foreach ($records as $record) {
@@ -120,18 +119,13 @@ class LineFormatter extends NormalizerFormatter
return $message;
}
- public function stringify($value)
+ public function stringify($value): string
{
return $this->replaceNewlines($this->convertToString($value));
}
- protected function normalizeException($e)
+ protected function normalizeException(\Throwable $e, int $depth = 0): string
{
- // TODO 2.0 only check for Throwable
- if (!$e instanceof \Exception && !$e instanceof \Throwable) {
- throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
- }
-
$previousText = '';
if ($previous = $e->getPrevious()) {
do {
@@ -147,7 +141,7 @@ class LineFormatter extends NormalizerFormatter
return $str;
}
- protected function convertToString($data)
+ protected function convertToString($data): string
{
if (null === $data || is_bool($data)) {
return var_export($data, true);
@@ -157,14 +151,10 @@ class LineFormatter extends NormalizerFormatter
return (string) $data;
}
- if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
- return $this->toJson($data, true);
- }
-
- return str_replace('\\/', '/', @json_encode($data));
+ return (string) $this->toJson($data, true);
}
- protected function replaceNewlines($str)
+ protected function replaceNewlines(string $str): string
{
if ($this->allowInlineLineBreaks) {
if (0 === strpos($str, '{')) {
@@ -174,6 +164,6 @@ class LineFormatter extends NormalizerFormatter
return $str;
}
- return str_replace(array("\r\n", "\r", "\n"), ' ', $str);
+ return str_replace(["\r\n", "\r", "\n"], ' ', $str);
}
}
diff --git a/src/Monolog/Formatter/LogglyFormatter.php b/src/Monolog/Formatter/LogglyFormatter.php
index 401859b..29841aa 100644
--- a/src/Monolog/Formatter/LogglyFormatter.php
+++ b/src/Monolog/Formatter/LogglyFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -21,10 +21,8 @@ class LogglyFormatter extends JsonFormatter
/**
* Overrides the default batch mode to new lines for compatibility with the
* Loggly bulk API.
- *
- * @param int $batchMode
*/
- public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = false)
+ public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = false)
{
parent::__construct($batchMode, $appendNewline);
}
@@ -35,11 +33,11 @@ class LogglyFormatter extends JsonFormatter
* @see https://www.loggly.com/docs/automated-parsing/#json
* @see \Monolog\Formatter\JsonFormatter::format()
*/
- public function format(array $record)
+ public function format(array $record): string
{
- if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTime)) {
+ if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) {
$record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO");
- // TODO 2.0 unset the 'datetime' parameter, retained for BC
+ unset($record["datetime"]);
}
return parent::format($record);
diff --git a/src/Monolog/Formatter/LogmaticFormatter.php b/src/Monolog/Formatter/LogmaticFormatter.php
new file mode 100644
index 0000000..7a75e00
--- /dev/null
+++ b/src/Monolog/Formatter/LogmaticFormatter.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Formatter;
+
+/**
+ * Encodes message information into JSON in a format compatible with Logmatic.
+ *
+ * @author Julien Breux <julien.breux@gmail.com>
+ */
+class LogmaticFormatter extends JsonFormatter
+{
+ const MARKERS = ["sourcecode", "php"];
+
+ /**
+ * @param string
+ */
+ protected $hostname = '';
+
+ /**
+ * @param string
+ */
+ protected $appname = '';
+
+ /**
+ * Set hostname
+ *
+ * @param string $hostname
+ */
+ public function setHostname(string $hostname)
+ {
+ $this->hostname = $hostname;
+ }
+
+ /**
+ * Set appname
+ *
+ * @param string $appname
+ */
+ public function setAppname(string $appname)
+ {
+ $this->appname = $appname;
+ }
+
+ /**
+ * Appends the 'hostname' and 'appname' parameter for indexing by Logmatic.
+ *
+ * @see http://doc.logmatic.io/docs/basics-to-send-data
+ * @see \Monolog\Formatter\JsonFormatter::format()
+ */
+ public function format(array $record): string
+ {
+ if (!empty($this->hostname)) {
+ $record["hostname"] = $this->hostname;
+ }
+ if (!empty($this->appname)) {
+ $record["appname"] = $this->appname;
+ }
+
+ $record["@marker"] = self::MARKERS;
+
+ return parent::format($record);
+ }
+}
diff --git a/src/Monolog/Formatter/LogstashFormatter.php b/src/Monolog/Formatter/LogstashFormatter.php
index 8f83bec..3cf31dd 100644
--- a/src/Monolog/Formatter/LogstashFormatter.php
+++ b/src/Monolog/Formatter/LogstashFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -15,15 +15,12 @@ namespace Monolog\Formatter;
* Serializes a log message to Logstash Event Format
*
* @see http://logstash.net/
- * @see https://github.com/logstash/logstash/blob/master/lib/logstash/event.rb
+ * @see https://github.com/elastic/logstash/blob/master/logstash-core-event/lib/logstash/event.rb
*
* @author Tim Mower <timothy.mower@gmail.com>
*/
class LogstashFormatter extends NormalizerFormatter
{
- const V0 = 0;
- const V1 = 1;
-
/**
* @var string the name of the system for the Logstash log message, used to fill the @source field
*/
@@ -45,18 +42,12 @@ class LogstashFormatter extends NormalizerFormatter
protected $contextPrefix;
/**
- * @var int logstash format version to use
- */
- protected $version;
-
- /**
* @param string $applicationName the application that sends the data, used as the "type" field of logstash
* @param string $systemName the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
* @param string $extraPrefix prefix for extra keys inside logstash "fields"
* @param string $contextPrefix prefix for context keys inside logstash "fields", defaults to ctxt_
- * @param int $version the logstash format version to use, defaults to 0
*/
- public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0)
+ public function __construct(string $applicationName, string $systemName = null, string $extraPrefix = null, string $contextPrefix = 'ctxt_')
{
// logstash requires a ISO 8601 format date with optional millisecond precision.
parent::__construct('Y-m-d\TH:i:s.uP');
@@ -65,78 +56,23 @@ class LogstashFormatter extends NormalizerFormatter
$this->applicationName = $applicationName;
$this->extraPrefix = $extraPrefix;
$this->contextPrefix = $contextPrefix;
- $this->version = $version;
}
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): string
{
$record = parent::format($record);
- if ($this->version === self::V1) {
- $message = $this->formatV1($record);
- } else {
- $message = $this->formatV0($record);
- }
-
- return $this->toJson($message) . "\n";
- }
-
- protected function formatV0(array $record)
- {
if (empty($record['datetime'])) {
$record['datetime'] = gmdate('c');
}
- $message = array(
- '@timestamp' => $record['datetime'],
- '@source' => $this->systemName,
- '@fields' => array(),
- );
- if (isset($record['message'])) {
- $message['@message'] = $record['message'];
- }
- if (isset($record['channel'])) {
- $message['@tags'] = array($record['channel']);
- $message['@fields']['channel'] = $record['channel'];
- }
- if (isset($record['level'])) {
- $message['@fields']['level'] = $record['level'];
- }
- if ($this->applicationName) {
- $message['@type'] = $this->applicationName;
- }
- if (isset($record['extra']['server'])) {
- $message['@source_host'] = $record['extra']['server'];
- }
- if (isset($record['extra']['url'])) {
- $message['@source_path'] = $record['extra']['url'];
- }
- if (!empty($record['extra'])) {
- foreach ($record['extra'] as $key => $val) {
- $message['@fields'][$this->extraPrefix . $key] = $val;
- }
- }
- if (!empty($record['context'])) {
- foreach ($record['context'] as $key => $val) {
- $message['@fields'][$this->contextPrefix . $key] = $val;
- }
- }
-
- return $message;
- }
-
- protected function formatV1(array $record)
- {
- if (empty($record['datetime'])) {
- $record['datetime'] = gmdate('c');
- }
- $message = array(
+ $message = [
'@timestamp' => $record['datetime'],
'@version' => 1,
'host' => $this->systemName,
- );
+ ];
if (isset($record['message'])) {
$message['message'] = $record['message'];
}
@@ -147,20 +83,19 @@ class LogstashFormatter extends NormalizerFormatter
if (isset($record['level_name'])) {
$message['level'] = $record['level_name'];
}
+ if (isset($record['level'])) {
+ $message['monolog_level'] = $record['level'];
+ }
if ($this->applicationName) {
$message['type'] = $this->applicationName;
}
if (!empty($record['extra'])) {
- foreach ($record['extra'] as $key => $val) {
- $message[$this->extraPrefix . $key] = $val;
- }
+ $message[$this->extraPrefix.'extra'] = $record['extra'];
}
if (!empty($record['context'])) {
- foreach ($record['context'] as $key => $val) {
- $message[$this->contextPrefix . $key] = $val;
- }
+ $message[$this->contextPrefix.'context'] = $record['context'];
}
- return $message;
+ return $this->toJson($message) . "\n";
}
}
diff --git a/src/Monolog/Formatter/MongoDBFormatter.php b/src/Monolog/Formatter/MongoDBFormatter.php
index eb067bb..8c40e3e 100644
--- a/src/Monolog/Formatter/MongoDBFormatter.php
+++ b/src/Monolog/Formatter/MongoDBFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,6 +11,8 @@
namespace Monolog\Formatter;
+use MongoDB\BSON\UTCDateTime;
+
/**
* Formats a record for use with the MongoDBHandler.
*
@@ -20,21 +22,24 @@ class MongoDBFormatter implements FormatterInterface
{
private $exceptionTraceAsString;
private $maxNestingLevel;
+ private $isLegacyMongoExt;
/**
* @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
* @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
*/
- public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = true)
+ public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true)
{
$this->maxNestingLevel = max($maxNestingLevel, 0);
- $this->exceptionTraceAsString = (bool) $exceptionTraceAsString;
+ $this->exceptionTraceAsString = $exceptionTraceAsString;
+
+ $this->isLegacyMongoExt = version_compare(phpversion('mongodb'), '1.1.9', '<=');
}
/**
* {@inheritDoc}
*/
- public function format(array $record)
+ public function format(array $record): array
{
return $this->formatArray($record);
}
@@ -42,7 +47,7 @@ class MongoDBFormatter implements FormatterInterface
/**
* {@inheritDoc}
*/
- public function formatBatch(array $records)
+ public function formatBatch(array $records): array
{
foreach ($records as $key => $record) {
$records[$key] = $this->format($record);
@@ -51,13 +56,16 @@ class MongoDBFormatter implements FormatterInterface
return $records;
}
- protected function formatArray(array $record, $nestingLevel = 0)
+ /**
+ * @return array|string Array except when max nesting level is reached then a string "[...]"
+ */
+ protected function formatArray(array $record, int $nestingLevel = 0)
{
if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) {
foreach ($record as $name => $value) {
- if ($value instanceof \DateTime) {
+ if ($value instanceof \DateTimeInterface) {
$record[$name] = $this->formatDate($value, $nestingLevel + 1);
- } elseif ($value instanceof \Exception) {
+ } elseif ($value instanceof \Throwable) {
$record[$name] = $this->formatException($value, $nestingLevel + 1);
} elseif (is_array($value)) {
$record[$name] = $this->formatArray($value, $nestingLevel + 1);
@@ -72,7 +80,7 @@ class MongoDBFormatter implements FormatterInterface
return $record;
}
- protected function formatObject($value, $nestingLevel)
+ protected function formatObject($value, int $nestingLevel)
{
$objectVars = get_object_vars($value);
$objectVars['class'] = get_class($value);
@@ -80,14 +88,14 @@ class MongoDBFormatter implements FormatterInterface
return $this->formatArray($objectVars, $nestingLevel);
}
- protected function formatException(\Exception $exception, $nestingLevel)
+ protected function formatException(\Throwable $exception, int $nestingLevel)
{
- $formattedException = array(
+ $formattedException = [
'class' => get_class($exception),
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
'file' => $exception->getFile() . ':' . $exception->getLine(),
- );
+ ];
if ($this->exceptionTraceAsString === true) {
$formattedException['trace'] = $exception->getTraceAsString();
@@ -98,8 +106,35 @@ class MongoDBFormatter implements FormatterInterface
return $this->formatArray($formattedException, $nestingLevel);
}
- protected function formatDate(\DateTime $value, $nestingLevel)
+ protected function formatDate(\DateTimeInterface $value, int $nestingLevel): UTCDateTime
+ {
+ if ($this->isLegacyMongoExt) {
+ return $this->legacyGetMongoDbDateTime($value);
+ }
+
+ return $this->getMongoDbDateTime($value);
+ }
+
+ private function getMongoDbDateTime(\DateTimeInterface $value): UTCDateTime
+ {
+ return new UTCDateTime((int) (string) floor($value->format('U.u') * 1000));
+ }
+
+ /**
+ * This is needed to support MongoDB Driver v1.19 and below
+ *
+ * See https://github.com/mongodb/mongo-php-driver/issues/426
+ *
+ * It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted
+ */
+ private function legacyGetMongoDbDateTime(\DateTimeInterface $value): UTCDateTime
{
- return new \MongoDate($value->getTimestamp());
+ $milliseconds = floor($value->format('U.u') * 1000);
+
+ $milliseconds = (PHP_INT_SIZE == 8) //64-bit OS?
+ ? (int) $milliseconds
+ : (string) $milliseconds;
+
+ return new UTCDateTime($milliseconds);
}
}
diff --git a/src/Monolog/Formatter/NormalizerFormatter.php b/src/Monolog/Formatter/NormalizerFormatter.php
index d441488..84f644c 100644
--- a/src/Monolog/Formatter/NormalizerFormatter.php
+++ b/src/Monolog/Formatter/NormalizerFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,7 +11,8 @@
namespace Monolog\Formatter;
-use Exception;
+use Throwable;
+use Monolog\DateTimeImmutable;
/**
* Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
@@ -20,16 +21,16 @@ use Exception;
*/
class NormalizerFormatter implements FormatterInterface
{
- const SIMPLE_DATE = "Y-m-d H:i:s";
+ const SIMPLE_DATE = "Y-m-d\TH:i:sP";
protected $dateFormat;
/**
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format
*/
- public function __construct($dateFormat = null)
+ public function __construct(string $dateFormat = null)
{
- $this->dateFormat = $dateFormat ?: static::SIMPLE_DATE;
+ $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
if (!function_exists('json_encode')) {
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter');
}
@@ -55,8 +56,16 @@ class NormalizerFormatter implements FormatterInterface
return $records;
}
- protected function normalize($data)
+ /**
+ * @param mixed $data
+ * @return int|bool|string|null|array
+ */
+ protected function normalize($data, int $depth = 0)
{
+ if ($depth > 9) {
+ return 'Over 9 levels deep, aborting normalization';
+ }
+
if (null === $data || is_scalar($data)) {
if (is_float($data)) {
if (is_infinite($data)) {
@@ -71,7 +80,7 @@ class NormalizerFormatter implements FormatterInterface
}
if (is_array($data)) {
- $normalized = array();
+ $normalized = [];
$count = 1;
foreach ($data as $key => $value) {
@@ -79,53 +88,56 @@ class NormalizerFormatter implements FormatterInterface
$normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
break;
}
- $normalized[$key] = $this->normalize($value);
+ $normalized[$key] = $this->normalize($value, $depth + 1);
}
return $normalized;
}
- if ($data instanceof \DateTime) {
- return $data->format($this->dateFormat);
+ if ($data instanceof \DateTimeInterface) {
+ return $this->formatDate($data);
}
if (is_object($data)) {
- // TODO 2.0 only check for Throwable
- if ($data instanceof Exception || (PHP_VERSION_ID > 70000 && $data instanceof \Throwable)) {
- return $this->normalizeException($data);
+ if ($data instanceof Throwable) {
+ return $this->normalizeException($data, $depth);
}
- // non-serializable objects that implement __toString stringified
- if (method_exists($data, '__toString') && !$data instanceof \JsonSerializable) {
+ if ($data instanceof \JsonSerializable) {
+ $value = $data->jsonSerialize();
+ } elseif (method_exists($data, '__toString')) {
$value = $data->__toString();
} else {
- // the rest is json-serialized in some way
- $value = $this->toJson($data, true);
+ // the rest is normalized by json encoding and decoding it
+ $encoded = $this->toJson($data, true);
+ if ($encoded === false) {
+ $value = 'JSON_ERROR';
+ } else {
+ $value = json_decode($encoded, true);
+ }
}
- return sprintf("[object] (%s: %s)", get_class($data), $value);
+ return [get_class($data) => $value];
}
if (is_resource($data)) {
- return sprintf('[resource] (%s)', get_resource_type($data));
+ return sprintf('[resource(%s)]', get_resource_type($data));
}
return '[unknown('.gettype($data).')]';
}
- protected function normalizeException($e)
+ /**
+ * @return array
+ */
+ protected function normalizeException(Throwable $e, int $depth = 0)
{
- // TODO 2.0 only check for Throwable
- if (!$e instanceof Exception && !$e instanceof \Throwable) {
- throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
- }
-
- $data = array(
+ $data = [
'class' => get_class($e),
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile().':'.$e->getLine(),
- );
+ ];
if ($e instanceof \SoapFault) {
if (isset($e->faultcode)) {
@@ -150,12 +162,12 @@ class NormalizerFormatter implements FormatterInterface
$data['trace'][] = $frame['function'];
} else {
// We should again normalize the frames, because it might contain invalid items
- $data['trace'][] = $this->toJson($this->normalize($frame), true);
+ $data['trace'][] = $this->toJson($this->normalize($frame, $depth + 1), true);
}
}
if ($previous = $e->getPrevious()) {
- $data['previous'] = $this->normalizeException($previous);
+ $data['previous'] = $this->normalizeException($previous, $depth + 1);
}
return $data;
@@ -165,11 +177,10 @@ class NormalizerFormatter implements FormatterInterface
* Return the JSON representation of a value
*
* @param mixed $data
- * @param bool $ignoreErrors
* @throws \RuntimeException if encoding fails and errors are not ignored
- * @return string
+ * @return string|bool
*/
- protected function toJson($data, $ignoreErrors = false)
+ protected function toJson($data, bool $ignoreErrors = false)
{
// suppress json_encode errors since it's twitchy with some inputs
if ($ignoreErrors) {
@@ -186,16 +197,12 @@ class NormalizerFormatter implements FormatterInterface
}
/**
- * @param mixed $data
- * @return string JSON encoded data or null on failure
+ * @param mixed $data
+ * @return string|bool JSON encoded data or false on failure
*/
private function jsonEncode($data)
{
- if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
- return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
- }
-
- return json_encode($data);
+ return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION);
}
/**
@@ -203,7 +210,7 @@ class NormalizerFormatter implements FormatterInterface
*
* If the failure is due to invalid string encoding, try to clean the
* input and encode again. If the second encoding attempt fails, the
- * inital error is not encoding related or the input can't be cleaned then
+ * initial error is not encoding related or the input can't be cleaned then
* raise a descriptive exception.
*
* @param int $code return code of json_last_error function
@@ -211,7 +218,7 @@ class NormalizerFormatter implements FormatterInterface
* @throws \RuntimeException if failure can't be corrected
* @return string JSON encoded data after error correction
*/
- private function handleJsonError($code, $data)
+ private function handleJsonError(int $code, $data): string
{
if ($code !== JSON_ERROR_UTF8) {
$this->throwEncodeError($code, $data);
@@ -220,7 +227,7 @@ class NormalizerFormatter implements FormatterInterface
if (is_string($data)) {
$this->detectAndCleanUtf8($data);
} elseif (is_array($data)) {
- array_walk_recursive($data, array($this, 'detectAndCleanUtf8'));
+ array_walk_recursive($data, [$this, 'detectAndCleanUtf8']);
} else {
$this->throwEncodeError($code, $data);
}
@@ -241,7 +248,7 @@ class NormalizerFormatter implements FormatterInterface
* @param mixed $data data that was meant to be encoded
* @throws \RuntimeException
*/
- private function throwEncodeError($code, $data)
+ private function throwEncodeError(int $code, $data)
{
switch ($code) {
case JSON_ERROR_DEPTH:
@@ -284,14 +291,27 @@ class NormalizerFormatter implements FormatterInterface
if (is_string($data) && !preg_match('//u', $data)) {
$data = preg_replace_callback(
'/[\x80-\xFF]+/',
- function ($m) { return utf8_encode($m[0]); },
+ function ($m) {
+ return utf8_encode($m[0]);
+ },
$data
);
$data = str_replace(
- array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
- array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
+ ['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'],
+ ['€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'],
$data
);
}
}
+
+ protected function formatDate(\DateTimeInterface $date)
+ {
+ // in case the date format isn't custom then we defer to the custom DateTimeImmutable
+ // formatting logic, which will pick the right format based on whether useMicroseconds is on
+ if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) {
+ return (string) $date;
+ }
+
+ return $date->format($this->dateFormat);
+ }
}
diff --git a/src/Monolog/Formatter/ScalarFormatter.php b/src/Monolog/Formatter/ScalarFormatter.php
index 5d345d5..8d560e7 100644
--- a/src/Monolog/Formatter/ScalarFormatter.php
+++ b/src/Monolog/Formatter/ScalarFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -22,7 +22,7 @@ class ScalarFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): array
{
foreach ($record as $key => $value) {
$record[$key] = $this->normalizeValue($value);
diff --git a/src/Monolog/Formatter/WildfireFormatter.php b/src/Monolog/Formatter/WildfireFormatter.php
index 654710a..c8a3bb4 100644
--- a/src/Monolog/Formatter/WildfireFormatter.php
+++ b/src/Monolog/Formatter/WildfireFormatter.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -27,7 +27,7 @@ class WildfireFormatter extends NormalizerFormatter
/**
* Translates Monolog log levels to Wildfire levels.
*/
- private $logLevels = array(
+ private $logLevels = [
Logger::DEBUG => 'LOG',
Logger::INFO => 'INFO',
Logger::NOTICE => 'INFO',
@@ -36,12 +36,12 @@ class WildfireFormatter extends NormalizerFormatter
Logger::CRITICAL => 'ERROR',
Logger::ALERT => 'ERROR',
Logger::EMERGENCY => 'ERROR',
- );
+ ];
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): string
{
// Retrieve the line and file if set and remove them from the formatted extra
$file = $line = '';
@@ -55,7 +55,7 @@ class WildfireFormatter extends NormalizerFormatter
}
$record = $this->normalize($record);
- $message = array('message' => $record['message']);
+ $message = ['message' => $record['message']];
$handleError = false;
if ($record['context']) {
$message['context'] = $record['context'];
@@ -79,15 +79,15 @@ class WildfireFormatter extends NormalizerFormatter
}
// Create JSON object describing the appearance of the message in the console
- $json = $this->toJson(array(
- array(
+ $json = $this->toJson([
+ [
'Type' => $type,
'File' => $file,
'Line' => $line,
'Label' => $label,
- ),
+ ],
$message,
- ), $handleError);
+ ], $handleError);
// The message itself is a serialization of the above JSON object + it's length
return sprintf(
@@ -97,17 +97,23 @@ class WildfireFormatter extends NormalizerFormatter
);
}
+ /**
+ * {@inheritdoc}
+ */
public function formatBatch(array $records)
{
throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
}
- protected function normalize($data)
+ /**
+ * {@inheritdoc}
+ */
+ protected function normalize($data, int $depth = 0)
{
- if (is_object($data) && !$data instanceof \DateTime) {
+ if (is_object($data) && !$data instanceof \DateTimeInterface) {
return $data;
}
- return parent::normalize($data);
+ return parent::normalize($data, $depth);
}
}
diff --git a/src/Monolog/Handler/AbstractHandler.php b/src/Monolog/Handler/AbstractHandler.php
index 758a425..ea79ec9 100644
--- a/src/Monolog/Handler/AbstractHandler.php
+++ b/src/Monolog/Handler/AbstractHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,26 +12,18 @@
namespace Monolog\Handler;
use Monolog\Logger;
-use Monolog\Formatter\FormatterInterface;
-use Monolog\Formatter\LineFormatter;
/**
- * Base Handler class providing the Handler structure
+ * Base Handler class providing basic level/bubble support
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
-abstract class AbstractHandler implements HandlerInterface
+abstract class AbstractHandler extends Handler
{
protected $level = Logger::DEBUG;
protected $bubble = true;
/**
- * @var FormatterInterface
- */
- protected $formatter;
- protected $processors = array();
-
- /**
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
@@ -44,84 +36,18 @@ abstract class AbstractHandler implements HandlerInterface
/**
* {@inheritdoc}
*/
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
return $record['level'] >= $this->level;
}
/**
- * {@inheritdoc}
- */
- public function handleBatch(array $records)
- {
- foreach ($records as $record) {
- $this->handle($record);
- }
- }
-
- /**
- * Closes the handler.
- *
- * This will be called automatically when the object is destroyed
- */
- public function close()
- {
- }
-
- /**
- * {@inheritdoc}
- */
- public function pushProcessor($callback)
- {
- if (!is_callable($callback)) {
- throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
- }
- array_unshift($this->processors, $callback);
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function popProcessor()
- {
- if (!$this->processors) {
- throw new \LogicException('You tried to pop from an empty processor stack.');
- }
-
- return array_shift($this->processors);
- }
-
- /**
- * {@inheritdoc}
- */
- public function setFormatter(FormatterInterface $formatter)
- {
- $this->formatter = $formatter;
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFormatter()
- {
- if (!$this->formatter) {
- $this->formatter = $this->getDefaultFormatter();
- }
-
- return $this->formatter;
- }
-
- /**
* Sets minimum logging level at which this handler will be triggered.
*
* @param int|string $level Level or level name
* @return self
*/
- public function setLevel($level)
+ public function setLevel($level): self
{
$this->level = Logger::toMonologLevel($level);
@@ -133,7 +59,7 @@ abstract class AbstractHandler implements HandlerInterface
*
* @return int
*/
- public function getLevel()
+ public function getLevel(): int
{
return $this->level;
}
@@ -145,7 +71,7 @@ abstract class AbstractHandler implements HandlerInterface
* false means that bubbling is not permitted.
* @return self
*/
- public function setBubble($bubble)
+ public function setBubble(bool $bubble): self
{
$this->bubble = $bubble;
@@ -158,29 +84,8 @@ abstract class AbstractHandler implements HandlerInterface
* @return Boolean true means that this handler allows bubbling.
* false means that bubbling is not permitted.
*/
- public function getBubble()
+ public function getBubble(): bool
{
return $this->bubble;
}
-
- public function __destruct()
- {
- try {
- $this->close();
- } catch (\Exception $e) {
- // do nothing
- } catch (\Throwable $e) {
- // do nothing
- }
- }
-
- /**
- * Gets the default formatter.
- *
- * @return FormatterInterface
- */
- protected function getDefaultFormatter()
- {
- return new LineFormatter();
- }
}
diff --git a/src/Monolog/Handler/AbstractProcessingHandler.php b/src/Monolog/Handler/AbstractProcessingHandler.php
index 6f18f72..654e671 100644
--- a/src/Monolog/Handler/AbstractProcessingHandler.php
+++ b/src/Monolog/Handler/AbstractProcessingHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -19,18 +19,23 @@ namespace Monolog\Handler;
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Christophe Coevoet <stof@notk.org>
*/
-abstract class AbstractProcessingHandler extends AbstractHandler
+abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
+ use ProcessableHandlerTrait;
+ use FormattableHandlerTrait;
+
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
}
- $record = $this->processRecord($record);
+ if ($this->processors) {
+ $record = $this->processRecord($record);
+ }
$record['formatted'] = $this->getFormatter()->format($record);
@@ -46,21 +51,4 @@ abstract class AbstractProcessingHandler extends AbstractHandler
* @return void
*/
abstract protected function write(array $record);
-
- /**
- * Processes a record.
- *
- * @param array $record
- * @return array
- */
- protected function processRecord(array $record)
- {
- if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
- }
-
- return $record;
- }
}
diff --git a/src/Monolog/Handler/AbstractSyslogHandler.php b/src/Monolog/Handler/AbstractSyslogHandler.php
index e2b2832..d6fc41e 100644
--- a/src/Monolog/Handler/AbstractSyslogHandler.php
+++ b/src/Monolog/Handler/AbstractSyslogHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Logger;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
@@ -24,7 +25,7 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
/**
* Translates Monolog log levels to syslog log priorities.
*/
- protected $logLevels = array(
+ protected $logLevels = [
Logger::DEBUG => LOG_DEBUG,
Logger::INFO => LOG_INFO,
Logger::NOTICE => LOG_NOTICE,
@@ -33,12 +34,12 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
Logger::CRITICAL => LOG_CRIT,
Logger::ALERT => LOG_ALERT,
Logger::EMERGENCY => LOG_EMERG,
- );
+ ];
/**
* List of valid log facility names.
*/
- protected $facilities = array(
+ protected $facilities = [
'auth' => LOG_AUTH,
'authpriv' => LOG_AUTHPRIV,
'cron' => LOG_CRON,
@@ -50,7 +51,7 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
'syslog' => LOG_SYSLOG,
'user' => LOG_USER,
'uucp' => LOG_UUCP,
- );
+ ];
/**
* @param mixed $facility
@@ -82,7 +83,7 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
}
// convert textual description of facility to syslog constant
- if (array_key_exists(strtolower($facility), $this->facilities)) {
+ if (is_string($facility) && array_key_exists(strtolower($facility), $this->facilities)) {
$facility = $this->facilities[strtolower($facility)];
} elseif (!in_array($facility, array_values($this->facilities), true)) {
throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given');
@@ -94,7 +95,7 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
/**
* {@inheritdoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
}
diff --git a/src/Monolog/Handler/AmqpHandler.php b/src/Monolog/Handler/AmqpHandler.php
index e5a46bc..6e39a11 100644
--- a/src/Monolog/Handler/AmqpHandler.php
+++ b/src/Monolog/Handler/AmqpHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Logger;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Channel\AMQPChannel;
@@ -31,18 +32,18 @@ class AmqpHandler extends AbstractProcessingHandler
/**
* @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
- * @param string $exchangeName
+ * @param string $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
* @param int $level
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
- public function __construct($exchange, $exchangeName = 'log', $level = Logger::DEBUG, $bubble = true)
+ public function __construct($exchange, $exchangeName = null, $level = Logger::DEBUG, $bubble = true)
{
- if ($exchange instanceof AMQPExchange) {
- $exchange->setName($exchangeName);
- } elseif ($exchange instanceof AMQPChannel) {
+ if ($exchange instanceof AMQPChannel) {
$this->exchangeName = $exchangeName;
- } else {
+ } elseif (!$exchange instanceof AMQPExchange) {
throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required');
+ } elseif ($exchangeName) {
+ @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
}
$this->exchange = $exchange;
@@ -62,10 +63,10 @@ class AmqpHandler extends AbstractProcessingHandler
$data,
$routingKey,
0,
- array(
+ [
'delivery_mode' => 2,
'content_type' => 'application/json',
- )
+ ]
);
} else {
$this->exchange->basic_publish(
@@ -113,12 +114,7 @@ class AmqpHandler extends AbstractProcessingHandler
*/
protected function getRoutingKey(array $record)
{
- $routingKey = sprintf(
- '%s.%s',
- // TODO 2.0 remove substr call
- substr($record['level_name'], 0, 4),
- $record['channel']
- );
+ $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);
return strtolower($routingKey);
}
@@ -131,17 +127,17 @@ class AmqpHandler extends AbstractProcessingHandler
{
return new AMQPMessage(
(string) $data,
- array(
+ [
'delivery_mode' => 2,
'content_type' => 'application/json',
- )
+ ]
);
}
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
}
diff --git a/src/Monolog/Handler/BrowserConsoleHandler.php b/src/Monolog/Handler/BrowserConsoleHandler.php
index b3a21bd..4879d24 100644
--- a/src/Monolog/Handler/BrowserConsoleHandler.php
+++ b/src/Monolog/Handler/BrowserConsoleHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter;
+use Monolog\Formatter\FormatterInterface;
/**
* Handler sending logs to browser's javascript console with no browser extension required
@@ -21,7 +22,7 @@ use Monolog\Formatter\LineFormatter;
class BrowserConsoleHandler extends AbstractProcessingHandler
{
protected static $initialized = false;
- protected static $records = array();
+ protected static $records = [];
/**
* {@inheritDoc}
@@ -32,7 +33,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
*
* You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
}
@@ -78,7 +79,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
*/
public static function reset()
{
- self::$records = array();
+ self::$records = [];
}
/**
@@ -87,7 +88,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
protected function registerShutdownFunction()
{
if (PHP_SAPI !== 'cli') {
- register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send'));
+ register_shutdown_function(['Monolog\Handler\BrowserConsoleHandler', 'send']);
}
}
@@ -132,7 +133,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function generateScript()
{
- $script = array();
+ $script = [];
foreach (self::$records as $record) {
$context = self::dump('Context', $record['context']);
$extra = self::dump('Extra', $record['extra']);
@@ -141,10 +142,10 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
$script[] = self::call_array('log', self::handleStyles($record['formatted']));
} else {
$script = array_merge($script,
- array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))),
+ [self::call_array('groupCollapsed', self::handleStyles($record['formatted']))],
$context,
$extra,
- array(self::call('groupEnd'))
+ [self::call('groupEnd')]
);
}
}
@@ -154,7 +155,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function handleStyles($formatted)
{
- $args = array(self::quote('font-weight: normal'));
+ $args = [self::quote('font-weight: normal')];
$format = '%c' . $formatted;
preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
@@ -173,8 +174,8 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function handleCustomStyles($style, $string)
{
- static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey');
- static $labels = array();
+ static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
+ static $labels = [];
return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) {
if (trim($m[1]) === 'autolabel') {
@@ -193,7 +194,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function dump($title, array $dict)
{
- $script = array();
+ $script = [];
$dict = array_filter($dict);
if (empty($dict)) {
return $script;
diff --git a/src/Monolog/Handler/BufferHandler.php b/src/Monolog/Handler/BufferHandler.php
index 72f8953..5ce6c39 100644
--- a/src/Monolog/Handler/BufferHandler.php
+++ b/src/Monolog/Handler/BufferHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -21,13 +21,15 @@ use Monolog\Logger;
*
* @author Christophe Coevoet <stof@notk.org>
*/
-class BufferHandler extends AbstractHandler
+class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface
{
+ use ProcessableHandlerTrait;
+
protected $handler;
protected $bufferSize = 0;
protected $bufferLimit;
protected $flushOnOverflow;
- protected $buffer = array();
+ protected $buffer = [];
protected $initialized = false;
/**
@@ -48,7 +50,7 @@ class BufferHandler extends AbstractHandler
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($record['level'] < $this->level) {
return false;
@@ -56,7 +58,7 @@ class BufferHandler extends AbstractHandler
if (!$this->initialized) {
// __destructor() doesn't get called on Fatal errors
- register_shutdown_function(array($this, 'close'));
+ register_shutdown_function([$this, 'close']);
$this->initialized = true;
}
@@ -70,9 +72,7 @@ class BufferHandler extends AbstractHandler
}
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ $record = $this->processRecord($record);
}
$this->buffer[] = $record;
@@ -112,6 +112,6 @@ class BufferHandler extends AbstractHandler
public function clear()
{
$this->bufferSize = 0;
- $this->buffer = array();
+ $this->buffer = [];
}
}
diff --git a/src/Monolog/Handler/ChromePHPHandler.php b/src/Monolog/Handler/ChromePHPHandler.php
index 785cb0c..4c6be69 100644
--- a/src/Monolog/Handler/ChromePHPHandler.php
+++ b/src/Monolog/Handler/ChromePHPHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Formatter\ChromePHPFormatter;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
@@ -32,7 +33,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
* Header name
*/
const HEADER_NAME = 'X-ChromeLogger-Data';
-
+
/**
* Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
*/
@@ -49,11 +50,11 @@ class ChromePHPHandler extends AbstractProcessingHandler
*/
protected static $overflowed = false;
- protected static $json = array(
+ protected static $json = [
'version' => self::VERSION,
- 'columns' => array('label', 'log', 'backtrace', 'type'),
- 'rows' => array(),
- );
+ 'columns' => ['label', 'log', 'backtrace', 'type'],
+ 'rows' => [],
+ ];
protected static $sendHeaders = true;
@@ -74,7 +75,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
*/
public function handleBatch(array $records)
{
- $messages = array();
+ $messages = [];
foreach ($records as $record) {
if ($record['level'] < $this->level) {
@@ -93,7 +94,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new ChromePHPFormatter();
}
@@ -131,7 +132,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
return;
}
- self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
+ self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
}
$json = @json_encode(self::$json);
@@ -139,15 +140,15 @@ class ChromePHPHandler extends AbstractProcessingHandler
if (strlen($data) > 240 * 1024) {
self::$overflowed = true;
- $record = array(
+ $record = [
'message' => 'Incomplete logs, chrome header size limit reached',
- 'context' => array(),
+ 'context' => [],
'level' => Logger::WARNING,
'level_name' => Logger::getLevelName(Logger::WARNING),
'channel' => 'monolog',
- 'datetime' => new \DateTime(),
- 'extra' => array(),
- );
+ 'datetime' => new \DateTimeImmutable(),
+ 'extra' => [],
+ ];
self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
$json = @json_encode(self::$json);
$data = base64_encode(utf8_encode($json));
@@ -173,39 +174,13 @@ class ChromePHPHandler extends AbstractProcessingHandler
/**
* Verifies if the headers are accepted by the current user agent
- *
- * @return Boolean
*/
- protected function headersAccepted()
+ protected function headersAccepted(): bool
{
if (empty($_SERVER['HTTP_USER_AGENT'])) {
return false;
}
- return preg_match(self::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']);
- }
-
- /**
- * BC getter for the sendHeaders property that has been made static
- */
- public function __get($property)
- {
- if ('sendHeaders' !== $property) {
- throw new \InvalidArgumentException('Undefined property '.$property);
- }
-
- return static::$sendHeaders;
- }
-
- /**
- * BC setter for the sendHeaders property that has been made static
- */
- public function __set($property, $value)
- {
- if ('sendHeaders' !== $property) {
- throw new \InvalidArgumentException('Undefined property '.$property);
- }
-
- static::$sendHeaders = $value;
+ return preg_match(self::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
}
}
diff --git a/src/Monolog/Handler/CouchDBHandler.php b/src/Monolog/Handler/CouchDBHandler.php
index cc98697..e0603f3 100644
--- a/src/Monolog/Handler/CouchDBHandler.php
+++ b/src/Monolog/Handler/CouchDBHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,6 +11,7 @@
namespace Monolog\Handler;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use Monolog\Logger;
@@ -23,15 +24,15 @@ class CouchDBHandler extends AbstractProcessingHandler
{
private $options;
- public function __construct(array $options = array(), $level = Logger::DEBUG, $bubble = true)
+ public function __construct(array $options = [], $level = Logger::DEBUG, $bubble = true)
{
- $this->options = array_merge(array(
+ $this->options = array_merge([
'host' => 'localhost',
'port' => 5984,
'dbname' => 'logger',
'username' => null,
'password' => null,
- ), $options);
+ ], $options);
parent::__construct($level, $bubble);
}
@@ -47,17 +48,17 @@ class CouchDBHandler extends AbstractProcessingHandler
}
$url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname'];
- $context = stream_context_create(array(
- 'http' => array(
+ $context = stream_context_create([
+ 'http' => [
'method' => 'POST',
'content' => $record['formatted'],
'ignore_errors' => true,
'max_redirects' => 0,
'header' => 'Content-type: application/json',
- ),
- ));
+ ],
+ ]);
- if (false === @file_get_contents($url, null, $context)) {
+ if (false === @file_get_contents($url, false, $context)) {
throw new \RuntimeException(sprintf('Could not connect to %s', $url));
}
}
@@ -65,7 +66,7 @@ class CouchDBHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
}
diff --git a/src/Monolog/Handler/CubeHandler.php b/src/Monolog/Handler/CubeHandler.php
index 96b3ca0..ab6e007 100644
--- a/src/Monolog/Handler/CubeHandler.php
+++ b/src/Monolog/Handler/CubeHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -26,7 +26,7 @@ class CubeHandler extends AbstractProcessingHandler
private $scheme;
private $host;
private $port;
- private $acceptedSchemes = array('http', 'udp');
+ private $acceptedSchemes = ['http', 'udp'];
/**
* Create a Cube handler
@@ -105,7 +105,7 @@ class CubeHandler extends AbstractProcessingHandler
{
$date = $record['datetime'];
- $data = array('time' => $date->format('Y-m-d\TH:i:s.uO'));
+ $data = ['time' => $date->format('Y-m-d\TH:i:s.uO')];
unset($record['datetime']);
if (isset($record['context']['type'])) {
@@ -141,10 +141,10 @@ class CubeHandler extends AbstractProcessingHandler
}
curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']');
- curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array(
+ curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen('['.$data.']'),
- ));
+ ]);
Curl\Util::execute($this->httpConnection, 5, false);
}
diff --git a/src/Monolog/Handler/Curl/Util.php b/src/Monolog/Handler/Curl/Util.php
index 48d30b3..b0bec3d 100644
--- a/src/Monolog/Handler/Curl/Util.php
+++ b/src/Monolog/Handler/Curl/Util.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -13,7 +13,7 @@ namespace Monolog\Handler\Curl;
class Util
{
- private static $retriableErrorCodes = array(
+ private static $retriableErrorCodes = [
CURLE_COULDNT_RESOLVE_HOST,
CURLE_COULDNT_CONNECT,
CURLE_HTTP_NOT_FOUND,
@@ -21,7 +21,7 @@ class Util
CURLE_OPERATION_TIMEOUTED,
CURLE_HTTP_POST_ERROR,
CURLE_SSL_CONNECT_ERROR,
- );
+ ];
/**
* Executes a CURL request with optional retries and exception on failure
diff --git a/src/Monolog/Handler/DeduplicationHandler.php b/src/Monolog/Handler/DeduplicationHandler.php
index 7778c22..235b3b8 100644
--- a/src/Monolog/Handler/DeduplicationHandler.php
+++ b/src/Monolog/Handler/DeduplicationHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -81,7 +81,6 @@ class DeduplicationHandler extends BufferHandler
foreach ($this->buffer as $record) {
if ($record['level'] >= $this->deduplicationLevel) {
-
$passthru = $passthru || !$this->isDuplicate($record);
if ($passthru) {
$this->appendRecord($record);
@@ -139,13 +138,13 @@ class DeduplicationHandler extends BufferHandler
$handle = fopen($this->deduplicationStore, 'rw+');
flock($handle, LOCK_EX);
- $validLogs = array();
+ $validLogs = [];
$timestampValidity = time() - $this->time;
while (!feof($handle)) {
$log = fgets($handle);
- if (substr($log, 0, 10) >= $timestampValidity) {
+ if ($log && substr($log, 0, 10) >= $timestampValidity) {
$validLogs[] = $log;
}
}
diff --git a/src/Monolog/Handler/DoctrineCouchDBHandler.php b/src/Monolog/Handler/DoctrineCouchDBHandler.php
index b91ffec..13a08ee 100644
--- a/src/Monolog/Handler/DoctrineCouchDBHandler.php
+++ b/src/Monolog/Handler/DoctrineCouchDBHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;
+use Monolog\Formatter\FormatterInterface;
use Doctrine\CouchDB\CouchDBClient;
/**
@@ -38,7 +39,7 @@ class DoctrineCouchDBHandler extends AbstractProcessingHandler
$this->client->postDocument($record['formatted']);
}
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new NormalizerFormatter;
}
diff --git a/src/Monolog/Handler/DynamoDbHandler.php b/src/Monolog/Handler/DynamoDbHandler.php
index 237b71f..a6991fa 100644
--- a/src/Monolog/Handler/DynamoDbHandler.php
+++ b/src/Monolog/Handler/DynamoDbHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Aws\Sdk;
use Aws\DynamoDb\DynamoDbClient;
+use Monolog\Formatter\FormatterInterface;
use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter;
use Monolog\Logger;
@@ -80,10 +81,10 @@ class DynamoDbHandler extends AbstractProcessingHandler
$formatted = $this->client->formatAttributes($filtered);
}
- $this->client->putItem(array(
+ $this->client->putItem([
'TableName' => $this->table,
'Item' => $formatted,
- ));
+ ]);
}
/**
@@ -100,7 +101,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
/**
* {@inheritdoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new ScalarFormatter(self::DATE_FORMAT);
}
diff --git a/src/Monolog/Handler/ElasticSearchHandler.php b/src/Monolog/Handler/ElasticSearchHandler.php
index 8196740..fbb999f 100644
--- a/src/Monolog/Handler/ElasticSearchHandler.php
+++ b/src/Monolog/Handler/ElasticSearchHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -43,7 +43,7 @@ class ElasticSearchHandler extends AbstractProcessingHandler
/**
* @var array Handler config options
*/
- protected $options = array();
+ protected $options = [];
/**
* @param Client $client Elastica Client object
@@ -51,16 +51,16 @@ class ElasticSearchHandler extends AbstractProcessingHandler
* @param int $level The minimum logging level at which this handler will be triggered
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
- public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true)
+ public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, $bubble = true)
{
parent::__construct($level, $bubble);
$this->client = $client;
$this->options = array_merge(
- array(
+ [
'index' => 'monolog', // Elastic index name
'type' => 'record', // Elastic document type
'ignore_error' => false, // Suppress Elastica exceptions
- ),
+ ],
$options
);
}
@@ -70,13 +70,13 @@ class ElasticSearchHandler extends AbstractProcessingHandler
*/
protected function write(array $record)
{
- $this->bulkSend(array($record['formatted']));
+ $this->bulkSend([$record['formatted']]);
}
/**
* {@inheritdoc}
*/
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
if ($formatter instanceof ElasticaFormatter) {
return parent::setFormatter($formatter);
@@ -96,7 +96,7 @@ class ElasticSearchHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new ElasticaFormatter($this->options['index'], $this->options['type']);
}
diff --git a/src/Monolog/Handler/ErrorLogHandler.php b/src/Monolog/Handler/ErrorLogHandler.php
index 1447a58..2c80139 100644
--- a/src/Monolog/Handler/ErrorLogHandler.php
+++ b/src/Monolog/Handler/ErrorLogHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
@@ -51,16 +52,16 @@ class ErrorLogHandler extends AbstractProcessingHandler
*/
public static function getAvailableTypes()
{
- return array(
+ return [
self::OPERATING_SYSTEM,
self::SAPI,
- );
+ ];
}
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%');
}
@@ -70,13 +71,14 @@ class ErrorLogHandler extends AbstractProcessingHandler
*/
protected function write(array $record)
{
- if ($this->expandNewlines) {
- $lines = preg_split('{[\r\n]+}', (string) $record['formatted']);
- foreach ($lines as $line) {
- error_log($line, $this->messageType);
- }
- } else {
+ if (!$this->expandNewlines) {
error_log((string) $record['formatted'], $this->messageType);
+ return;
+ }
+
+ $lines = preg_split('{[\r\n]+}', (string) $record['formatted']);
+ foreach ($lines as $line) {
+ error_log($line, $this->messageType);
}
}
}
diff --git a/src/Monolog/Handler/FilterHandler.php b/src/Monolog/Handler/FilterHandler.php
index 2a0f7fd..da0634a 100644
--- a/src/Monolog/Handler/FilterHandler.php
+++ b/src/Monolog/Handler/FilterHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -21,8 +21,10 @@ use Monolog\Logger;
* @author Hennadiy Verkh
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
-class FilterHandler extends AbstractHandler
+class FilterHandler extends Handler implements ProcessableHandlerInterface
{
+ use ProcessableHandlerTrait;
+
/**
* Handler or factory callable($record, $this)
*
@@ -64,7 +66,7 @@ class FilterHandler extends AbstractHandler
/**
* @return array
*/
- public function getAcceptedLevels()
+ public function getAcceptedLevels(): array
{
return array_flip($this->acceptedLevels);
}
@@ -90,7 +92,7 @@ class FilterHandler extends AbstractHandler
/**
* {@inheritdoc}
*/
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
return isset($this->acceptedLevels[$record['level']]);
}
@@ -98,7 +100,7 @@ class FilterHandler extends AbstractHandler
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
@@ -113,9 +115,7 @@ class FilterHandler extends AbstractHandler
}
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ $record = $this->processRecord($record);
}
$this->handler->handle($record);
@@ -128,7 +128,7 @@ class FilterHandler extends AbstractHandler
*/
public function handleBatch(array $records)
{
- $filtered = array();
+ $filtered = [];
foreach ($records as $record) {
if ($this->isHandling($record)) {
$filtered[] = $record;
diff --git a/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
index c3e42ef..f9cab61 100644
--- a/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
+++ b/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
diff --git a/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php b/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php
index 2a2a64d..63a14cb 100644
--- a/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php
+++ b/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -42,7 +42,7 @@ class ChannelLevelActivationStrategy implements ActivationStrategyInterface
* @param int $defaultActionLevel The default action level to be used if the record's category doesn't match any
* @param array $channelToActionLevel An array that maps channel names to action levels.
*/
- public function __construct($defaultActionLevel, $channelToActionLevel = array())
+ public function __construct($defaultActionLevel, $channelToActionLevel = [])
{
$this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel);
$this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel);
diff --git a/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php b/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php
index 6e63085..d0ebd84 100644
--- a/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php
+++ b/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
diff --git a/src/Monolog/Handler/FingersCrossedHandler.php b/src/Monolog/Handler/FingersCrossedHandler.php
index d1dcaac..f0151d1 100644
--- a/src/Monolog/Handler/FingersCrossedHandler.php
+++ b/src/Monolog/Handler/FingersCrossedHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -27,13 +27,15 @@ use Monolog\Logger;
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
-class FingersCrossedHandler extends AbstractHandler
+class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface
{
+ use ProcessableHandlerTrait;
+
protected $handler;
protected $activationStrategy;
protected $buffering = true;
protected $bufferSize;
- protected $buffer = array();
+ protected $buffer = [];
protected $stopBuffering;
protected $passthruLevel;
@@ -74,7 +76,7 @@ class FingersCrossedHandler extends AbstractHandler
/**
* {@inheritdoc}
*/
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
return true;
}
@@ -96,18 +98,16 @@ class FingersCrossedHandler extends AbstractHandler
}
}
$this->handler->handleBatch($this->buffer);
- $this->buffer = array();
+ $this->buffer = [];
}
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ $record = $this->processRecord($record);
}
if ($this->buffering) {
@@ -137,7 +137,7 @@ class FingersCrossedHandler extends AbstractHandler
});
if (count($this->buffer) > 0) {
$this->handler->handleBatch($this->buffer);
- $this->buffer = array();
+ $this->buffer = [];
}
}
}
@@ -157,7 +157,7 @@ class FingersCrossedHandler extends AbstractHandler
*/
public function clear()
{
- $this->buffer = array();
+ $this->buffer = [];
$this->reset();
}
}
diff --git a/src/Monolog/Handler/FirePHPHandler.php b/src/Monolog/Handler/FirePHPHandler.php
index fee4795..ac7230c 100644
--- a/src/Monolog/Handler/FirePHPHandler.php
+++ b/src/Monolog/Handler/FirePHPHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Formatter\WildfireFormatter;
+use Monolog\Formatter\FormatterInterface;
/**
* Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
@@ -60,26 +61,24 @@ class FirePHPHandler extends AbstractProcessingHandler
* @param string $message Log message
* @return array Complete header string ready for the client as key and message as value
*/
- protected function createHeader(array $meta, $message)
+ protected function createHeader(array $meta, string $message): array
{
$header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta));
- return array($header => $message);
+ return [$header => $message];
}
/**
* Creates message header from record
*
* @see createHeader()
- * @param array $record
- * @return string
*/
- protected function createRecordHeader(array $record)
+ protected function createRecordHeader(array $record): array
{
// Wildfire is extensible to support multiple protocols & plugins in a single request,
// but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
return $this->createHeader(
- array(1, 1, 1, self::$messageIndex++),
+ [1, 1, 1, self::$messageIndex++],
$record['formatted']
);
}
@@ -87,7 +86,7 @@ class FirePHPHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new WildfireFormatter();
}
@@ -103,9 +102,9 @@ class FirePHPHandler extends AbstractProcessingHandler
{
// Initial payload consists of required headers for Wildfire
return array_merge(
- $this->createHeader(array('Protocol', 1), self::PROTOCOL_URI),
- $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI),
- $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI)
+ $this->createHeader(['Protocol', 1], self::PROTOCOL_URI),
+ $this->createHeader([1, 'Structure', 1], self::STRUCTURE_URI),
+ $this->createHeader([1, 'Plugin', 1], self::PLUGIN_URI)
);
}
@@ -168,28 +167,4 @@ class FirePHPHandler extends AbstractProcessingHandler
return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
}
-
- /**
- * BC getter for the sendHeaders property that has been made static
- */
- public function __get($property)
- {
- if ('sendHeaders' !== $property) {
- throw new \InvalidArgumentException('Undefined property '.$property);
- }
-
- return static::$sendHeaders;
- }
-
- /**
- * BC setter for the sendHeaders property that has been made static
- */
- public function __set($property, $value)
- {
- if ('sendHeaders' !== $property) {
- throw new \InvalidArgumentException('Undefined property '.$property);
- }
-
- static::$sendHeaders = $value;
- }
}
diff --git a/src/Monolog/Handler/FleepHookHandler.php b/src/Monolog/Handler/FleepHookHandler.php
index c43c013..748100b 100644
--- a/src/Monolog/Handler/FleepHookHandler.php
+++ b/src/Monolog/Handler/FleepHookHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,6 +11,7 @@
namespace Monolog\Handler;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
@@ -63,7 +64,7 @@ class FleepHookHandler extends SocketHandler
*
* @return LineFormatter
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter(null, null, true, true);
}
@@ -117,9 +118,9 @@ class FleepHookHandler extends SocketHandler
*/
private function buildContent($record)
{
- $dataArray = array(
+ $dataArray = [
'message' => $record['formatted'],
- );
+ ];
return http_build_query($dataArray);
}
diff --git a/src/Monolog/Handler/FlowdockHandler.php b/src/Monolog/Handler/FlowdockHandler.php
index dd9a361..67d1291 100644
--- a/src/Monolog/Handler/FlowdockHandler.php
+++ b/src/Monolog/Handler/FlowdockHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -53,7 +53,7 @@ class FlowdockHandler extends SocketHandler
/**
* {@inheritdoc}
*/
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
if (!$formatter instanceof FlowdockFormatter) {
throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly');
@@ -65,9 +65,9 @@ class FlowdockHandler extends SocketHandler
/**
* Gets the default formatter.
*
- * @return FormatterInterface
+ * @suppress PhanTypeMissingReturn
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly');
}
diff --git a/src/Monolog/Handler/FormattableHandlerInterface.php b/src/Monolog/Handler/FormattableHandlerInterface.php
new file mode 100644
index 0000000..fc1693c
--- /dev/null
+++ b/src/Monolog/Handler/FormattableHandlerInterface.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Formatter\FormatterInterface;
+
+/**
+ * Interface to describe loggers that have a formatter
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+interface FormattableHandlerInterface
+{
+ /**
+ * Sets the formatter.
+ *
+ * @param FormatterInterface $formatter
+ * @return HandlerInterface self
+ */
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface;
+
+ /**
+ * Gets the formatter.
+ *
+ * @return FormatterInterface
+ */
+ public function getFormatter(): FormatterInterface;
+}
diff --git a/src/Monolog/Handler/FormattableHandlerTrait.php b/src/Monolog/Handler/FormattableHandlerTrait.php
new file mode 100644
index 0000000..2b7e56f
--- /dev/null
+++ b/src/Monolog/Handler/FormattableHandlerTrait.php
@@ -0,0 +1,60 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Formatter\LineFormatter;
+
+/**
+ * Helper trait for implementing FormattableInterface
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+trait FormattableHandlerTrait
+{
+ /**
+ * @var FormatterInterface
+ */
+ protected $formatter;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
+ {
+ $this->formatter = $formatter;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormatter(): FormatterInterface
+ {
+ if (!$this->formatter) {
+ $this->formatter = $this->getDefaultFormatter();
+ }
+
+ return $this->formatter;
+ }
+
+ /**
+ * Gets the default formatter.
+ *
+ * @return FormatterInterface
+ */
+ protected function getDefaultFormatter(): FormatterInterface
+ {
+ return new LineFormatter();
+ }
+}
diff --git a/src/Monolog/Handler/GelfHandler.php b/src/Monolog/Handler/GelfHandler.php
index d3847d8..b5c3a8c 100644
--- a/src/Monolog/Handler/GelfHandler.php
+++ b/src/Monolog/Handler/GelfHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,12 +11,10 @@
namespace Monolog\Handler;
-use Gelf\IMessagePublisher;
use Gelf\PublisherInterface;
-use Gelf\Publisher;
-use InvalidArgumentException;
use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter;
+use Monolog\Formatter\FormatterInterface;
/**
* Handler to send messages to a Graylog2 (http://www.graylog2.org) server
@@ -27,23 +25,19 @@ use Monolog\Formatter\GelfMessageFormatter;
class GelfHandler extends AbstractProcessingHandler
{
/**
- * @var Publisher the publisher object that sends the message to the server
+ * @var PublisherInterface|null the publisher object that sends the message to the server
*/
protected $publisher;
/**
- * @param PublisherInterface|IMessagePublisher|Publisher $publisher a publisher object
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param PublisherInterface $publisher a publisher object
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
- public function __construct($publisher, $level = Logger::DEBUG, $bubble = true)
+ public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, $bubble = true)
{
parent::__construct($level, $bubble);
- if (!$publisher instanceof Publisher && !$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) {
- throw new InvalidArgumentException('Invalid publisher, expected a Gelf\Publisher, Gelf\IMessagePublisher or Gelf\PublisherInterface instance');
- }
-
$this->publisher = $publisher;
}
@@ -66,7 +60,7 @@ class GelfHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new GelfMessageFormatter();
}
diff --git a/src/Monolog/Handler/GroupHandler.php b/src/Monolog/Handler/GroupHandler.php
index 663f5a9..ef1485f 100644
--- a/src/Monolog/Handler/GroupHandler.php
+++ b/src/Monolog/Handler/GroupHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -18,8 +18,10 @@ use Monolog\Formatter\FormatterInterface;
*
* @author Lenar Lõhmus <lenar@city.ee>
*/
-class GroupHandler extends AbstractHandler
+class GroupHandler extends Handler implements ProcessableHandlerInterface
{
+ use ProcessableHandlerTrait;
+
protected $handlers;
/**
@@ -41,7 +43,7 @@ class GroupHandler extends AbstractHandler
/**
* {@inheritdoc}
*/
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
@@ -55,12 +57,10 @@ class GroupHandler extends AbstractHandler
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ $record = $this->processRecord($record);
}
foreach ($this->handlers as $handler) {
@@ -76,7 +76,7 @@ class GroupHandler extends AbstractHandler
public function handleBatch(array $records)
{
if ($this->processors) {
- $processed = array();
+ $processed = [];
foreach ($records as $record) {
foreach ($this->processors as $processor) {
$processed[] = call_user_func($processor, $record);
diff --git a/src/Monolog/Handler/Handler.php b/src/Monolog/Handler/Handler.php
new file mode 100644
index 0000000..347e7b7
--- /dev/null
+++ b/src/Monolog/Handler/Handler.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+/**
+ * Base Handler class providing basic close() support as well as handleBatch
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+abstract class Handler implements HandlerInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function handleBatch(array $records)
+ {
+ foreach ($records as $record) {
+ $this->handle($record);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ }
+
+ public function __destruct()
+ {
+ try {
+ $this->close();
+ } catch (\Throwable $e) {
+ // do nothing
+ }
+ }
+
+ public function __sleep()
+ {
+ $this->close();
+
+ return array_keys(get_object_vars($this));
+ }
+}
diff --git a/src/Monolog/Handler/HandlerInterface.php b/src/Monolog/Handler/HandlerInterface.php
index d920c4b..472fd31 100644
--- a/src/Monolog/Handler/HandlerInterface.php
+++ b/src/Monolog/Handler/HandlerInterface.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,8 +11,6 @@
namespace Monolog\Handler;
-use Monolog\Formatter\FormatterInterface;
-
/**
* Interface that all Monolog Handlers must implement
*
@@ -33,7 +31,7 @@ interface HandlerInterface
*
* @return Boolean
*/
- public function isHandling(array $record);
+ public function isHandling(array $record): bool;
/**
* Handles a record.
@@ -49,7 +47,7 @@ interface HandlerInterface
* @return Boolean true means that this handler handled the record, and that bubbling is not permitted.
* false means the record was either not processed or that this handler allows bubbling.
*/
- public function handle(array $record);
+ public function handle(array $record): bool;
/**
* Handles a set of records at once.
@@ -59,32 +57,12 @@ interface HandlerInterface
public function handleBatch(array $records);
/**
- * Adds a processor in the stack.
- *
- * @param callable $callback
- * @return self
- */
- public function pushProcessor($callback);
-
- /**
- * Removes the processor on top of the stack and returns it.
- *
- * @return callable
- */
- public function popProcessor();
-
- /**
- * Sets the formatter.
+ * Closes the handler.
*
- * @param FormatterInterface $formatter
- * @return self
- */
- public function setFormatter(FormatterInterface $formatter);
-
- /**
- * Gets the formatter.
+ * This will be called automatically when the object is destroyed if you extend Monolog\Handler\Handler
*
- * @return FormatterInterface
+ * Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage)
+ * and ideally handlers should be able to reopen themselves on handle() after they have been closed.
*/
- public function getFormatter();
+ public function close();
}
diff --git a/src/Monolog/Handler/HandlerWrapper.php b/src/Monolog/Handler/HandlerWrapper.php
index e540d80..28fe57d 100644
--- a/src/Monolog/Handler/HandlerWrapper.php
+++ b/src/Monolog/Handler/HandlerWrapper.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -30,7 +30,7 @@ use Monolog\Formatter\FormatterInterface;
*
* @author Alexey Karapetov <alexey@karapetov.com>
*/
-class HandlerWrapper implements HandlerInterface
+class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface
{
/**
* @var HandlerInterface
@@ -49,7 +49,7 @@ class HandlerWrapper implements HandlerInterface
/**
* {@inheritdoc}
*/
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
return $this->handler->isHandling($record);
}
@@ -57,7 +57,7 @@ class HandlerWrapper implements HandlerInterface
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
return $this->handler->handle($record);
}
@@ -73,36 +73,58 @@ class HandlerWrapper implements HandlerInterface
/**
* {@inheritdoc}
*/
- public function pushProcessor($callback)
+ public function close()
{
- $this->handler->pushProcessor($callback);
+ return $this->handler->close();
+ }
- return $this;
+ /**
+ * {@inheritdoc}
+ */
+ public function pushProcessor(callable $callback): HandlerInterface
+ {
+ if ($this->handler instanceof ProcessableHandlerInterface) {
+ $this->handler->pushProcessor($callback);
+
+ return $this;
+ }
+
+ throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
}
/**
* {@inheritdoc}
*/
- public function popProcessor()
+ public function popProcessor(): callable
{
- return $this->handler->popProcessor();
+ if ($this->handler instanceof ProcessableHandlerInterface) {
+ return $this->handler->popProcessor();
+ }
+
+ throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
}
/**
* {@inheritdoc}
*/
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
- $this->handler->setFormatter($formatter);
+ if ($this->handler instanceof FormattableHandlerInterface) {
+ $this->handler->setFormatter($formatter);
+ }
- return $this;
+ throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
}
/**
* {@inheritdoc}
*/
- public function getFormatter()
+ public function getFormatter(): FormatterInterface
{
- return $this->handler->getFormatter();
+ if ($this->handler instanceof FormattableHandlerInterface) {
+ return $this->handler->getFormatter($formatter);
+ }
+
+ throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
}
}
diff --git a/src/Monolog/Handler/HipChatHandler.php b/src/Monolog/Handler/HipChatHandler.php
index 73049f3..98441f3 100644
--- a/src/Monolog/Handler/HipChatHandler.php
+++ b/src/Monolog/Handler/HipChatHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -16,12 +16,13 @@ use Monolog\Logger;
/**
* Sends notifications through the hipchat api to a hipchat room
*
+ * This handler only supports the API v2
+ *
* Notes:
* API token - HipChat API token
* Room - HipChat Room Id or name, where messages are sent
* Name - Name used to send the message (from)
* notify - Should the message trigger a notification in the clients
- * version - The API version to use (HipChatHandler::API_V1 | HipChatHandler::API_V2)
*
* @author Rafael Dohms <rafael@doh.ms>
* @see https://www.hipchat.com/docs/api
@@ -29,16 +30,6 @@ use Monolog\Logger;
class HipChatHandler extends SocketHandler
{
/**
- * Use API version 1
- */
- const API_V1 = 'v1';
-
- /**
- * Use API version v2
- */
- const API_V2 = 'v2';
-
- /**
* The maximum allowed length for the name used in the "from" field.
*/
const MAXIMUM_NAME_LENGTH = 15;
@@ -79,28 +70,18 @@ class HipChatHandler extends SocketHandler
private $host;
/**
- * @var string
+ * @param string $token HipChat API Token
+ * @param string $room The room that should be alerted of the message (Id or Name)
+ * @param string $name Name used in the "from" field.
+ * @param bool $notify Trigger a notification in clients or not
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $useSSL Whether to connect via SSL.
+ * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages)
+ * @param string $host The HipChat server hostname.
*/
- private $version;
-
- /**
- * @param string $token HipChat API Token
- * @param string $room The room that should be alerted of the message (Id or Name)
- * @param string $name Name used in the "from" field.
- * @param bool $notify Trigger a notification in clients or not
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param bool $useSSL Whether to connect via SSL.
- * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages)
- * @param string $host The HipChat server hostname.
- * @param string $version The HipChat API version (default HipChatHandler::API_V1)
- */
- public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1)
+ public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com')
{
- if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) {
- throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.');
- }
-
$connectionString = $useSSL ? 'ssl://'.$host.':443' : $host.':80';
parent::__construct($connectionString, $level, $bubble);
@@ -110,7 +91,6 @@ class HipChatHandler extends SocketHandler
$this->room = $room;
$this->format = $format;
$this->host = $host;
- $this->version = $version;
}
/**
@@ -134,14 +114,12 @@ class HipChatHandler extends SocketHandler
*/
private function buildContent($record)
{
- $dataArray = array(
- 'notify' => $this->version == self::API_V1 ?
- ($this->notify ? 1 : 0) :
- ($this->notify ? 'true' : 'false'),
+ $dataArray = [
+ 'notify' => $this->notify ? 'true' : 'false',
'message' => $record['formatted'],
'message_format' => $this->format,
'color' => $this->getAlertColor($record['level']),
- );
+ ];
if (!$this->validateStringLength($dataArray['message'], static::MAXIMUM_MESSAGE_LENGTH)) {
if (function_exists('mb_substr')) {
@@ -151,14 +129,9 @@ class HipChatHandler extends SocketHandler
}
}
- // if we are using the legacy API then we need to send some additional information
- if ($this->version == self::API_V1) {
- $dataArray['room_id'] = $this->room;
- }
-
// append the sender name if it is set
// always append it if we use the v1 api (it is required in v1)
- if ($this->version == self::API_V1 || $this->name !== null) {
+ if ($this->name !== null) {
$dataArray['from'] = (string) $this->name;
}
@@ -173,13 +146,9 @@ class HipChatHandler extends SocketHandler
*/
private function buildHeader($content)
{
- if ($this->version == self::API_V1) {
- $header = "POST /v1/rooms/message?format=json&auth_token={$this->token} HTTP/1.1\r\n";
- } else {
- // needed for rooms with special (spaces, etc) characters in the name
- $room = rawurlencode($this->room);
- $header = "POST /v2/room/{$room}/notification?auth_token={$this->token} HTTP/1.1\r\n";
- }
+ // needed for rooms with special (spaces, etc) characters in the name
+ $room = rawurlencode($this->room);
+ $header = "POST /v2/room/{$room}/notification?auth_token={$this->token} HTTP/1.1\r\n";
$header .= "Host: {$this->host}\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
@@ -259,9 +228,9 @@ class HipChatHandler extends SocketHandler
private function combineRecords($records)
{
$batchRecord = null;
- $batchRecords = array();
- $messages = array();
- $formattedMessages = array();
+ $batchRecords = [];
+ $messages = [];
+ $formattedMessages = [];
$level = 0;
$levelName = null;
$datetime = null;
@@ -283,12 +252,12 @@ class HipChatHandler extends SocketHandler
$formattedMessages[] = $this->getFormatter()->format($record);
$formattedMessageStr = implode('', $formattedMessages);
- $batchRecord = array(
+ $batchRecord = [
'message' => $messageStr,
'formatted' => $formattedMessageStr,
- 'context' => array(),
- 'extra' => array(),
- );
+ 'context' => [],
+ 'extra' => [],
+ ];
if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) {
// Pop the last message and implode the remaining messages
@@ -298,8 +267,8 @@ class HipChatHandler extends SocketHandler
$batchRecord['formatted'] = implode('', $formattedMessages);
$batchRecords[] = $batchRecord;
- $messages = array($lastMessage);
- $formattedMessages = array($lastFormattedMessage);
+ $messages = [$lastMessage];
+ $formattedMessages = [$lastFormattedMessage];
$batchRecord = null;
}
@@ -313,11 +282,11 @@ class HipChatHandler extends SocketHandler
foreach ($batchRecords as &$batchRecord) {
$batchRecord = array_merge(
$batchRecord,
- array(
+ [
'level' => $level,
'level_name' => $levelName,
'datetime' => $datetime,
- )
+ ]
);
}
diff --git a/src/Monolog/Handler/IFTTTHandler.php b/src/Monolog/Handler/IFTTTHandler.php
index d60a3c8..46792ee 100644
--- a/src/Monolog/Handler/IFTTTHandler.php
+++ b/src/Monolog/Handler/IFTTTHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -48,11 +48,11 @@ class IFTTTHandler extends AbstractProcessingHandler
*/
public function write(array $record)
{
- $postData = array(
+ $postData = [
"value1" => $record["channel"],
"value2" => $record["level_name"],
"value3" => $record["message"],
- );
+ ];
$postString = json_encode($postData);
$ch = curl_init();
@@ -60,9 +60,9 @@ class IFTTTHandler extends AbstractProcessingHandler
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
- curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
- ));
+ ]);
Curl\Util::execute($ch);
}
diff --git a/src/Monolog/Handler/LogEntriesHandler.php b/src/Monolog/Handler/LogEntriesHandler.php
index 494c605..c74b9d2 100644
--- a/src/Monolog/Handler/LogEntriesHandler.php
+++ b/src/Monolog/Handler/LogEntriesHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
diff --git a/src/Monolog/Handler/LogglyHandler.php b/src/Monolog/Handler/LogglyHandler.php
index bcd62e1..544e7c7 100644
--- a/src/Monolog/Handler/LogglyHandler.php
+++ b/src/Monolog/Handler/LogglyHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Logger;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogglyFormatter;
/**
@@ -29,7 +30,7 @@ class LogglyHandler extends AbstractProcessingHandler
protected $token;
- protected $tag = array();
+ protected $tag = [];
public function __construct($token, $level = Logger::DEBUG, $bubble = true)
{
@@ -44,14 +45,14 @@ class LogglyHandler extends AbstractProcessingHandler
public function setTag($tag)
{
- $tag = !empty($tag) ? $tag : array();
- $this->tag = is_array($tag) ? $tag : array($tag);
+ $tag = !empty($tag) ? $tag : [];
+ $this->tag = is_array($tag) ? $tag : [$tag];
}
public function addTag($tag)
{
if (!empty($tag)) {
- $tag = is_array($tag) ? $tag : array($tag);
+ $tag = is_array($tag) ? $tag : [$tag];
$this->tag = array_unique(array_merge($this->tag, $tag));
}
}
@@ -78,7 +79,7 @@ class LogglyHandler extends AbstractProcessingHandler
{
$url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token);
- $headers = array('Content-Type: application/json');
+ $headers = ['Content-Type: application/json'];
if (!empty($this->tag)) {
$headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag);
@@ -95,7 +96,7 @@ class LogglyHandler extends AbstractProcessingHandler
Curl\Util::execute($ch);
}
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LogglyFormatter();
}
diff --git a/src/Monolog/Handler/LogmaticHandler.php b/src/Monolog/Handler/LogmaticHandler.php
new file mode 100644
index 0000000..9747220
--- /dev/null
+++ b/src/Monolog/Handler/LogmaticHandler.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Formatter\LogmaticFormatter;
+
+/**
+ * @author Julien Breux <julien.breux@gmail.com>
+ */
+class LogmaticHandler extends SocketHandler
+{
+ /**
+ * @var string
+ */
+ private $logToken;
+
+ /**
+ * @var string
+ */
+ private $hostname;
+
+ /**
+ * @var string
+ */
+ private $appname;
+
+ /**
+ * @param string $token Log token supplied by Logmatic.
+ * @param string $hostname Host name supplied by Logmatic.
+ * @param string $appname Application name supplied by Logmatic.
+ * @param bool $useSSL Whether or not SSL encryption should be used.
+ * @param int|string $level The minimum logging level to trigger this handler.
+ * @param bool $bubble Whether or not messages that are handled should bubble up the stack.
+ *
+ * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
+ */
+ public function __construct(string $token, string $hostname = '', string $appname = '', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
+ {
+ if ($useSSL && !extension_loaded('openssl')) {
+ throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler');
+ }
+
+ $endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514';
+ $endpoint .= '/v1/';
+
+ parent::__construct($endpoint, $level, $bubble);
+
+ $this->logToken = $token;
+ $this->hostname = $hostname;
+ $this->appname = $appname;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function generateDataStream($record): string
+ {
+ return $this->logToken . ' ' . $record['formatted'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getDefaultFormatter(): FormatterInterface
+ {
+ $formatter = new LogmaticFormatter();
+
+ if (!empty($this->hostname)) {
+ $formatter->setHostname($this->hostname);
+ }
+ if (!empty($this->appname)) {
+ $formatter->setAppname($this->appname);
+ }
+
+ return $formatter;
+ }
+}
diff --git a/src/Monolog/Handler/MailHandler.php b/src/Monolog/Handler/MailHandler.php
index 9e23283..634fbc1 100644
--- a/src/Monolog/Handler/MailHandler.php
+++ b/src/Monolog/Handler/MailHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,6 +11,9 @@
namespace Monolog\Handler;
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Formatter\HtmlFormatter;
+
/**
* Base class for all mail handlers
*
@@ -23,7 +26,7 @@ abstract class MailHandler extends AbstractProcessingHandler
*/
public function handleBatch(array $records)
{
- $messages = array();
+ $messages = [];
foreach ($records as $record) {
if ($record['level'] < $this->level) {
@@ -43,14 +46,14 @@ abstract class MailHandler extends AbstractProcessingHandler
* @param string $content formatted email body to be sent
* @param array $records the array of log records that formed this content
*/
- abstract protected function send($content, array $records);
+ abstract protected function send(string $content, array $records);
/**
* {@inheritdoc}
*/
protected function write(array $record)
{
- $this->send((string) $record['formatted'], array($record));
+ $this->send((string) $record['formatted'], [$record]);
}
protected function getHighestRecord(array $records)
@@ -64,4 +67,19 @@ abstract class MailHandler extends AbstractProcessingHandler
return $highestRecord;
}
+
+ protected function isHtmlBody($body)
+ {
+ return substr($body, 0, 1) === '<';
+ }
+
+ /**
+ * Gets the default formatter.
+ *
+ * @return FormatterInterface
+ */
+ protected function getDefaultFormatter(): FormatterInterface
+ {
+ return new HtmlFormatter();
+ }
}
diff --git a/src/Monolog/Handler/MandrillHandler.php b/src/Monolog/Handler/MandrillHandler.php
index ab95924..066c649 100644
--- a/src/Monolog/Handler/MandrillHandler.php
+++ b/src/Monolog/Handler/MandrillHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -46,10 +46,15 @@ class MandrillHandler extends MailHandler
/**
* {@inheritdoc}
*/
- protected function send($content, array $records)
+ protected function send(string $content, array $records)
{
+ $mime = null;
+ if ($this->isHtmlBody($content)) {
+ $mime = 'text/html';
+ }
+
$message = clone $this->message;
- $message->setBody($content);
+ $message->setBody($content, $mime);
$message->setDate(time());
$ch = curl_init();
@@ -57,11 +62,11 @@ class MandrillHandler extends MailHandler
curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'key' => $this->apiKey,
'raw_message' => (string) $message,
'async' => false,
- )));
+ ]));
Curl\Util::execute($ch);
}
diff --git a/src/Monolog/Handler/MissingExtensionException.php b/src/Monolog/Handler/MissingExtensionException.php
index 4724a7e..1554b34 100644
--- a/src/Monolog/Handler/MissingExtensionException.php
+++ b/src/Monolog/Handler/MissingExtensionException.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
diff --git a/src/Monolog/Handler/MongoDBHandler.php b/src/Monolog/Handler/MongoDBHandler.php
index 56fe755..f302d31 100644
--- a/src/Monolog/Handler/MongoDBHandler.php
+++ b/src/Monolog/Handler/MongoDBHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,49 +11,75 @@
namespace Monolog\Handler;
+use MongoDB\Driver\BulkWrite;
+use MongoDB\Driver\Manager;
+use MongoDB\Client;
use Monolog\Logger;
-use Monolog\Formatter\NormalizerFormatter;
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Formatter\MongoDBFormatter;
/**
* Logs to a MongoDB database.
*
- * usage example:
+ * Usage example:
*
- * $log = new Logger('application');
- * $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod");
+ * $log = new \Monolog\Logger('application');
+ * $client = new \MongoDB\Client('mongodb://localhost:27017');
+ * $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod');
* $log->pushHandler($mongodb);
*
- * @author Thomas Tourlourat <thomas@tourlourat.com>
+ * The above examples uses the MongoDB PHP library's client class; however, the
+ * MongoDB\Driver\Manager class from ext-mongodb is also supported.
*/
class MongoDBHandler extends AbstractProcessingHandler
{
- protected $mongoCollection;
+ private $collection;
+ private $manager;
+ private $namespace;
- public function __construct($mongo, $database, $collection, $level = Logger::DEBUG, $bubble = true)
+ /**
+ * Constructor.
+ *
+ * @param Client|Manager $mongodb MongoDB library or driver client
+ * @param string $database Database name
+ * @param string $collection Collection name
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
+ */
+ public function __construct($mongodb, $database, $collection, $level = Logger::DEBUG, $bubble = true)
{
- if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo || $mongo instanceof \MongoDB\Client)) {
- throw new \InvalidArgumentException('MongoClient, Mongo or MongoDB\Client instance required');
+ if (!($mongodb instanceof Client || $mongodb instanceof Manager)) {
+ throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required');
}
- $this->mongoCollection = $mongo->selectCollection($database, $collection);
+ if ($mongodb instanceof Client) {
+ $this->collection = $mongodb->selectCollection($database, $collection);
+ } else {
+ $this->manager = $mongodb;
+ $this->namespace = $database . '.' . $collection;
+ }
parent::__construct($level, $bubble);
}
protected function write(array $record)
{
- if ($this->mongoCollection instanceof \MongoDB\Collection) {
- $this->mongoCollection->insertOne($record["formatted"]);
- } else {
- $this->mongoCollection->save($record["formatted"]);
+ if (isset($this->collection)) {
+ $this->collection->insertOne($record['formatted']);
+ }
+
+ if (isset($this->manager, $this->namespace)) {
+ $bulk = new BulkWrite;
+ $bulk->insert($record["formatted"]);
+ $this->manager->executeBulkWrite($this->namespace, $bulk);
}
}
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
- return new NormalizerFormatter();
+ return new MongoDBFormatter;
}
}
diff --git a/src/Monolog/Handler/NativeMailerHandler.php b/src/Monolog/Handler/NativeMailerHandler.php
index d7807fd..b597761 100644
--- a/src/Monolog/Handler/NativeMailerHandler.php
+++ b/src/Monolog/Handler/NativeMailerHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -38,13 +38,13 @@ class NativeMailerHandler extends MailHandler
* Optional headers for the message
* @var array
*/
- protected $headers = array();
+ protected $headers = [];
/**
* Optional parameters for the message
* @var array
*/
- protected $parameters = array();
+ protected $parameters = [];
/**
* The wordwrap length for the message
@@ -56,7 +56,7 @@ class NativeMailerHandler extends MailHandler
* The Content-type for the message
* @var string
*/
- protected $contentType = 'text/plain';
+ protected $contentType;
/**
* The encoding for the message
@@ -75,7 +75,7 @@ class NativeMailerHandler extends MailHandler
public function __construct($to, $subject, $from, $level = Logger::ERROR, $bubble = true, $maxColumnWidth = 70)
{
parent::__construct($level, $bubble);
- $this->to = is_array($to) ? $to : array($to);
+ $this->to = (array) $to;
$this->subject = $subject;
$this->addHeader(sprintf('From: %s', $from));
$this->maxColumnWidth = $maxColumnWidth;
@@ -115,12 +115,17 @@ class NativeMailerHandler extends MailHandler
/**
* {@inheritdoc}
*/
- protected function send($content, array $records)
+ protected function send(string $content, array $records)
{
- $content = wordwrap($content, $this->maxColumnWidth);
+ $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
+
+ if ($contentType !== 'text/html') {
+ $content = wordwrap($content, $this->maxColumnWidth);
+ }
+
$headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n");
- $headers .= 'Content-type: ' . $this->getContentType() . '; charset=' . $this->getEncoding() . "\r\n";
- if ($this->getContentType() == 'text/html' && false === strpos($headers, 'MIME-Version:')) {
+ $headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n";
+ if ($contentType === 'text/html' && false === strpos($headers, 'MIME-Version:')) {
$headers .= 'MIME-Version: 1.0' . "\r\n";
}
diff --git a/src/Monolog/Handler/NewRelicHandler.php b/src/Monolog/Handler/NewRelicHandler.php
index 6718e9e..fb03778 100644
--- a/src/Monolog/Handler/NewRelicHandler.php
+++ b/src/Monolog/Handler/NewRelicHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;
+use Monolog\Formatter\FormatterInterface;
/**
* Class to record a log on a NewRelic application.
@@ -195,7 +196,7 @@ class NewRelicHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new NormalizerFormatter();
}
diff --git a/src/Monolog/Handler/NoopHandler.php b/src/Monolog/Handler/NoopHandler.php
new file mode 100644
index 0000000..8ee2b4c
--- /dev/null
+++ b/src/Monolog/Handler/NoopHandler.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+/**
+ * No-op
+ *
+ * This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack.
+ * This can be used for testing, or to disable a handler when overriding a configuration without
+ * influencing the rest of the stack.
+ *
+ * @author Roel Harbers <roelharbers@gmail.com>
+ */
+class NoopHandler extends Handler
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function isHandling(array $record): bool
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handle(array $record): bool
+ {
+ return false;
+ }
+}
diff --git a/src/Monolog/Handler/NullHandler.php b/src/Monolog/Handler/NullHandler.php
index 4b84588..93678e8 100644
--- a/src/Monolog/Handler/NullHandler.php
+++ b/src/Monolog/Handler/NullHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -21,20 +21,30 @@ use Monolog\Logger;
*
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
-class NullHandler extends AbstractHandler
+class NullHandler extends Handler
{
+ private $level;
+
/**
* @param int $level The minimum logging level at which this handler will be triggered
*/
- public function __construct($level = Logger::DEBUG)
+ public function __construct(int $level = Logger::DEBUG)
+ {
+ $this->level = $level;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isHandling(array $record): bool
{
- parent::__construct($level, false);
+ return $record['level'] >= $this->level;
}
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($record['level'] < $this->level) {
return false;
diff --git a/src/Monolog/Handler/PHPConsoleHandler.php b/src/Monolog/Handler/PHPConsoleHandler.php
index 1f2076a..c2b7b3e 100644
--- a/src/Monolog/Handler/PHPConsoleHandler.php
+++ b/src/Monolog/Handler/PHPConsoleHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,11 +11,11 @@
namespace Monolog\Handler;
-use Exception;
use Monolog\Formatter\LineFormatter;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use PhpConsole\Connector;
-use PhpConsole\Handler;
+use PhpConsole\Handler as VendorPhpConsoleHandler;
use PhpConsole\Helper;
/**
@@ -32,17 +32,17 @@ use PhpConsole\Helper;
* $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
* \Monolog\ErrorHandler::register($logger);
* echo $undefinedVar;
- * $logger->addDebug('SELECT * FROM users', array('db', 'time' => 0.012));
+ * $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012));
* PC::debug($_SERVER); // PHP Console debugger for any type of vars
*
* @author Sergey Barbushin https://www.linkedin.com/in/barbushin
*/
class PHPConsoleHandler extends AbstractProcessingHandler
{
- private $options = array(
+ private $options = [
'enabled' => true, // bool Is PHP Console server enabled
- 'classesPartialsTraceIgnore' => array('Monolog\\'), // array Hide calls of classes started with...
- 'debugTagsKeysInContext' => array(0, 'tag'), // bool Is PHP Console server enabled
+ 'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with...
+ 'debugTagsKeysInContext' => [0, 'tag'], // bool Is PHP Console server enabled
'useOwnErrorsHandler' => false, // bool Enable errors handling
'useOwnExceptionsHandler' => false, // bool Enable exceptions handling
'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths
@@ -51,7 +51,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
'headersLimit' => null, // int|null Set headers size limit for your web-server
'password' => null, // string|null Protect PHP Console connection by password
'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed
- 'ipMasks' => array(), // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
+ 'ipMasks' => [], // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level
@@ -60,22 +60,22 @@ class PHPConsoleHandler extends AbstractProcessingHandler
'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON
'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug
'dataStorage' => null, // PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ)
- );
+ ];
/** @var Connector */
private $connector;
/**
- * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
- * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
- * @param int $level
- * @param bool $bubble
- * @throws Exception
+ * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
+ * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
+ * @param int $level
+ * @param bool $bubble
+ * @throws \RuntimeException
*/
- public function __construct(array $options = array(), Connector $connector = null, $level = Logger::DEBUG, $bubble = true)
+ public function __construct(array $options = [], Connector $connector = null, $level = Logger::DEBUG, $bubble = true)
{
if (!class_exists('PhpConsole\Connector')) {
- throw new Exception('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
+ throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
}
parent::__construct($level, $bubble);
$this->options = $this->initOptions($options);
@@ -86,7 +86,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
{
$wrongOptions = array_diff(array_keys($options), array_keys($this->options));
if ($wrongOptions) {
- throw new Exception('Unknown options: ' . implode(', ', $wrongOptions));
+ throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
}
return array_replace($this->options, $options);
@@ -107,7 +107,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
if ($this->options['enabled'] && $connector->isActiveClient()) {
if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
- $handler = Handler::getInstance();
+ $handler = VendorPhpConsoleHandler::getInstance();
$handler->setHandleErrors($this->options['useOwnErrorsHandler']);
$handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
$handler->start();
@@ -157,7 +157,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
return $this->options;
}
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->options['enabled'] && $this->connector->isActiveClient()) {
return parent::handle($record);
@@ -176,7 +176,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
{
if ($record['level'] < Logger::NOTICE) {
$this->handleDebugRecord($record);
- } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) {
+ } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$this->handleExceptionRecord($record);
} else {
$this->handleErrorRecord($record);
@@ -203,10 +203,10 @@ class PHPConsoleHandler extends AbstractProcessingHandler
$context = $record['context'];
$this->connector->getErrorsDispatcher()->dispatchError(
- isset($context['code']) ? $context['code'] : null,
- isset($context['message']) ? $context['message'] : $record['message'],
- isset($context['file']) ? $context['file'] : null,
- isset($context['line']) ? $context['line'] : null,
+ $context['code'] ?? null,
+ $context['message'] ?? $record['message'],
+ $context['file'] ?? null,
+ $context['line'] ?? null,
$this->options['classesPartialsTraceIgnore']
);
}
@@ -235,7 +235,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter('%message%');
}
diff --git a/src/Monolog/Handler/ProcessHandler.php b/src/Monolog/Handler/ProcessHandler.php
new file mode 100644
index 0000000..8cf6087
--- /dev/null
+++ b/src/Monolog/Handler/ProcessHandler.php
@@ -0,0 +1,202 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+
+/**
+ * Stores to STDIN of any process, specified by a command.
+ *
+ * Usage example:
+ * <pre>
+ * $log = new Logger('myLogger');
+ * $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
+ * </pre>
+ *
+ * @author Kolja Zuelsdorf <koljaz@web.de>
+ */
+class ProcessHandler extends AbstractProcessingHandler
+{
+ /**
+ * Holds the process to receive data on its STDIN.
+ *
+ * @var resource|bool|null
+ */
+ private $process;
+
+ /**
+ * @var string
+ */
+ private $command;
+
+ /**
+ * @var string
+ */
+ private $cwd;
+
+ /**
+ * @var array
+ */
+ private $pipes = [];
+
+ /**
+ * @var array
+ */
+ const DESCRIPTOR_SPEC = [
+ 0 => ['pipe', 'r'], // STDIN is a pipe that the child will read from
+ 1 => ['pipe', 'w'], // STDOUT is a pipe that the child will write to
+ 2 => ['pipe', 'w'], // STDERR is a pipe to catch the any errors
+ ];
+
+ /**
+ * @param string $command Command for the process to start. Absolute paths are recommended,
+ * especially if you do not use the $cwd parameter.
+ * @param string|int $level The minimum logging level at which this handler will be triggered.
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not.
+ * @param string $cwd "Current working directory" (CWD) for the process to be executed in.
+ * @throws \InvalidArgumentException
+ */
+ public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, string $cwd = null)
+ {
+ if ($command === '') {
+ throw new \InvalidArgumentException('The command argument must be a non-empty string.');
+ }
+ if ($cwd === '') {
+ throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
+ }
+
+ parent::__construct($level, $bubble);
+
+ $this->command = $command;
+ $this->cwd = $cwd;
+ }
+
+ /**
+ * Writes the record down to the log of the implementing handler
+ *
+ * @param array $record
+ * @throws \UnexpectedValueException
+ * @return void
+ */
+ protected function write(array $record)
+ {
+ $this->ensureProcessIsStarted();
+
+ $this->writeProcessInput($record['formatted']);
+
+ $errors = $this->readProcessErrors();
+ if (empty($errors) === false) {
+ throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
+ }
+ }
+
+ /**
+ * Makes sure that the process is actually started, and if not, starts it,
+ * assigns the stream pipes, and handles startup errors, if any.
+ *
+ * @return void
+ */
+ private function ensureProcessIsStarted()
+ {
+ if (is_resource($this->process) === false) {
+ $this->startProcess();
+
+ $this->handleStartupErrors();
+ }
+ }
+
+ /**
+ * Starts the actual process and sets all streams to non-blocking.
+ *
+ * @return void
+ */
+ private function startProcess()
+ {
+ $this->process = proc_open($this->command, self::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
+
+ foreach ($this->pipes as $pipe) {
+ stream_set_blocking($pipe, false);
+ }
+ }
+
+ /**
+ * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
+ *
+ * @throws \UnexpectedValueException
+ * @return void
+ */
+ private function handleStartupErrors()
+ {
+ $selected = $this->selectErrorStream();
+ if (false === $selected) {
+ throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
+ }
+
+ $errors = $this->readProcessErrors();
+
+ if (is_resource($this->process) === false || empty($errors) === false) {
+ throw new \UnexpectedValueException(
+ sprintf('The process "%s" could not be opened: ' . $errors, $this->command)
+ );
+ }
+ }
+
+ /**
+ * Selects the STDERR stream.
+ *
+ * @return int|bool
+ */
+ protected function selectErrorStream()
+ {
+ $empty = [];
+ $errorPipes = [$this->pipes[2]];
+
+ return stream_select($errorPipes, $empty, $empty, 1);
+ }
+
+ /**
+ * Reads the errors of the process, if there are any.
+ *
+ * @codeCoverageIgnore
+ * @return string Empty string if there are no errors.
+ */
+ protected function readProcessErrors()
+ {
+ return stream_get_contents($this->pipes[2]);
+ }
+
+ /**
+ * Writes to the input stream of the opened process.
+ *
+ * @codeCoverageIgnore
+ * @param $string
+ * @return void
+ */
+ protected function writeProcessInput($string)
+ {
+ fwrite($this->pipes[0], (string) $string);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ if (is_resource($this->process)) {
+ foreach ($this->pipes as $pipe) {
+ fclose($pipe);
+ }
+ proc_close($this->process);
+ $this->process = null;
+ }
+ }
+}
diff --git a/src/Monolog/Handler/ProcessableHandlerInterface.php b/src/Monolog/Handler/ProcessableHandlerInterface.php
new file mode 100644
index 0000000..9556f98
--- /dev/null
+++ b/src/Monolog/Handler/ProcessableHandlerInterface.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+/**
+ * Interface to describe loggers that have processors
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+interface ProcessableHandlerInterface
+{
+ /**
+ * Adds a processor in the stack.
+ *
+ * @param callable $callback
+ * @return HandlerInterface self
+ */
+ public function pushProcessor(callable $callback): HandlerInterface;
+
+ /**
+ * Removes the processor on top of the stack and returns it.
+ *
+ * @throws \LogicException In case the processor stack is empty
+ * @return callable
+ */
+ public function popProcessor(): callable;
+}
diff --git a/src/Monolog/Handler/ProcessableHandlerTrait.php b/src/Monolog/Handler/ProcessableHandlerTrait.php
new file mode 100644
index 0000000..bba940e
--- /dev/null
+++ b/src/Monolog/Handler/ProcessableHandlerTrait.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+/**
+ * Helper trait for implementing ProcessableInterface
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+trait ProcessableHandlerTrait
+{
+ /**
+ * @var callable[]
+ */
+ protected $processors = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function pushProcessor(callable $callback): HandlerInterface
+ {
+ array_unshift($this->processors, $callback);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function popProcessor(): callable
+ {
+ if (!$this->processors) {
+ throw new \LogicException('You tried to pop from an empty processor stack.');
+ }
+
+ return array_shift($this->processors);
+ }
+
+ /**
+ * Processes a record.
+ *
+ * @param array $record
+ * @return array
+ */
+ protected function processRecord(array $record)
+ {
+ foreach ($this->processors as $processor) {
+ $record = $processor($record);
+ }
+
+ return $record;
+ }
+}
diff --git a/src/Monolog/Handler/PsrHandler.php b/src/Monolog/Handler/PsrHandler.php
index 1ae8584..415b45f 100644
--- a/src/Monolog/Handler/PsrHandler.php
+++ b/src/Monolog/Handler/PsrHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -43,7 +43,7 @@ class PsrHandler extends AbstractHandler
/**
* {@inheritDoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
diff --git a/src/Monolog/Handler/PushoverHandler.php b/src/Monolog/Handler/PushoverHandler.php
index bba7200..b53ce6c 100644
--- a/src/Monolog/Handler/PushoverHandler.php
+++ b/src/Monolog/Handler/PushoverHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -37,7 +37,7 @@ class PushoverHandler extends SocketHandler
* @see https://pushover.net/api
* @var array
*/
- private $parameterNames = array(
+ private $parameterNames = [
'token' => true,
'user' => true,
'message' => true,
@@ -51,18 +51,18 @@ class PushoverHandler extends SocketHandler
'retry' => true,
'expire' => true,
'callback' => true,
- );
+ ];
/**
* Sounds the api supports by default
* @see https://pushover.net/api#sounds
* @var array
*/
- private $sounds = array(
+ private $sounds = [
'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming',
'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb',
'persistent', 'echo', 'updown', 'none',
- );
+ ];
/**
* @param string $token Pushover api token
@@ -110,13 +110,13 @@ class PushoverHandler extends SocketHandler
$timestamp = $record['datetime']->getTimestamp();
- $dataArray = array(
+ $dataArray = [
'token' => $this->token,
'user' => $this->user,
'message' => $message,
'title' => $this->title,
'timestamp' => $timestamp,
- );
+ ];
if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) {
$dataArray['priority'] = 2;
diff --git a/src/Monolog/Handler/RavenHandler.php b/src/Monolog/Handler/RavenHandler.php
index 53a8b39..1c8e718 100644
--- a/src/Monolog/Handler/RavenHandler.php
+++ b/src/Monolog/Handler/RavenHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -27,7 +27,7 @@ class RavenHandler extends AbstractProcessingHandler
/**
* Translates Monolog log levels to Raven log levels.
*/
- private $logLevels = array(
+ private $logLevels = [
Logger::DEBUG => Raven_Client::DEBUG,
Logger::INFO => Raven_Client::INFO,
Logger::NOTICE => Raven_Client::INFO,
@@ -36,7 +36,7 @@ class RavenHandler extends AbstractProcessingHandler
Logger::CRITICAL => Raven_Client::FATAL,
Logger::ALERT => Raven_Client::FATAL,
Logger::EMERGENCY => Raven_Client::FATAL,
- );
+ ];
/**
* @var string should represent the current version of the calling
@@ -92,7 +92,7 @@ class RavenHandler extends AbstractProcessingHandler
});
// the other ones are added as a context item
- $logs = array();
+ $logs = [];
foreach ($records as $r) {
$logs[] = $this->processRecord($r);
}
@@ -133,10 +133,11 @@ class RavenHandler extends AbstractProcessingHandler
*/
protected function write(array $record)
{
+ /** @var bool|null|array This is false, unless set below to null or an array of data, when we read the current user context */
$previousUserContext = false;
- $options = array();
+ $options = [];
$options['level'] = $this->logLevels[$record['level']];
- $options['tags'] = array();
+ $options['tags'] = [];
if (!empty($record['extra']['tags'])) {
$options['tags'] = array_merge($options['tags'], $record['extra']['tags']);
unset($record['extra']['tags']);
@@ -156,7 +157,7 @@ class RavenHandler extends AbstractProcessingHandler
$options['logger'] = $record['channel'];
}
foreach ($this->getExtraParameters() as $key) {
- foreach (array('extra', 'context') as $source) {
+ foreach (['extra', 'context'] as $source) {
if (!empty($record[$source][$key])) {
$options[$key] = $record[$source][$key];
unset($record[$source][$key]);
@@ -179,14 +180,15 @@ class RavenHandler extends AbstractProcessingHandler
$options['release'] = $this->release;
}
- if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
+ if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$options['extra']['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
- $this->ravenClient->captureMessage($record['formatted'], array(), $options);
+ $this->ravenClient->captureMessage($record['formatted'], [], $options);
}
- if ($previousUserContext !== false) {
+ // restore the user context if it was modified
+ if (!is_bool($previousUserContext)) {
$this->ravenClient->user_context($previousUserContext);
}
}
@@ -194,7 +196,7 @@ class RavenHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter('[%channel%] %message%');
}
@@ -216,11 +218,11 @@ class RavenHandler extends AbstractProcessingHandler
*/
protected function getExtraParameters()
{
- return array('checksum', 'release', 'event_id');
+ return ['checksum', 'release', 'event_id'];
}
/**
- * @param string $value
+ * @param string $value
* @return self
*/
public function setRelease($value)
diff --git a/src/Monolog/Handler/RedisHandler.php b/src/Monolog/Handler/RedisHandler.php
index 590f996..e7ddb44 100644
--- a/src/Monolog/Handler/RedisHandler.php
+++ b/src/Monolog/Handler/RedisHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
@@ -36,9 +37,9 @@ class RedisHandler extends AbstractProcessingHandler
* @param string $key The key name to push records to
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param int $capSize Number of entries to limit list size to
+ * @param int $capSize Number of entries to limit list size to, 0 = unlimited
*/
- public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true, $capSize = false)
+ public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0)
{
if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) {
throw new \InvalidArgumentException('Predis\Client or Redis instance required');
@@ -90,7 +91,7 @@ class RedisHandler extends AbstractProcessingHandler
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter();
}
diff --git a/src/Monolog/Handler/RollbarHandler.php b/src/Monolog/Handler/RollbarHandler.php
index 6c8a3e3..5b6678e 100644
--- a/src/Monolog/Handler/RollbarHandler.php
+++ b/src/Monolog/Handler/RollbarHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -12,7 +12,7 @@
namespace Monolog\Handler;
use RollbarNotifier;
-use Exception;
+use Throwable;
use Monolog\Logger;
/**
@@ -40,7 +40,7 @@ class RollbarHandler extends AbstractProcessingHandler
*/
protected $rollbarNotifier;
- protected $levelMap = array(
+ protected $levelMap = [
Logger::DEBUG => 'debug',
Logger::INFO => 'info',
Logger::NOTICE => 'info',
@@ -49,7 +49,7 @@ class RollbarHandler extends AbstractProcessingHandler
Logger::CRITICAL => 'critical',
Logger::ALERT => 'critical',
Logger::EMERGENCY => 'critical',
- );
+ ];
/**
* Records whether any log records have been added since the last flush of the rollbar notifier
@@ -84,19 +84,19 @@ class RollbarHandler extends AbstractProcessingHandler
}
$context = $record['context'];
- $payload = array();
+ $payload = [];
if (isset($context['payload'])) {
$payload = $context['payload'];
unset($context['payload']);
}
- $context = array_merge($context, $record['extra'], array(
+ $context = array_merge($context, $record['extra'], [
'level' => $this->levelMap[$record['level']],
'monolog_level' => $record['level_name'],
'channel' => $record['channel'],
'datetime' => $record['datetime']->format('U'),
- ));
+ ]);
- if (isset($context['exception']) && $context['exception'] instanceof Exception) {
+ if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
$payload['level'] = $context['level'];
$exception = $context['exception'];
unset($context['exception']);
diff --git a/src/Monolog/Handler/RotatingFileHandler.php b/src/Monolog/Handler/RotatingFileHandler.php
index 3b60b3d..a4a5ba4 100644
--- a/src/Monolog/Handler/RotatingFileHandler.php
+++ b/src/Monolog/Handler/RotatingFileHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,6 +11,7 @@
namespace Monolog\Handler;
+use InvalidArgumentException;
use Monolog\Logger;
/**
@@ -47,7 +48,7 @@ class RotatingFileHandler extends StreamHandler
{
$this->filename = $filename;
$this->maxFiles = (int) $maxFiles;
- $this->nextRotation = new \DateTime('tomorrow');
+ $this->nextRotation = new \DateTimeImmutable('tomorrow');
$this->filenameFormat = '{filename}-{date}';
$this->dateFormat = 'Y-m-d';
@@ -69,18 +70,16 @@ class RotatingFileHandler extends StreamHandler
public function setFilenameFormat($filenameFormat, $dateFormat)
{
if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
- trigger_error(
+ throw new InvalidArgumentException(
'Invalid date format - format must be one of '.
'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '.
'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '.
- 'date formats using slashes, underscores and/or dots instead of dashes.',
- E_USER_DEPRECATED
+ 'date formats using slashes, underscores and/or dots instead of dashes.'
);
}
if (substr_count($filenameFormat, '{date}') === 0) {
- trigger_error(
- 'Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.',
- E_USER_DEPRECATED
+ throw new InvalidArgumentException(
+ 'Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.'
);
}
$this->filenameFormat = $filenameFormat;
@@ -114,7 +113,7 @@ class RotatingFileHandler extends StreamHandler
{
// update filename
$this->url = $this->getTimedFilename();
- $this->nextRotation = new \DateTime('tomorrow');
+ $this->nextRotation = new \DateTimeImmutable('tomorrow');
// skip GC of old logs if files are unlimited
if (0 === $this->maxFiles) {
@@ -136,7 +135,8 @@ class RotatingFileHandler extends StreamHandler
if (is_writable($file)) {
// suppress errors here as unlink() might fail if two processes
// are cleaning up/rotating at the same time
- set_error_handler(function ($errno, $errstr, $errfile, $errline) {});
+ set_error_handler(function ($errno, $errstr, $errfile, $errline) {
+ });
unlink($file);
restore_error_handler();
}
@@ -149,8 +149,8 @@ class RotatingFileHandler extends StreamHandler
{
$fileInfo = pathinfo($this->filename);
$timedFilename = str_replace(
- array('{filename}', '{date}'),
- array($fileInfo['filename'], date($this->dateFormat)),
+ ['{filename}', '{date}'],
+ [$fileInfo['filename'], date($this->dateFormat)],
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
@@ -165,8 +165,8 @@ class RotatingFileHandler extends StreamHandler
{
$fileInfo = pathinfo($this->filename);
$glob = str_replace(
- array('{filename}', '{date}'),
- array($fileInfo['filename'], '*'),
+ ['{filename}', '{date}'],
+ [$fileInfo['filename'], '*'],
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
if (!empty($fileInfo['extension'])) {
diff --git a/src/Monolog/Handler/SamplingHandler.php b/src/Monolog/Handler/SamplingHandler.php
index 9509ae3..8a25cbb 100644
--- a/src/Monolog/Handler/SamplingHandler.php
+++ b/src/Monolog/Handler/SamplingHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -25,8 +25,10 @@ namespace Monolog\Handler;
* @author Bryan Davis <bd808@wikimedia.org>
* @author Kunal Mehta <legoktm@gmail.com>
*/
-class SamplingHandler extends AbstractHandler
+class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface
{
+ use ProcessableHandlerTrait;
+
/**
* @var callable|HandlerInterface $handler
*/
@@ -52,12 +54,12 @@ class SamplingHandler extends AbstractHandler
}
}
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
return $this->handler->isHandling($record);
}
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
// The same logic as in FingersCrossedHandler
@@ -69,9 +71,7 @@ class SamplingHandler extends AbstractHandler
}
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ $record = $this->processRecord($record);
}
$this->handler->handle($record);
diff --git a/src/Monolog/Handler/SendGridHandler.php b/src/Monolog/Handler/SendGridHandler.php
new file mode 100644
index 0000000..7d82d94
--- /dev/null
+++ b/src/Monolog/Handler/SendGridHandler.php
@@ -0,0 +1,100 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+
+/**
+ * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html
+ *
+ * @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com>
+ */
+class SendGridHandler extends MailHandler
+{
+ /**
+ * The SendGrid API User
+ * @var string
+ */
+ protected $apiUser;
+
+ /**
+ * The SendGrid API Key
+ * @var string
+ */
+ protected $apiKey;
+
+ /**
+ * The email addresses to which the message will be sent
+ * @var string
+ */
+ protected $from;
+
+ /**
+ * The email addresses to which the message will be sent
+ * @var array
+ */
+ protected $to;
+
+ /**
+ * The subject of the email
+ * @var string
+ */
+ protected $subject;
+
+ /**
+ * @param string $apiUser The SendGrid API User
+ * @param string $apiKey The SendGrid API Key
+ * @param string $from The sender of the email
+ * @param string|array $to The recipients of the email
+ * @param string $subject The subject of the mail
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ */
+ public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, int $level = Logger::ERROR, bool $bubble = true)
+ {
+ parent::__construct($level, $bubble);
+ $this->apiUser = $apiUser;
+ $this->apiKey = $apiKey;
+ $this->from = $from;
+ $this->to = (array) $to;
+ $this->subject = $subject;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function send(string $content, array $records)
+ {
+ $message = [];
+ $message['api_user'] = $this->apiUser;
+ $message['api_key'] = $this->apiKey;
+ $message['from'] = $this->from;
+ foreach ($this->to as $recipient) {
+ $message['to[]'] = $recipient;
+ }
+ $message['subject'] = $this->subject;
+ $message['date'] = date('r');
+
+ if ($this->isHtmlBody($content)) {
+ $message['html'] = $content;
+ } else {
+ $message['text'] = $content;
+ }
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json');
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message));
+ Curl\Util::execute($ch, 2);
+ }
+}
diff --git a/src/Monolog/Handler/Slack/SlackRecord.php b/src/Monolog/Handler/Slack/SlackRecord.php
index 38bc838..d9e6a4c 100644
--- a/src/Monolog/Handler/Slack/SlackRecord.php
+++ b/src/Monolog/Handler/Slack/SlackRecord.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -89,7 +89,7 @@ class SlackRecord
{
$this->channel = $channel;
$this->username = $username;
- $this->userIcon = trim($userIcon, ':');
+ $this->userIcon = $userIcon !== null ? trim($userIcon, ':') : null;
$this->useAttachment = $useAttachment;
$this->useShortAttachment = $useShortAttachment;
$this->includeContextAndExtra = $includeContextAndExtra;
@@ -127,7 +127,7 @@ class SlackRecord
'color' => $this->getAttachmentColor($record['level']),
'fields' => array(),
'mrkdwn_in' => array('fields'),
- 'ts' => $record['datetime']->getTimestamp()
+ 'ts' => $record['datetime']->getTimestamp(),
);
if ($this->useShortAttachment) {
@@ -137,7 +137,6 @@ class SlackRecord
$attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']);
}
-
if ($this->includeContextAndExtra) {
foreach (array('extra', 'context') as $key) {
if (empty($record[$key])) {
@@ -229,7 +228,7 @@ class SlackRecord
/**
* Generates attachment field
*
- * @param string $title
+ * @param string $title
* @param string|array $value\
*
* @return array
@@ -243,7 +242,7 @@ class SlackRecord
return array(
'title' => $title,
'value' => $value,
- 'short' => false
+ 'short' => false,
);
}
diff --git a/src/Monolog/Handler/SlackHandler.php b/src/Monolog/Handler/SlackHandler.php
index 3ac4d83..a99872f 100644
--- a/src/Monolog/Handler/SlackHandler.php
+++ b/src/Monolog/Handler/SlackHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -197,7 +197,7 @@ class SlackHandler extends SocketHandler
return $this->slackRecord->stringify($fields);
}
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
parent::setFormatter($formatter);
$this->slackRecord->setFormatter($formatter);
@@ -205,7 +205,7 @@ class SlackHandler extends SocketHandler
return $this;
}
- public function getFormatter()
+ public function getFormatter(): FormatterInterface
{
$formatter = parent::getFormatter();
$this->slackRecord->setFormatter($formatter);
diff --git a/src/Monolog/Handler/SlackWebhookHandler.php b/src/Monolog/Handler/SlackWebhookHandler.php
index 9a1bbb4..a2ea52a 100644
--- a/src/Monolog/Handler/SlackWebhookHandler.php
+++ b/src/Monolog/Handler/SlackWebhookHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -36,16 +36,16 @@ class SlackWebhookHandler extends AbstractProcessingHandler
private $slackRecord;
/**
- * @param string $webhookUrl Slack Webhook URL
- * @param string|null $channel Slack channel (encoded ID or name)
- * @param string|null $username Name of a bot
- * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
- * @param string|null $iconEmoji The emoji name to use (or null)
- * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
- * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
+ * @param string $webhookUrl Slack Webhook URL
+ * @param string|null $channel Slack channel (encoded ID or name)
+ * @param string|null $username Name of a bot
+ * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
+ * @param string|null $iconEmoji The emoji name to use (or null)
+ * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
+ * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
*/
public function __construct($webhookUrl, $channel = null, $username = null, $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeContextAndExtra = false, $level = Logger::CRITICAL, $bubble = true, array $excludeFields = array())
{
@@ -97,7 +97,7 @@ class SlackWebhookHandler extends AbstractProcessingHandler
Curl\Util::execute($ch);
}
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
parent::setFormatter($formatter);
$this->slackRecord->setFormatter($formatter);
@@ -105,7 +105,7 @@ class SlackWebhookHandler extends AbstractProcessingHandler
return $this;
}
- public function getFormatter()
+ public function getFormatter(): FormatterInterface
{
$formatter = parent::getFormatter();
$this->slackRecord->setFormatter($formatter);
diff --git a/src/Monolog/Handler/SlackbotHandler.php b/src/Monolog/Handler/SlackbotHandler.php
index baead52..dd2db59 100644
--- a/src/Monolog/Handler/SlackbotHandler.php
+++ b/src/Monolog/Handler/SlackbotHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -40,11 +40,11 @@ class SlackbotHandler extends AbstractProcessingHandler
private $channel;
/**
- * @param string $slackTeam Slack team slug
- * @param string $token Slackbot token
- * @param string $channel Slack channel (encoded ID or name)
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param string $slackTeam Slack team slug
+ * @param string $token Slackbot token
+ * @param string $channel Slack channel (encoded ID or name)
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($slackTeam, $token, $channel, $level = Logger::CRITICAL, $bubble = true)
{
diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php
index 7a61bf4..e2161ff 100644
--- a/src/Monolog/Handler/SocketHandler.php
+++ b/src/Monolog/Handler/SocketHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -23,8 +23,11 @@ class SocketHandler extends AbstractProcessingHandler
{
private $connectionString;
private $connectionTimeout;
+ /** @var resource|null */
private $resource;
+ /** @var float */
private $timeout = 0;
+ /** @var float */
private $writingTimeout = 10;
private $lastSentBytes = null;
private $persistent = false;
@@ -149,20 +152,16 @@ class SocketHandler extends AbstractProcessingHandler
/**
* Get current connection timeout setting
- *
- * @return float
*/
- public function getConnectionTimeout()
+ public function getConnectionTimeout(): float
{
return $this->connectionTimeout;
}
/**
* Get current in-transfer timeout
- *
- * @return float
*/
- public function getTimeout()
+ public function getTimeout(): float
{
return $this->timeout;
}
@@ -172,7 +171,7 @@ class SocketHandler extends AbstractProcessingHandler
*
* @return float
*/
- public function getWritingTimeout()
+ public function getWritingTimeout(): float
{
return $this->writingTimeout;
}
@@ -216,7 +215,7 @@ class SocketHandler extends AbstractProcessingHandler
$seconds = floor($this->timeout);
$microseconds = round(($this->timeout - $seconds) * 1e6);
- return stream_set_timeout($this->resource, $seconds, $microseconds);
+ return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
}
/**
diff --git a/src/Monolog/Handler/SqsHandler.php b/src/Monolog/Handler/SqsHandler.php
new file mode 100644
index 0000000..01c70dc
--- /dev/null
+++ b/src/Monolog/Handler/SqsHandler.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Aws\Sqs\SqsClient;
+use Monolog\Logger;
+
+/**
+ * Writes to any sqs queue.
+ *
+ * @author Martijn van Calker <git@amvc.nl>
+ */
+class SqsHandler extends AbstractProcessingHandler
+{
+ /** @var SqsClient */
+ private $client;
+ /** @var string */
+ private $queueUrl;
+
+ public function __construct(SqsClient $sqsClient, $queueUrl, $level = Logger::DEBUG, $bubble = true)
+ {
+ parent::__construct($level, $bubble);
+
+ $this->client = $sqsClient;
+ $this->queueUrl = $queueUrl;
+ }
+
+ /**
+ * Writes the record down to the log of the implementing handler.
+ *
+ * @param array $record
+ */
+ protected function write(array $record)
+ {
+ if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) {
+ throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string');
+ }
+
+ $this->client->sendMessage([
+ 'QueueUrl' => $this->queueUrl,
+ 'MessageBody' => $record['formatted'],
+ ]);
+ }
+}
diff --git a/src/Monolog/Handler/StreamHandler.php b/src/Monolog/Handler/StreamHandler.php
index 09a1573..5abbc59 100644
--- a/src/Monolog/Handler/StreamHandler.php
+++ b/src/Monolog/Handler/StreamHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -22,8 +22,10 @@ use Monolog\Logger;
*/
class StreamHandler extends AbstractProcessingHandler
{
+ /** @var resource|null */
protected $stream;
protected $url;
+ /** @var string|null */
private $errorMessage;
protected $filePermission;
protected $useLocking;
@@ -96,7 +98,7 @@ class StreamHandler extends AbstractProcessingHandler
}
$this->createDir();
$this->errorMessage = null;
- set_error_handler(array($this, 'customErrorHandler'));
+ set_error_handler([$this, 'customErrorHandler']);
$this->stream = fopen($this->url, 'a');
if ($this->filePermission !== null) {
@chmod($this->url, $this->filePermission);
@@ -123,7 +125,7 @@ class StreamHandler extends AbstractProcessingHandler
/**
* Write to stream
* @param resource $stream
- * @param array $record
+ * @param array $record
*/
protected function streamWrite($stream, array $record)
{
@@ -164,7 +166,7 @@ class StreamHandler extends AbstractProcessingHandler
$dir = $this->getDirFromStream($this->url);
if (null !== $dir && !is_dir($dir)) {
$this->errorMessage = null;
- set_error_handler(array($this, 'customErrorHandler'));
+ set_error_handler([$this, 'customErrorHandler']);
$status = mkdir($dir, 0777, true);
restore_error_handler();
if (false === $status) {
diff --git a/src/Monolog/Handler/SwiftMailerHandler.php b/src/Monolog/Handler/SwiftMailerHandler.php
index 72f44a5..3359ac8 100644
--- a/src/Monolog/Handler/SwiftMailerHandler.php
+++ b/src/Monolog/Handler/SwiftMailerHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
+use Swift_Message;
use Swift;
/**
@@ -26,12 +27,12 @@ class SwiftMailerHandler extends MailHandler
private $messageTemplate;
/**
- * @param \Swift_Mailer $mailer The mailer to use
- * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param \Swift_Mailer $mailer The mailer to use
+ * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
+ * @param int|string $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
- public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true)
+ public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true)
{
parent::__construct($level, $bubble);
@@ -42,7 +43,7 @@ class SwiftMailerHandler extends MailHandler
/**
* {@inheritdoc}
*/
- protected function send($content, array $records)
+ protected function send(string $content, array $records)
{
$this->mailer->send($this->buildMessage($content, $records));
}
@@ -50,21 +51,21 @@ class SwiftMailerHandler extends MailHandler
/**
* Creates instance of Swift_Message to be sent
*
- * @param string $content formatted email body to be sent
- * @param array $records Log records that formed the content
- * @return \Swift_Message
+ * @param string $content formatted email body to be sent
+ * @param array $records Log records that formed the content
+ * @return Swift_Message
*/
- protected function buildMessage($content, array $records)
+ protected function buildMessage(string $content, array $records): Swift_Message
{
$message = null;
- if ($this->messageTemplate instanceof \Swift_Message) {
+ if ($this->messageTemplate instanceof Swift_Message) {
$message = clone $this->messageTemplate;
$message->generateId();
} elseif (is_callable($this->messageTemplate)) {
$message = call_user_func($this->messageTemplate, $content, $records);
}
- if (!$message instanceof \Swift_Message) {
+ if (!$message instanceof Swift_Message) {
throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it');
}
@@ -73,7 +74,12 @@ class SwiftMailerHandler extends MailHandler
$message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
}
- $message->setBody($content);
+ $mime = null;
+ if ($this->isHtmlBody($content)) {
+ $mime = 'text/html';
+ }
+
+ $message->setBody($content, $mime);
if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
$message->setDate(new \DateTimeImmutable());
} else {
@@ -82,18 +88,4 @@ class SwiftMailerHandler extends MailHandler
return $message;
}
-
- /**
- * BC getter, to be removed in 2.0
- */
- public function __get($name)
- {
- if ($name === 'message') {
- trigger_error('SwiftMailerHandler->message is deprecated, use ->buildMessage() instead to retrieve the message', E_USER_DEPRECATED);
-
- return $this->buildMessage(null, array());
- }
-
- throw new \InvalidArgumentException('Invalid property '.$name);
- }
}
diff --git a/src/Monolog/Handler/SyslogHandler.php b/src/Monolog/Handler/SyslogHandler.php
index 376bc3b..863fc56 100644
--- a/src/Monolog/Handler/SyslogHandler.php
+++ b/src/Monolog/Handler/SyslogHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
diff --git a/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/src/Monolog/Handler/SyslogUdp/UdpSocket.php
index 3bff085..f1801b3 100644
--- a/src/Monolog/Handler/SyslogUdp/UdpSocket.php
+++ b/src/Monolog/Handler/SyslogUdp/UdpSocket.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -17,6 +17,8 @@ class UdpSocket
protected $ip;
protected $port;
+
+ /** @var resource|null */
protected $socket;
public function __construct($ip, $port = 514)
@@ -42,7 +44,7 @@ class UdpSocket
protected function send($chunk)
{
if (!is_resource($this->socket)) {
- throw new \LogicException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore');
+ throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore');
}
socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
}
diff --git a/src/Monolog/Handler/SyslogUdpHandler.php b/src/Monolog/Handler/SyslogUdpHandler.php
index 4718711..2258f56 100644
--- a/src/Monolog/Handler/SyslogUdpHandler.php
+++ b/src/Monolog/Handler/SyslogUdpHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -57,19 +57,19 @@ class SyslogUdpHandler extends AbstractSyslogHandler
$this->socket->close();
}
- private function splitMessageIntoLines($message)
+ private function splitMessageIntoLines($message): array
{
if (is_array($message)) {
$message = implode("\n", $message);
}
- return preg_split('/$\R?^/m', $message, -1, PREG_SPLIT_NO_EMPTY);
+ return preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
}
/**
* Make common syslog header (see rfc5424)
*/
- protected function makeCommonSyslogHeader($severity)
+ protected function makeCommonSyslogHeader($severity): string
{
$priority = $severity + $this->facility;
@@ -96,7 +96,7 @@ class SyslogUdpHandler extends AbstractSyslogHandler
/**
* Inject your own socket, mainly used for testing
*/
- public function setSocket($socket)
+ public function setSocket(UdpSocket $socket)
{
$this->socket = $socket;
}
diff --git a/src/Monolog/Handler/TestHandler.php b/src/Monolog/Handler/TestHandler.php
index e39cfc6..3df7b6d 100644
--- a/src/Monolog/Handler/TestHandler.php
+++ b/src/Monolog/Handler/TestHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -65,8 +65,8 @@ namespace Monolog\Handler;
*/
class TestHandler extends AbstractProcessingHandler
{
- protected $records = array();
- protected $recordsByLevel = array();
+ protected $records = [];
+ protected $recordsByLevel = [];
public function getRecords()
{
@@ -75,8 +75,8 @@ class TestHandler extends AbstractProcessingHandler
public function clear()
{
- $this->records = array();
- $this->recordsByLevel = array();
+ $this->records = [];
+ $this->recordsByLevel = [];
}
public function hasRecords($level)
@@ -109,12 +109,8 @@ class TestHandler extends AbstractProcessingHandler
}, $level);
}
- public function hasRecordThatPasses($predicate, $level)
+ public function hasRecordThatPasses(callable $predicate, $level)
{
- if (!is_callable($predicate)) {
- throw new \InvalidArgumentException("Expected a callable for hasRecordThatSucceeds");
- }
-
if (!isset($this->recordsByLevel[$level])) {
return false;
}
@@ -145,7 +141,7 @@ class TestHandler extends AbstractProcessingHandler
if (method_exists($this, $genericMethod)) {
$args[] = $level;
- return call_user_func_array(array($this, $genericMethod), $args);
+ return call_user_func_array([$this, $genericMethod], $args);
}
}
diff --git a/src/Monolog/Handler/WhatFailureGroupHandler.php b/src/Monolog/Handler/WhatFailureGroupHandler.php
index 2732ba3..42c2336 100644
--- a/src/Monolog/Handler/WhatFailureGroupHandler.php
+++ b/src/Monolog/Handler/WhatFailureGroupHandler.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -22,7 +22,7 @@ class WhatFailureGroupHandler extends GroupHandler
/**
* {@inheritdoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->processors) {
foreach ($this->processors as $processor) {
@@ -33,8 +33,6 @@ class WhatFailureGroupHandler extends GroupHandler
foreach ($this->handlers as $handler) {
try {
$handler->handle($record);
- } catch (\Exception $e) {
- // What failure?
} catch (\Throwable $e) {
// What failure?
}
@@ -51,8 +49,6 @@ class WhatFailureGroupHandler extends GroupHandler
foreach ($this->handlers as $handler) {
try {
$handler->handleBatch($records);
- } catch (\Exception $e) {
- // What failure?
} catch (\Throwable $e) {
// What failure?
}
diff --git a/src/Monolog/Handler/ZendMonitorHandler.php b/src/Monolog/Handler/ZendMonitorHandler.php
index f22cf21..c0bceb4 100644
--- a/src/Monolog/Handler/ZendMonitorHandler.php
+++ b/src/Monolog/Handler/ZendMonitorHandler.php
@@ -1,4 +1,5 @@
-<?php
+<?php declare(strict_types=1);
+
/*
* This file is part of the Monolog package.
*
@@ -10,6 +11,7 @@
namespace Monolog\Handler;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Logger;
@@ -25,7 +27,7 @@ class ZendMonitorHandler extends AbstractProcessingHandler
*
* @var array
*/
- protected $levelMap = array(
+ protected $levelMap = [
Logger::DEBUG => 1,
Logger::INFO => 2,
Logger::NOTICE => 3,
@@ -34,7 +36,7 @@ class ZendMonitorHandler extends AbstractProcessingHandler
Logger::CRITICAL => 6,
Logger::ALERT => 7,
Logger::EMERGENCY => 0,
- );
+ ];
/**
* Construct
@@ -78,7 +80,7 @@ class ZendMonitorHandler extends AbstractProcessingHandler
/**
* {@inheritdoc}
*/
- public function getDefaultFormatter()
+ public function getDefaultFormatter(): FormatterInterface
{
return new NormalizerFormatter();
}
diff --git a/src/Monolog/Logger.php b/src/Monolog/Logger.php
index 49d00af..88ecf0d 100644
--- a/src/Monolog/Logger.php
+++ b/src/Monolog/Logger.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -11,8 +11,8 @@
namespace Monolog;
+use DateTimeZone;
use Monolog\Handler\HandlerInterface;
-use Monolog\Handler\StreamHandler;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
@@ -84,14 +84,16 @@ class Logger implements LoggerInterface
*
* @var int
*/
- const API = 1;
+ const API = 2;
/**
* Logging levels from syslog protocol defined in RFC 5424
*
- * @var array $levels Logging levels
+ * This is a static variable and not a constant to serve as an extension point for custom levels
+ *
+ * @var string[] $levels Logging levels with the levels as key
*/
- protected static $levels = array(
+ protected static $levels = [
self::DEBUG => 'DEBUG',
self::INFO => 'INFO',
self::NOTICE => 'NOTICE',
@@ -100,12 +102,7 @@ class Logger implements LoggerInterface
self::CRITICAL => 'CRITICAL',
self::ALERT => 'ALERT',
self::EMERGENCY => 'EMERGENCY',
- );
-
- /**
- * @var \DateTimeZone
- */
- protected static $timezone;
+ ];
/**
* @var string
@@ -134,31 +131,33 @@ class Logger implements LoggerInterface
protected $microsecondTimestamps = true;
/**
- * @param string $name The logging channel
+ * @var DateTimeZone
+ */
+ protected $timezone;
+
+ /**
+ * @param string $name The logging channel, a simple descriptive name that is attached to all log records
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
* @param callable[] $processors Optional array of processors
+ * @param DateTimeZone $timezone Optional timezone, if not provided date_default_timezone_get() will be used
*/
- public function __construct($name, array $handlers = array(), array $processors = array())
+ public function __construct(string $name, array $handlers = [], array $processors = [], DateTimeZone $timezone = null)
{
$this->name = $name;
$this->handlers = $handlers;
$this->processors = $processors;
+ $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
}
- /**
- * @return string
- */
- public function getName()
+ public function getName(): string
{
return $this->name;
}
/**
* Return a new cloned instance with the name changed
- *
- * @return static
*/
- public function withName($name)
+ public function withName(string $name): self
{
$new = clone $this;
$new->name = $name;
@@ -168,11 +167,8 @@ class Logger implements LoggerInterface
/**
* Pushes a handler on to the stack.
- *
- * @param HandlerInterface $handler
- * @return $this
*/
- public function pushHandler(HandlerInterface $handler)
+ public function pushHandler(HandlerInterface $handler): self
{
array_unshift($this->handlers, $handler);
@@ -182,9 +178,9 @@ class Logger implements LoggerInterface
/**
* Pops a handler from the stack
*
- * @return HandlerInterface
+ * @throws \LogicException If empty handler stack
*/
- public function popHandler()
+ public function popHandler(): HandlerInterface
{
if (!$this->handlers) {
throw new \LogicException('You tried to pop from an empty handler stack.');
@@ -198,12 +194,11 @@ class Logger implements LoggerInterface
*
* If a map is passed, keys will be ignored.
*
- * @param HandlerInterface[] $handlers
- * @return $this
+ * @param HandlerInterface[] $handlers
*/
- public function setHandlers(array $handlers)
+ public function setHandlers(array $handlers): self
{
- $this->handlers = array();
+ $this->handlers = [];
foreach (array_reverse($handlers) as $handler) {
$this->pushHandler($handler);
}
@@ -214,22 +209,16 @@ class Logger implements LoggerInterface
/**
* @return HandlerInterface[]
*/
- public function getHandlers()
+ public function getHandlers(): array
{
return $this->handlers;
}
/**
* Adds a processor on to the stack.
- *
- * @param callable $callback
- * @return $this
*/
- public function pushProcessor($callback)
+ public function pushProcessor(callable $callback): self
{
- if (!is_callable($callback)) {
- throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
- }
array_unshift($this->processors, $callback);
return $this;
@@ -238,9 +227,10 @@ class Logger implements LoggerInterface
/**
* Removes the processor on top of the stack and returns it.
*
+ * @throws \LogicException If empty processor stack
* @return callable
*/
- public function popProcessor()
+ public function popProcessor(): callable
{
if (!$this->processors) {
throw new \LogicException('You tried to pop from an empty processor stack.');
@@ -252,7 +242,7 @@ class Logger implements LoggerInterface
/**
* @return callable[]
*/
- public function getProcessors()
+ public function getProcessors(): array
{
return $this->processors;
}
@@ -261,18 +251,22 @@ class Logger implements LoggerInterface
* Control the use of microsecond resolution timestamps in the 'datetime'
* member of new records.
*
- * Generating microsecond resolution timestamps by calling
+ * On PHP7.0, generating microsecond resolution timestamps by calling
* microtime(true), formatting the result via sprintf() and then parsing
* the resulting string via \DateTime::createFromFormat() can incur
* a measurable runtime overhead vs simple usage of DateTime to capture
* a second resolution timestamp in systems which generate a large number
* of log events.
*
+ * On PHP7.1 however microseconds are always included by the engine, so
+ * this setting can be left alone unless you really want to suppress
+ * microseconds in the output.
+ *
* @param bool $micro True to use microtime() to create timestamps
*/
- public function useMicrosecondTimestamps($micro)
+ public function useMicrosecondTimestamps(bool $micro)
{
- $this->microsecondTimestamps = (bool) $micro;
+ $this->microsecondTimestamps = $micro;
}
/**
@@ -283,56 +277,43 @@ class Logger implements LoggerInterface
* @param array $context The log context
* @return Boolean Whether the record has been processed
*/
- public function addRecord($level, $message, array $context = array())
+ public function addRecord(int $level, string $message, array $context = []): bool
{
- if (!$this->handlers) {
- $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
- }
-
- $levelName = static::getLevelName($level);
-
// check if any handler will handle this message so we can return early and save cycles
$handlerKey = null;
- reset($this->handlers);
- while ($handler = current($this->handlers)) {
- if ($handler->isHandling(array('level' => $level))) {
- $handlerKey = key($this->handlers);
+ foreach ($this->handlers as $key => $handler) {
+ if ($handler->isHandling(['level' => $level])) {
+ $handlerKey = $key;
break;
}
-
- next($this->handlers);
}
if (null === $handlerKey) {
return false;
}
- if (!static::$timezone) {
- static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC');
- }
-
- // php7.1+ always has microseconds enabled, so we do not need this hack
- if ($this->microsecondTimestamps && PHP_VERSION_ID < 70100) {
- $ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone);
- } else {
- $ts = new \DateTime(null, static::$timezone);
- }
- $ts->setTimezone(static::$timezone);
+ $levelName = static::getLevelName($level);
- $record = array(
- 'message' => (string) $message,
+ $record = [
+ 'message' => $message,
'context' => $context,
'level' => $level,
'level_name' => $levelName,
'channel' => $this->name,
- 'datetime' => $ts,
- 'extra' => array(),
- );
+ 'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
+ 'extra' => [],
+ ];
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
+ // advance the array pointer to the first handler that will handle this record
+ reset($this->handlers);
+ while ($handlerKey !== key($this->handlers)) {
+ next($this->handlers);
+ }
+
while ($handler = current($this->handlers)) {
if (true === $handler->handle($record)) {
break;
@@ -345,107 +326,11 @@ class Logger implements LoggerInterface
}
/**
- * Adds a log record at the DEBUG level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addDebug($message, array $context = array())
- {
- return $this->addRecord(static::DEBUG, $message, $context);
- }
-
- /**
- * Adds a log record at the INFO level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addInfo($message, array $context = array())
- {
- return $this->addRecord(static::INFO, $message, $context);
- }
-
- /**
- * Adds a log record at the NOTICE level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addNotice($message, array $context = array())
- {
- return $this->addRecord(static::NOTICE, $message, $context);
- }
-
- /**
- * Adds a log record at the WARNING level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addWarning($message, array $context = array())
- {
- return $this->addRecord(static::WARNING, $message, $context);
- }
-
- /**
- * Adds a log record at the ERROR level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addError($message, array $context = array())
- {
- return $this->addRecord(static::ERROR, $message, $context);
- }
-
- /**
- * Adds a log record at the CRITICAL level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addCritical($message, array $context = array())
- {
- return $this->addRecord(static::CRITICAL, $message, $context);
- }
-
- /**
- * Adds a log record at the ALERT level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addAlert($message, array $context = array())
- {
- return $this->addRecord(static::ALERT, $message, $context);
- }
-
- /**
- * Adds a log record at the EMERGENCY level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function addEmergency($message, array $context = array())
- {
- return $this->addRecord(static::EMERGENCY, $message, $context);
- }
-
- /**
* Gets all supported logging levels.
*
* @return array Assoc array with human-readable level names => level codes.
*/
- public static function getLevels()
+ public static function getLevels(): array
{
return array_flip(static::$levels);
}
@@ -453,10 +338,11 @@ class Logger implements LoggerInterface
/**
* Gets the name of the logging level.
*
- * @param int $level
+ * @param int $level
+ * @throws \Psr\Log\InvalidArgumentException If level is not defined
* @return string
*/
- public static function getLevelName($level)
+ public static function getLevelName(int $level): string
{
if (!isset(static::$levels[$level])) {
throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
@@ -469,12 +355,17 @@ class Logger implements LoggerInterface
* Converts PSR-3 levels to Monolog ones if necessary
*
* @param string|int Level number (monolog) or name (PSR-3)
+ * @throws \Psr\Log\InvalidArgumentException If level is not defined
* @return int
*/
- public static function toMonologLevel($level)
+ public static function toMonologLevel($level): int
{
- if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) {
- return constant(__CLASS__.'::'.strtoupper($level));
+ if (is_string($level)) {
+ if (defined(__CLASS__.'::'.strtoupper($level))) {
+ return constant(__CLASS__.'::'.strtoupper($level));
+ }
+
+ throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
}
return $level;
@@ -486,11 +377,11 @@ class Logger implements LoggerInterface
* @param int $level
* @return Boolean
*/
- public function isHandling($level)
+ public function isHandling(int $level): bool
{
- $record = array(
+ $record = [
'level' => $level,
- );
+ ];
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
@@ -506,16 +397,15 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param mixed $level The log level
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param mixed $level The log level
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function log($level, $message, array $context = array())
+ public function log($level, $message, array $context = [])
{
$level = static::toMonologLevel($level);
- return $this->addRecord($level, $message, $context);
+ $this->addRecord($level, (string) $message, $context);
}
/**
@@ -523,13 +413,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function debug($message, array $context = array())
+ public function debug($message, array $context = [])
{
- return $this->addRecord(static::DEBUG, $message, $context);
+ $this->addRecord(static::DEBUG, (string) $message, $context);
}
/**
@@ -537,13 +426,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function info($message, array $context = array())
+ public function info($message, array $context = [])
{
- return $this->addRecord(static::INFO, $message, $context);
+ $this->addRecord(static::INFO, (string) $message, $context);
}
/**
@@ -551,13 +439,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function notice($message, array $context = array())
+ public function notice($message, array $context = [])
{
- return $this->addRecord(static::NOTICE, $message, $context);
+ $this->addRecord(static::NOTICE, (string) $message, $context);
}
/**
@@ -565,41 +452,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function warn($message, array $context = array())
- {
- return $this->addRecord(static::WARNING, $message, $context);
- }
-
- /**
- * Adds a log record at the WARNING level.
- *
- * This method allows for compatibility with common interfaces.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function warning($message, array $context = array())
- {
- return $this->addRecord(static::WARNING, $message, $context);
- }
-
- /**
- * Adds a log record at the ERROR level.
- *
- * This method allows for compatibility with common interfaces.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function err($message, array $context = array())
+ public function warning($message, array $context = [])
{
- return $this->addRecord(static::ERROR, $message, $context);
+ $this->addRecord(static::WARNING, (string) $message, $context);
}
/**
@@ -607,13 +465,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function error($message, array $context = array())
+ public function error($message, array $context = [])
{
- return $this->addRecord(static::ERROR, $message, $context);
+ $this->addRecord(static::ERROR, (string) $message, $context);
}
/**
@@ -621,27 +478,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function crit($message, array $context = array())
+ public function critical($message, array $context = [])
{
- return $this->addRecord(static::CRITICAL, $message, $context);
- }
-
- /**
- * Adds a log record at the CRITICAL level.
- *
- * This method allows for compatibility with common interfaces.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
- */
- public function critical($message, array $context = array())
- {
- return $this->addRecord(static::CRITICAL, $message, $context);
+ $this->addRecord(static::CRITICAL, (string) $message, $context);
}
/**
@@ -649,13 +491,12 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function alert($message, array $context = array())
+ public function alert($message, array $context = [])
{
- return $this->addRecord(static::ALERT, $message, $context);
+ $this->addRecord(static::ALERT, (string) $message, $context);
}
/**
@@ -663,38 +504,33 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
*/
- public function emerg($message, array $context = array())
+ public function emergency($message, array $context = [])
{
- return $this->addRecord(static::EMERGENCY, $message, $context);
+ $this->addRecord(static::EMERGENCY, (string) $message, $context);
}
/**
- * Adds a log record at the EMERGENCY level.
- *
- * This method allows for compatibility with common interfaces.
+ * Set the timezone to be used for the timestamp of log records.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param DateTimeZone $tz Timezone object
*/
- public function emergency($message, array $context = array())
+ public function setTimezone(DateTimeZone $tz): self
{
- return $this->addRecord(static::EMERGENCY, $message, $context);
+ $this->timezone = $tz;
+
+ return $this;
}
/**
* Set the timezone to be used for the timestamp of log records.
*
- * This is stored globally for all Logger instances
- *
- * @param \DateTimeZone $tz Timezone object
+ * @return DateTimeZone
*/
- public static function setTimezone(\DateTimeZone $tz)
+ public function getTimezone(): DateTimeZone
{
- self::$timezone = $tz;
+ return $this->timezone;
}
}
diff --git a/src/Monolog/Processor/GitProcessor.php b/src/Monolog/Processor/GitProcessor.php
index 1899400..9eec186 100644
--- a/src/Monolog/Processor/GitProcessor.php
+++ b/src/Monolog/Processor/GitProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -29,11 +29,7 @@ class GitProcessor
$this->level = Logger::toMonologLevel($level);
}
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
@@ -45,7 +41,7 @@ class GitProcessor
return $record;
}
- private static function getGitInfo()
+ private static function getGitInfo(): array
{
if (self::$cache) {
return self::$cache;
@@ -53,12 +49,12 @@ class GitProcessor
$branches = `git branch -v --no-abbrev`;
if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
- return self::$cache = array(
+ return self::$cache = [
'branch' => $matches[1],
'commit' => $matches[2],
- );
+ ];
}
- return self::$cache = array();
+ return self::$cache = [];
}
}
diff --git a/src/Monolog/Processor/IntrospectionProcessor.php b/src/Monolog/Processor/IntrospectionProcessor.php
index 2c07cae..3a27529 100644
--- a/src/Monolog/Processor/IntrospectionProcessor.php
+++ b/src/Monolog/Processor/IntrospectionProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -32,23 +32,19 @@ class IntrospectionProcessor
private $skipStackFramesCount;
- private $skipFunctions = array(
+ private $skipFunctions = [
'call_user_func',
'call_user_func_array',
- );
+ ];
- public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array(), $skipStackFramesCount = 0)
+ public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
{
$this->level = Logger::toMonologLevel($level);
- $this->skipClassesPartials = array_merge(array('Monolog\\'), $skipClassesPartials);
+ $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials);
$this->skipStackFramesCount = $skipStackFramesCount;
}
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
@@ -90,18 +86,18 @@ class IntrospectionProcessor
// we should have the call source now
$record['extra'] = array_merge(
$record['extra'],
- array(
+ [
'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null,
'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null,
'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null,
'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null,
- )
+ ]
);
return $record;
}
- private function isTraceClassOrSkippedFunction(array $trace, $index)
+ private function isTraceClassOrSkippedFunction(array $trace, int $index)
{
if (!isset($trace[$index])) {
return false;
diff --git a/src/Monolog/Processor/MemoryPeakUsageProcessor.php b/src/Monolog/Processor/MemoryPeakUsageProcessor.php
index 0543e92..b6f8acc 100644
--- a/src/Monolog/Processor/MemoryPeakUsageProcessor.php
+++ b/src/Monolog/Processor/MemoryPeakUsageProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -19,11 +19,7 @@ namespace Monolog\Processor;
*/
class MemoryPeakUsageProcessor extends MemoryProcessor
{
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
$bytes = memory_get_peak_usage($this->realUsage);
$formatted = $this->formatBytes($bytes);
diff --git a/src/Monolog/Processor/MemoryProcessor.php b/src/Monolog/Processor/MemoryProcessor.php
index 85f9dc5..5b06c2e 100644
--- a/src/Monolog/Processor/MemoryProcessor.php
+++ b/src/Monolog/Processor/MemoryProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -32,22 +32,20 @@ abstract class MemoryProcessor
* @param bool $realUsage Set this to true to get the real size of memory allocated from system.
* @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size)
*/
- public function __construct($realUsage = true, $useFormatting = true)
+ public function __construct(bool $realUsage = true, bool $useFormatting = true)
{
- $this->realUsage = (boolean) $realUsage;
- $this->useFormatting = (boolean) $useFormatting;
+ $this->realUsage = $realUsage;
+ $this->useFormatting = $useFormatting;
}
/**
* Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is
*
* @param int $bytes
- * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as is
+ * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as int
*/
- protected function formatBytes($bytes)
+ protected function formatBytes(int $bytes)
{
- $bytes = (int) $bytes;
-
if (!$this->useFormatting) {
return $bytes;
}
diff --git a/src/Monolog/Processor/MemoryUsageProcessor.php b/src/Monolog/Processor/MemoryUsageProcessor.php
index 2783d65..31c9396 100644
--- a/src/Monolog/Processor/MemoryUsageProcessor.php
+++ b/src/Monolog/Processor/MemoryUsageProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -19,11 +19,7 @@ namespace Monolog\Processor;
*/
class MemoryUsageProcessor extends MemoryProcessor
{
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
$bytes = memory_get_usage($this->realUsage);
$formatted = $this->formatBytes($bytes);
diff --git a/src/Monolog/Processor/MercurialProcessor.php b/src/Monolog/Processor/MercurialProcessor.php
index 7c07a7e..6ab5bba 100644
--- a/src/Monolog/Processor/MercurialProcessor.php
+++ b/src/Monolog/Processor/MercurialProcessor.php
@@ -1,9 +1,9 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
*
- * (c) Jonathan A. Schweder <jonathanschweder@gmail.com>
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -28,11 +28,7 @@ class MercurialProcessor
$this->level = Logger::toMonologLevel($level);
}
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
@@ -44,20 +40,21 @@ class MercurialProcessor
return $record;
}
- private static function getMercurialInfo()
+ private static function getMercurialInfo(): array
{
if (self::$cache) {
return self::$cache;
}
$result = explode(' ', trim(`hg id -nb`));
+
if (count($result) >= 3) {
- return self::$cache = array(
+ return self::$cache = [
'branch' => $result[1],
'revision' => $result[2],
- );
+ ];
}
- return self::$cache = array();
+ return self::$cache = [];
}
}
diff --git a/src/Monolog/Processor/ProcessIdProcessor.php b/src/Monolog/Processor/ProcessIdProcessor.php
index 9d3f559..392bd13 100644
--- a/src/Monolog/Processor/ProcessIdProcessor.php
+++ b/src/Monolog/Processor/ProcessIdProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -18,11 +18,7 @@ namespace Monolog\Processor;
*/
class ProcessIdProcessor
{
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
$record['extra']['process_id'] = getmypid();
diff --git a/src/Monolog/Processor/PsrLogMessageProcessor.php b/src/Monolog/Processor/PsrLogMessageProcessor.php
index c2686ce..8078403 100644
--- a/src/Monolog/Processor/PsrLogMessageProcessor.php
+++ b/src/Monolog/Processor/PsrLogMessageProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -20,20 +20,34 @@ namespace Monolog\Processor;
*/
class PsrLogMessageProcessor
{
+ const SIMPLE_DATE = "Y-m-d\TH:i:sP";
+
+ private $dateFormat;
+
+ /**
+ * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
+ */
+ public function __construct(string $dateFormat = null)
+ {
+ $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
+ }
+
/**
* @param array $record
* @return array
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
if (false === strpos($record['message'], '{')) {
return $record;
}
- $replacements = array();
+ $replacements = [];
foreach ($record['context'] as $key => $val) {
if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
$replacements['{'.$key.'}'] = $val;
+ } elseif ($val instanceof \DateTimeInterface) {
+ $replacements['{'.$key.'}'] = $val->format($this->dateFormat);
} elseif (is_object($val)) {
$replacements['{'.$key.'}'] = '[object '.get_class($val).']';
} else {
diff --git a/src/Monolog/Processor/TagProcessor.php b/src/Monolog/Processor/TagProcessor.php
index 7e2df2a..6371986 100644
--- a/src/Monolog/Processor/TagProcessor.php
+++ b/src/Monolog/Processor/TagProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -20,22 +20,22 @@ class TagProcessor
{
private $tags;
- public function __construct(array $tags = array())
+ public function __construct(array $tags = [])
{
$this->setTags($tags);
}
- public function addTags(array $tags = array())
+ public function addTags(array $tags = [])
{
$this->tags = array_merge($this->tags, $tags);
}
- public function setTags(array $tags = array())
+ public function setTags(array $tags = [])
{
$this->tags = $tags;
}
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
$record['extra']['tags'] = $this->tags;
diff --git a/src/Monolog/Processor/UidProcessor.php b/src/Monolog/Processor/UidProcessor.php
index 812707c..601171b 100644
--- a/src/Monolog/Processor/UidProcessor.php
+++ b/src/Monolog/Processor/UidProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -20,16 +20,16 @@ class UidProcessor
{
private $uid;
- public function __construct($length = 7)
+ public function __construct(int $length = 7)
{
if (!is_int($length) || $length > 32 || $length < 1) {
throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
}
- $this->uid = substr(hash('md5', uniqid('', true)), 0, $length);
+ $this->uid = substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length);
}
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
$record['extra']['uid'] = $this->uid;
@@ -39,7 +39,7 @@ class UidProcessor
/**
* @return string
*/
- public function getUid()
+ public function getUid(): string
{
return $this->uid;
}
diff --git a/src/Monolog/Processor/WebProcessor.php b/src/Monolog/Processor/WebProcessor.php
index ea1d897..37324af 100644
--- a/src/Monolog/Processor/WebProcessor.php
+++ b/src/Monolog/Processor/WebProcessor.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -30,13 +30,13 @@ class WebProcessor
*
* @var array
*/
- protected $extraFields = array(
+ protected $extraFields = [
'url' => 'REQUEST_URI',
'ip' => 'REMOTE_ADDR',
'http_method' => 'REQUEST_METHOD',
'server' => 'SERVER_NAME',
'referrer' => 'HTTP_REFERER',
- );
+ ];
/**
* @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
@@ -65,11 +65,7 @@ class WebProcessor
}
}
- /**
- * @param array $record
- * @return array
- */
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// skip processing if for some reason request data
// is not present (CLI or wonky SAPIs)
@@ -82,26 +78,17 @@ class WebProcessor
return $record;
}
- /**
- * @param string $extraName
- * @param string $serverName
- * @return $this
- */
- public function addExtraField($extraName, $serverName)
+ public function addExtraField(string $extraName, string $serverName): self
{
$this->extraFields[$extraName] = $serverName;
return $this;
}
- /**
- * @param array $extra
- * @return array
- */
- private function appendExtraFields(array $extra)
+ private function appendExtraFields(array $extra): array
{
foreach ($this->extraFields as $extraName => $serverName) {
- $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null;
+ $extra[$extraName] = $this->serverData[$serverName] ?? null;
}
if (isset($this->serverData['UNIQUE_ID'])) {
diff --git a/src/Monolog/Registry.php b/src/Monolog/Registry.php
index 159b751..99a4344 100644
--- a/src/Monolog/Registry.php
+++ b/src/Monolog/Registry.php
@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
@@ -28,8 +28,8 @@ use InvalidArgumentException;
*
* function testLogger()
* {
- * Monolog\Registry::api()->addError('Sent to $api Logger instance');
- * Monolog\Registry::application()->addError('Sent to $application Logger instance');
+ * Monolog\Registry::api()->error('Sent to $api Logger instance');
+ * Monolog\Registry::application()->error('Sent to $application Logger instance');
* }
* </code>
*
@@ -42,7 +42,7 @@ class Registry
*
* @var Logger[]
*/
- private static $loggers = array();
+ private static $loggers = [];
/**
* Adds new logging channel to the registry
@@ -68,15 +68,15 @@ class Registry
*
* @param string|Logger $logger Name or logger instance
*/
- public static function hasLogger($logger)
+ public static function hasLogger($logger): bool
{
if ($logger instanceof Logger) {
$index = array_search($logger, self::$loggers, true);
return false !== $index;
- } else {
- return isset(self::$loggers[$logger]);
}
+
+ return isset(self::$loggers[$logger]);
}
/**
@@ -100,7 +100,7 @@ class Registry
*/
public static function clear()
{
- self::$loggers = array();
+ self::$loggers = [];
}
/**
@@ -108,9 +108,8 @@ class Registry
*
* @param string $name Name of the requested Logger instance
* @throws \InvalidArgumentException If named Logger instance is not in the registry
- * @return Logger Requested instance of Logger
*/
- public static function getInstance($name)
+ public static function getInstance($name): Logger
{
if (!isset(self::$loggers[$name])) {
throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
diff --git a/src/Monolog/Test/TestCase.php b/src/Monolog/Test/TestCase.php
new file mode 100644
index 0000000..23cf9ad
--- /dev/null
+++ b/src/Monolog/Test/TestCase.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Test;
+
+use Monolog\Logger;
+use Monolog\DateTimeImmutable;
+use Monolog\Formatter\FormatterInterface;
+
+/**
+ * Lets you easily generate log records and a dummy formatter for testing purposes
+ * *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class TestCase extends \PHPUnit\Framework\TestCase
+{
+ /**
+ * @return array Record
+ */
+ protected function getRecord($level = Logger::WARNING, $message = 'test', $context = [])
+ {
+ return [
+ 'message' => $message,
+ 'context' => $context,
+ 'level' => $level,
+ 'level_name' => Logger::getLevelName($level),
+ 'channel' => 'test',
+ 'datetime' => new DateTimeImmutable(true),
+ 'extra' => [],
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ protected function getMultipleRecords()
+ {
+ return [
+ $this->getRecord(Logger::DEBUG, 'debug message 1'),
+ $this->getRecord(Logger::DEBUG, 'debug message 2'),
+ $this->getRecord(Logger::INFO, 'information'),
+ $this->getRecord(Logger::WARNING, 'warning'),
+ $this->getRecord(Logger::ERROR, 'error'),
+ ];
+ }
+
+ protected function getIdentityFormatter(): FormatterInterface
+ {
+ $formatter = $this->createMock(FormatterInterface::class);
+ $formatter->expects($this->any())
+ ->method('format')
+ ->will($this->returnCallback(function ($record) {
+ return $record['message'];
+ }));
+
+ return $formatter;
+ }
+}