summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Monolog/DateTimeImmutable.php20
-rw-r--r--src/Monolog/ErrorHandler.php29
-rw-r--r--src/Monolog/Formatter/ChromePHPFormatter.php3
-rw-r--r--src/Monolog/Formatter/ElasticaFormatter.php19
-rw-r--r--src/Monolog/Formatter/FlowdockFormatter.php17
-rw-r--r--src/Monolog/Formatter/FluentdFormatter.php10
-rw-r--r--src/Monolog/Formatter/GelfMessageFormatter.php4
-rw-r--r--src/Monolog/Formatter/HtmlFormatter.php12
-rw-r--r--src/Monolog/Formatter/JsonFormatter.php45
-rw-r--r--src/Monolog/Formatter/LineFormatter.php34
-rw-r--r--src/Monolog/Formatter/LogglyFormatter.php6
-rw-r--r--src/Monolog/Formatter/LogmaticFormatter.php2
-rw-r--r--src/Monolog/Formatter/LogstashFormatter.php5
-rw-r--r--src/Monolog/Formatter/MongoDBFormatter.php51
-rw-r--r--src/Monolog/Formatter/NormalizerFormatter.php50
-rw-r--r--src/Monolog/Formatter/ScalarFormatter.php2
-rw-r--r--src/Monolog/Formatter/WildfireFormatter.php10
-rw-r--r--src/Monolog/Handler/AmqpHandler.php2
-rw-r--r--src/Monolog/Handler/ChromePHPHandler.php6
-rw-r--r--src/Monolog/Handler/DynamoDbHandler.php24
-rw-r--r--src/Monolog/Handler/FirePHPHandler.php6
-rw-r--r--src/Monolog/Handler/FlowdockHandler.php2
-rw-r--r--src/Monolog/Handler/GelfHandler.php2
-rw-r--r--src/Monolog/Handler/MandrillHandler.php2
-rw-r--r--src/Monolog/Handler/NoopHandler.php42
-rw-r--r--src/Monolog/Handler/ProcessHandler.php18
-rw-r--r--src/Monolog/Handler/RavenHandler.php8
-rw-r--r--src/Monolog/Handler/RedisHandler.php4
-rw-r--r--src/Monolog/Handler/RollbarHandler.php79
-rw-r--r--src/Monolog/Handler/RotatingFileHandler.php7
-rw-r--r--src/Monolog/Handler/SendGridHandler.php2
-rw-r--r--src/Monolog/Handler/SlackHandler.php17
-rw-r--r--src/Monolog/Handler/SocketHandler.php13
-rw-r--r--src/Monolog/Handler/StreamHandler.php2
-rw-r--r--src/Monolog/Handler/SyslogUdp/UdpSocket.php2
-rw-r--r--src/Monolog/Handler/SyslogUdpHandler.php8
-rw-r--r--src/Monolog/Logger.php59
-rw-r--r--src/Monolog/Processor/GitProcessor.php8
-rw-r--r--src/Monolog/Processor/IntrospectionProcessor.php10
-rw-r--r--src/Monolog/Processor/MemoryPeakUsageProcessor.php6
-rw-r--r--src/Monolog/Processor/MemoryProcessor.php12
-rw-r--r--src/Monolog/Processor/MemoryUsageProcessor.php6
-rw-r--r--src/Monolog/Processor/MercurialProcessor.php60
-rw-r--r--src/Monolog/Processor/ProcessIdProcessor.php6
-rw-r--r--src/Monolog/Processor/PsrLogMessageProcessor.php2
-rw-r--r--src/Monolog/Processor/TagProcessor.php2
-rw-r--r--src/Monolog/Processor/UidProcessor.php8
-rw-r--r--src/Monolog/Processor/WebProcessor.php19
-rw-r--r--src/Monolog/Registry.php9
-rw-r--r--src/Monolog/Test/TestCase.php8
50 files changed, 467 insertions, 313 deletions
diff --git a/src/Monolog/DateTimeImmutable.php b/src/Monolog/DateTimeImmutable.php
index 6ca786c..45b80c7 100644
--- a/src/Monolog/DateTimeImmutable.php
+++ b/src/Monolog/DateTimeImmutable.php
@@ -23,17 +23,27 @@ class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
public function __construct($useMicroseconds, \DateTimeZone $timezone = null)
{
+ $this->useMicroseconds = $useMicroseconds;
$date = 'now';
+
if ($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
- $timestamp = microtime(true);
- $microseconds = sprintf("%06d", ($timestamp - floor($timestamp)) * 1000000);
- $date = date('Y-m-d H:i:s.' . $microseconds, (int) $timestamp);
+ //
+ // 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);
- $this->useMicroseconds = $useMicroseconds;
+ parent::__construct($date, $timezone);
}
public function jsonSerialize(): string
diff --git a/src/Monolog/ErrorHandler.php b/src/Monolog/ErrorHandler.php
index 4038d82..18c783f 100644
--- a/src/Monolog/ErrorHandler.php
+++ b/src/Monolog/ErrorHandler.php
@@ -32,6 +32,7 @@ class ErrorHandler
private $previousErrorHandler;
private $errorLevelMap;
+ private $handleOnlyReportedErrors;
private $hasFatalErrorHandler;
private $fatalLevel;
@@ -54,7 +55,7 @@ class ErrorHandler
* @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling
* @return ErrorHandler
*/
- public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null)
+ public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self
{
$handler = new static($logger);
if ($errorLevelMap !== false) {
@@ -70,34 +71,42 @@ class ErrorHandler
return $handler;
}
- public function registerExceptionHandler($levelMap = [], $callPrevious = true)
+ public function registerExceptionHandler($levelMap = [], $callPrevious = true): self
{
$prev = set_exception_handler([$this, 'handleException']);
$this->uncaughtExceptionLevelMap = array_replace($this->defaultExceptionLevelMap(), $levelMap);
if ($callPrevious && $prev) {
$this->previousExceptionHandler = $prev;
}
+
+ return $this;
}
- public function registerErrorHandler(array $levelMap = [], $callPrevious = true, $errorTypes = -1)
+ public function registerErrorHandler(array $levelMap = [], $callPrevious = true, $errorTypes = -1, $handleOnlyReportedErrors = true): self
{
$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([$this, 'handleFatalError']);
$this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
$this->fatalLevel = $level;
$this->hasFatalErrorHandler = true;
+
+ return $this;
}
- protected function defaultExceptionLevelMap()
+ protected function defaultExceptionLevelMap(): array
{
return [
'ParseError' => LogLevel::CRITICAL,
@@ -105,7 +114,7 @@ class ErrorHandler
];
}
- protected function defaultErrorLevelMap()
+ protected function defaultErrorLevelMap(): array
{
return [
E_ERROR => LogLevel::CRITICAL,
@@ -157,14 +166,14 @@ class ErrorHandler
*/
public function handleError($code, $message, $file = '', $line = 0, $context = [])
{
- if (!(error_reporting() & $code)) {
+ if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) {
return;
}
// 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, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line, 'context' => $context]);
+ $this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
}
if ($this->previousErrorHandler === true) {
@@ -179,7 +188,7 @@ class ErrorHandler
*/
public function handleFatalError()
{
- $this->reservedMemory = null;
+ $this->reservedMemory = '';
$lastError = error_get_last();
if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) {
@@ -197,7 +206,7 @@ class ErrorHandler
}
}
- 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 12b0d60..2b4d649 100644
--- a/src/Monolog/Formatter/ChromePHPFormatter.php
+++ b/src/Monolog/Formatter/ChromePHPFormatter.php
@@ -65,6 +65,9 @@ class ChromePHPFormatter implements FormatterInterface
];
}
+ /**
+ * {@inheritdoc}
+ */
public function formatBatch(array $records)
{
$formatted = [];
diff --git a/src/Monolog/Formatter/ElasticaFormatter.php b/src/Monolog/Formatter/ElasticaFormatter.php
index e6a5e67..a6354f5 100644
--- a/src/Monolog/Formatter/ElasticaFormatter.php
+++ b/src/Monolog/Formatter/ElasticaFormatter.php
@@ -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 6a33038..301b74b 100644
--- a/src/Monolog/Formatter/FlowdockFormatter.php
+++ b/src/Monolog/Formatter/FlowdockFormatter.php
@@ -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,7 +37,7 @@ class FlowdockFormatter implements FormatterInterface
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): array
{
$tags = [
'#logs',
@@ -75,7 +71,7 @@ class FlowdockFormatter implements FormatterInterface
/**
* {@inheritdoc}
*/
- public function formatBatch(array $records)
+ public function formatBatch(array $records): array
{
$formatted = [];
@@ -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 e2a6658..a84f826 100644
--- a/src/Monolog/Formatter/FluentdFormatter.php
+++ b/src/Monolog/Formatter/FluentdFormatter.php
@@ -39,21 +39,21 @@ 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) {
@@ -73,7 +73,7 @@ class FluentdFormatter implements FormatterInterface
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/GelfMessageFormatter.php b/src/Monolog/Formatter/GelfMessageFormatter.php
index 047358a..d6d46c0 100644
--- a/src/Monolog/Formatter/GelfMessageFormatter.php
+++ b/src/Monolog/Formatter/GelfMessageFormatter.php
@@ -53,7 +53,7 @@ class GelfMessageFormatter extends NormalizerFormatter
Logger::EMERGENCY => 0,
];
- public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_')
+ public function __construct(string $systemName = null, string $extraPrefix = null, string $contextPrefix = 'ctxt_')
{
parent::__construct('U.u');
@@ -66,7 +66,7 @@ class GelfMessageFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): Message
{
if (isset($record['context'])) {
$record['context'] = parent::format($record['context']);
diff --git a/src/Monolog/Formatter/HtmlFormatter.php b/src/Monolog/Formatter/HtmlFormatter.php
index f5f9d94..a343b06 100644
--- a/src/Monolog/Formatter/HtmlFormatter.php
+++ b/src/Monolog/Formatter/HtmlFormatter.php
@@ -39,7 +39,7 @@ class HtmlFormatter extends NormalizerFormatter
/**
* @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);
}
@@ -52,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) {
@@ -69,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');
@@ -82,7 +82,7 @@ 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">';
@@ -116,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) {
@@ -126,7 +126,7 @@ class HtmlFormatter extends NormalizerFormatter
return $message;
}
- protected function convertToString($data)
+ protected function convertToString($data): string
{
if (null === $data || is_scalar($data)) {
return (string) $data;
diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php
index 1a8fe0b..61ccf2c 100644
--- a/src/Monolog/Formatter/JsonFormatter.php
+++ b/src/Monolog/Formatter/JsonFormatter.php
@@ -11,7 +11,7 @@
namespace Monolog\Formatter;
-use Exception;
+use Throwable;
/**
* Encodes whatever record data is passed to it as json
@@ -32,10 +32,7 @@ class JsonFormatter extends NormalizerFormatter
*/
protected $includeStacktraces = false;
- /**
- * @param int $batchMode
- */
- 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;
@@ -47,20 +44,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;
}
@@ -68,7 +61,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" : '');
}
@@ -76,7 +69,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,18 +84,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);
}
@@ -110,11 +100,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;
@@ -135,7 +122,7 @@ class JsonFormatter extends NormalizerFormatter
*
* @return mixed
*/
- protected function normalize($data, $depth = 0)
+ protected function normalize($data, int $depth = 0)
{
if ($depth > 9) {
return 'Over 9 levels deep, aborting normalization';
@@ -156,8 +143,8 @@ class JsonFormatter extends NormalizerFormatter
return $normalized;
}
- if ($data instanceof Exception) {
- return $this->normalizeException($data);
+ if ($data instanceof Throwable) {
+ return $this->normalizeException($data, $depth);
}
return $data;
@@ -166,12 +153,8 @@ class JsonFormatter extends NormalizerFormatter
/**
* Normalizes given exception with or without its own stack trace based on
* `includeStacktraces` property.
- *
- * @param Throwable $e
- *
- * @return array
*/
- protected function normalizeException(\Throwable $e)
+ protected function normalizeException(Throwable $e, int $depth = 0): array
{
$data = [
'class' => get_class($e),
@@ -196,7 +179,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 5a65b4c..254a618 100644
--- a/src/Monolog/Formatter/LineFormatter.php
+++ b/src/Monolog/Formatter/LineFormatter.php
@@ -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,6 +76,7 @@ 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);
@@ -101,10 +102,15 @@ class LineFormatter extends NormalizerFormatter
}
}
+ // remove leftover %extra.xxx% and %context.xxx% if any
+ if (false !== strpos($output, '%')) {
+ $output = preg_replace('/%(?:extra|context)\..+?%/', '', $output);
+ }
+
return $output;
}
- public function formatBatch(array $records)
+ public function formatBatch(array $records): string
{
$message = '';
foreach ($records as $record) {
@@ -114,12 +120,12 @@ class LineFormatter extends NormalizerFormatter
return $message;
}
- public function stringify($value)
+ public function stringify($value): string
{
return $this->replaceNewlines($this->convertToString($value));
}
- protected function normalizeException(\Throwable $e)
+ protected function normalizeException(\Throwable $e, int $depth = 0): string
{
$previousText = '';
if ($previous = $e->getPrevious()) {
@@ -130,13 +136,13 @@ class LineFormatter extends NormalizerFormatter
$str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
if ($this->includeStacktraces) {
- $str .= "\n[stacktrace]\n".$e->getTraceAsString();
+ $str .= "\n[stacktrace]\n".$e->getTraceAsString()."\n";
}
return $str;
}
- protected function convertToString($data)
+ protected function convertToString($data): string
{
if (null === $data || is_bool($data)) {
return var_export($data, true);
@@ -146,12 +152,16 @@ class LineFormatter extends NormalizerFormatter
return (string) $data;
}
- return $this->toJson($data, true);
+ return (string) $this->toJson($data, true);
}
- protected function replaceNewlines($str)
+ protected function replaceNewlines(string $str): string
{
if ($this->allowInlineLineBreaks) {
+ if (0 === strpos($str, '{')) {
+ return str_replace(['\r', '\n'], ["\r", "\n"], $str);
+ }
+
return $str;
}
diff --git a/src/Monolog/Formatter/LogglyFormatter.php b/src/Monolog/Formatter/LogglyFormatter.php
index d4190df..29841aa 100644
--- a/src/Monolog/Formatter/LogglyFormatter.php
+++ b/src/Monolog/Formatter/LogglyFormatter.php
@@ -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,7 +33,7 @@ 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 \DateTimeInterface)) {
$record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO");
diff --git a/src/Monolog/Formatter/LogmaticFormatter.php b/src/Monolog/Formatter/LogmaticFormatter.php
index 2e10312..0b999a2 100644
--- a/src/Monolog/Formatter/LogmaticFormatter.php
+++ b/src/Monolog/Formatter/LogmaticFormatter.php
@@ -54,7 +54,7 @@ class LogmaticFormatter extends JsonFormatter
* @see http://doc.logmatic.io/docs/basics-to-send-data
* @see \Monolog\Formatter\JsonFormatter::format()
*/
- public function format(array $record)
+ public function format(array $record): string
{
if (!empty($this->hostname)) {
$record['hostname'] = $this->hostname;
diff --git a/src/Monolog/Formatter/LogstashFormatter.php b/src/Monolog/Formatter/LogstashFormatter.php
index 31e354c..bc22da1 100644
--- a/src/Monolog/Formatter/LogstashFormatter.php
+++ b/src/Monolog/Formatter/LogstashFormatter.php
@@ -46,9 +46,8 @@ class LogstashFormatter extends NormalizerFormatter
* @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_')
+ 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');
@@ -62,7 +61,7 @@ class LogstashFormatter extends NormalizerFormatter
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): string
{
$record = parent::format($record);
diff --git a/src/Monolog/Formatter/MongoDBFormatter.php b/src/Monolog/Formatter/MongoDBFormatter.php
index 0630f7c..4725c80 100644
--- a/src/Monolog/Formatter/MongoDBFormatter.php
+++ b/src/Monolog/Formatter/MongoDBFormatter.php
@@ -22,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);
}
@@ -44,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);
@@ -53,7 +56,10 @@ 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) {
@@ -74,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);
@@ -82,7 +88,7 @@ class MongoDBFormatter implements FormatterInterface
return $this->formatArray($objectVars, $nestingLevel);
}
- protected function formatException(\Throwable $exception, $nestingLevel)
+ protected function formatException(\Throwable $exception, int $nestingLevel)
{
$formattedException = [
'class' => get_class($exception),
@@ -100,8 +106,35 @@ class MongoDBFormatter implements FormatterInterface
return $this->formatArray($formattedException, $nestingLevel);
}
- protected function formatDate(\DateTimeInterface $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) ($value->format('U.u') * 1000));
+ return new UTCDateTime((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
+ {
+ $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 fcac4a6..592713f 100644
--- a/src/Monolog/Formatter/NormalizerFormatter.php
+++ b/src/Monolog/Formatter/NormalizerFormatter.php
@@ -39,7 +39,7 @@ class NormalizerFormatter implements FormatterInterface
/**
* {@inheritdoc}
*/
- public function format(array $record)
+ public function format(array $record): array
{
return $this->normalize($record);
}
@@ -47,7 +47,7 @@ class NormalizerFormatter implements FormatterInterface
/**
* {@inheritdoc}
*/
- public function formatBatch(array $records)
+ public function formatBatch(array $records): array
{
foreach ($records as $key => $record) {
$records[$key] = $this->format($record);
@@ -56,7 +56,11 @@ class NormalizerFormatter implements FormatterInterface
return $records;
}
- protected function normalize($data, $depth = 0)
+ /**
+ * @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';
@@ -79,9 +83,13 @@ class NormalizerFormatter implements FormatterInterface
$normalized = [];
$count = 1;
+ if ($data instanceof \Generator && !$data->valid()) {
+ return array('...' => 'Generator is already consumed, aborting');
+ }
+
foreach ($data as $key => $value) {
if ($count++ >= 1000) {
- $normalized['...'] = 'Over 1000 items, aborting normalization';
+ $normalized['...'] = 'Over 1000 items ('.($data instanceof \Generator ? 'generator function' : count($data).' total').'), aborting normalization';
break;
}
$normalized[$key] = $this->normalize($value, $depth + 1);
@@ -96,7 +104,7 @@ class NormalizerFormatter implements FormatterInterface
if (is_object($data)) {
if ($data instanceof Throwable) {
- return $this->normalizeException($data);
+ return $this->normalizeException($data, $depth);
}
if ($data instanceof \JsonSerializable) {
@@ -123,7 +131,10 @@ class NormalizerFormatter implements FormatterInterface
return '[unknown('.gettype($data).')]';
}
- protected function normalizeException(Throwable $e)
+ /**
+ * @return array
+ */
+ protected function normalizeException(Throwable $e, int $depth = 0)
{
$data = [
'class' => get_class($e),
@@ -132,6 +143,20 @@ class NormalizerFormatter implements FormatterInterface
'file' => $e->getFile().':'.$e->getLine(),
];
+ if ($e instanceof \SoapFault) {
+ if (isset($e->faultcode)) {
+ $data['faultcode'] = $e->faultcode;
+ }
+
+ if (isset($e->faultactor)) {
+ $data['faultactor'] = $e->faultactor;
+ }
+
+ if (isset($e->detail)) {
+ $data['detail'] = $e->detail;
+ }
+ }
+
$trace = $e->getTrace();
foreach ($trace as $frame) {
if (isset($frame['file'])) {
@@ -141,12 +166,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;
@@ -156,11 +181,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|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) {
@@ -182,7 +206,7 @@ class NormalizerFormatter implements FormatterInterface
*/
private function jsonEncode($data)
{
- return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+ return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION);
}
/**
@@ -286,7 +310,9 @@ class NormalizerFormatter implements FormatterInterface
protected function formatDate(\DateTimeInterface $date)
{
- if ($date instanceof DateTimeImmutable) {
+ // 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;
}
diff --git a/src/Monolog/Formatter/ScalarFormatter.php b/src/Monolog/Formatter/ScalarFormatter.php
index fcff129..8d560e7 100644
--- a/src/Monolog/Formatter/ScalarFormatter.php
+++ b/src/Monolog/Formatter/ScalarFormatter.php
@@ -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 9c00aa7..c8a3bb4 100644
--- a/src/Monolog/Formatter/WildfireFormatter.php
+++ b/src/Monolog/Formatter/WildfireFormatter.php
@@ -41,7 +41,7 @@ class WildfireFormatter extends NormalizerFormatter
/**
* {@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 = '';
@@ -97,12 +97,18 @@ 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, $depth = 0)
+ /**
+ * {@inheritdoc}
+ */
+ protected function normalize($data, int $depth = 0)
{
if (is_object($data) && !$data instanceof \DateTimeInterface) {
return $data;
diff --git a/src/Monolog/Handler/AmqpHandler.php b/src/Monolog/Handler/AmqpHandler.php
index b46435a..6e39a11 100644
--- a/src/Monolog/Handler/AmqpHandler.php
+++ b/src/Monolog/Handler/AmqpHandler.php
@@ -112,7 +112,7 @@ class AmqpHandler extends AbstractProcessingHandler
* @param array $record
* @return string
*/
- private function getRoutingKey(array $record)
+ protected function getRoutingKey(array $record)
{
$routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);
diff --git a/src/Monolog/Handler/ChromePHPHandler.php b/src/Monolog/Handler/ChromePHPHandler.php
index 31573ad..5dc5d5c 100644
--- a/src/Monolog/Handler/ChromePHPHandler.php
+++ b/src/Monolog/Handler/ChromePHPHandler.php
@@ -174,16 +174,14 @@ 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']);
+ return preg_match(self::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
}
/**
diff --git a/src/Monolog/Handler/DynamoDbHandler.php b/src/Monolog/Handler/DynamoDbHandler.php
index 43d4ddb..edbc630 100644
--- a/src/Monolog/Handler/DynamoDbHandler.php
+++ b/src/Monolog/Handler/DynamoDbHandler.php
@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Aws\Common\Aws;
use Aws\DynamoDb\DynamoDbClient;
use Monolog\Formatter\FormatterInterface;
+use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter;
use Monolog\Logger;
@@ -38,6 +39,16 @@ class DynamoDbHandler extends AbstractProcessingHandler
protected $table;
/**
+ * @var int
+ */
+ protected $version;
+
+ /**
+ * @var Marshaler
+ */
+ protected $marshaler;
+
+ /**
* @param DynamoDbClient $client
* @param string $table
* @param int $level
@@ -45,8 +56,11 @@ class DynamoDbHandler extends AbstractProcessingHandler
*/
public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true)
{
- if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) {
- throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases');
+ if (defined('Aws\Common\Aws::VERSION') && version_compare(Aws::VERSION, '3.0', '>=')) {
+ $this->version = 3;
+ $this->marshaler = new Marshaler;
+ } else {
+ $this->version = 2;
}
$this->client = $client;
@@ -61,7 +75,11 @@ class DynamoDbHandler extends AbstractProcessingHandler
protected function write(array $record)
{
$filtered = $this->filterEmptyFields($record['formatted']);
- $formatted = $this->client->formatAttributes($filtered);
+ if ($this->version === 3) {
+ $formatted = $this->marshaler->marshalItem($filtered);
+ } else {
+ $formatted = $this->client->formatAttributes($filtered);
+ }
$this->client->putItem([
'TableName' => $this->table,
diff --git a/src/Monolog/Handler/FirePHPHandler.php b/src/Monolog/Handler/FirePHPHandler.php
index 42c78f6..9a9acb5 100644
--- a/src/Monolog/Handler/FirePHPHandler.php
+++ b/src/Monolog/Handler/FirePHPHandler.php
@@ -61,7 +61,7 @@ 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));
@@ -72,10 +72,8 @@ class FirePHPHandler extends AbstractProcessingHandler
* 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.
diff --git a/src/Monolog/Handler/FlowdockHandler.php b/src/Monolog/Handler/FlowdockHandler.php
index b3fc9b4..67d1291 100644
--- a/src/Monolog/Handler/FlowdockHandler.php
+++ b/src/Monolog/Handler/FlowdockHandler.php
@@ -65,7 +65,7 @@ class FlowdockHandler extends SocketHandler
/**
* Gets the default formatter.
*
- * @return FormatterInterface
+ * @suppress PhanTypeMissingReturn
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/src/Monolog/Handler/GelfHandler.php b/src/Monolog/Handler/GelfHandler.php
index 4a6c0f8..b5c3a8c 100644
--- a/src/Monolog/Handler/GelfHandler.php
+++ b/src/Monolog/Handler/GelfHandler.php
@@ -25,7 +25,7 @@ use Monolog\Formatter\FormatterInterface;
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;
diff --git a/src/Monolog/Handler/MandrillHandler.php b/src/Monolog/Handler/MandrillHandler.php
index 68ec568..066c649 100644
--- a/src/Monolog/Handler/MandrillHandler.php
+++ b/src/Monolog/Handler/MandrillHandler.php
@@ -46,7 +46,7 @@ class MandrillHandler extends MailHandler
/**
* {@inheritdoc}
*/
- protected function send($content, array $records)
+ protected function send(string $content, array $records)
{
$mime = null;
if ($this->isHtmlBody($content)) {
diff --git a/src/Monolog/Handler/NoopHandler.php b/src/Monolog/Handler/NoopHandler.php
new file mode 100644
index 0000000..7c7ec03
--- /dev/null
+++ b/src/Monolog/Handler/NoopHandler.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Roel Harbers <roelharbers@gmail.com>
+ *
+ * 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;
+
+/**
+ * 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/ProcessHandler.php b/src/Monolog/Handler/ProcessHandler.php
index 9c135f8..8cf6087 100644
--- a/src/Monolog/Handler/ProcessHandler.php
+++ b/src/Monolog/Handler/ProcessHandler.php
@@ -29,7 +29,7 @@ class ProcessHandler extends AbstractProcessingHandler
/**
* Holds the process to receive data on its STDIN.
*
- * @var resource
+ * @var resource|bool|null
*/
private $process;
@@ -58,20 +58,20 @@ class ProcessHandler extends AbstractProcessingHandler
];
/**
- * @param int $command Command for the process to start. Absolute paths are recommended,
+ * @param string $command Command for the process to start. Absolute paths are recommended,
* especially if you do not use the $cwd parameter.
- * @param bool|int $level The minimum logging level at which this handler will be triggered.
- * @param bool|true $bubble Whether the messages that are handled can bubble up the stack or not.
- * @param string|null $cwd "Current working directory" (CWD) for the process to be executed in.
+ * @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($command, $level = Logger::DEBUG, $bubble = true, $cwd = null)
+ public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, string $cwd = null)
{
- if (empty($command) || is_string($command) === false) {
+ if ($command === '') {
throw new \InvalidArgumentException('The command argument must be a non-empty string.');
}
- if ($cwd !== null && (empty($cwd) || is_string($cwd) === false)) {
- throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string, if any.');
+ if ($cwd === '') {
+ throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
}
parent::__construct($level, $bubble);
diff --git a/src/Monolog/Handler/RavenHandler.php b/src/Monolog/Handler/RavenHandler.php
index db64f80..c2283e8 100644
--- a/src/Monolog/Handler/RavenHandler.php
+++ b/src/Monolog/Handler/RavenHandler.php
@@ -84,7 +84,7 @@ class RavenHandler extends AbstractProcessingHandler
// the record with the highest severity is the "main" one
$record = array_reduce($records, function ($highest, $record) {
- if ($record['level'] >= $highest['level']) {
+ if ($record['level'] > $highest['level']) {
return $record;
}
@@ -133,6 +133,7 @@ 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 = [];
$options['level'] = $this->logLevels[$record['level']];
@@ -179,14 +180,15 @@ class RavenHandler extends AbstractProcessingHandler
$options['release'] = $this->release;
}
- if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
+ if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
$options['extra']['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
$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);
}
}
diff --git a/src/Monolog/Handler/RedisHandler.php b/src/Monolog/Handler/RedisHandler.php
index f77d4fd..e7ddb44 100644
--- a/src/Monolog/Handler/RedisHandler.php
+++ b/src/Monolog/Handler/RedisHandler.php
@@ -37,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');
diff --git a/src/Monolog/Handler/RollbarHandler.php b/src/Monolog/Handler/RollbarHandler.php
index 0a82faa..94e4757 100644
--- a/src/Monolog/Handler/RollbarHandler.php
+++ b/src/Monolog/Handler/RollbarHandler.php
@@ -21,6 +21,14 @@ use Monolog\Logger;
* If the context data contains a `payload` key, that is used as an array
* of payload options to RollbarNotifier's report_message/report_exception methods.
*
+ * Rollbar's context info will contain the context + extra keys from the log record
+ * merged, and then on top of that a few keys:
+ *
+ * - level (rollbar level name)
+ * - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8)
+ * - channel
+ * - datetime (unix timestamp)
+ *
* @author Paul Statezny <paulstatezny@gmail.com>
*/
class RollbarHandler extends AbstractProcessingHandler
@@ -32,6 +40,17 @@ class RollbarHandler extends AbstractProcessingHandler
*/
protected $rollbarNotifier;
+ protected $levelMap = [
+ Logger::DEBUG => 'debug',
+ Logger::INFO => 'info',
+ Logger::NOTICE => 'info',
+ Logger::WARNING => 'warning',
+ Logger::ERROR => 'error',
+ 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
*
@@ -39,6 +58,8 @@ class RollbarHandler extends AbstractProcessingHandler
*/
private $hasRecords = false;
+ protected $initialized = false;
+
/**
* @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token
* @param int $level The minimum logging level at which this handler will be triggered
@@ -56,36 +77,35 @@ class RollbarHandler extends AbstractProcessingHandler
*/
protected function write(array $record)
{
- if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) {
- $context = $record['context'];
+ if (!$this->initialized) {
+ // __destructor() doesn't get called on Fatal errors
+ register_shutdown_function(array($this, 'close'));
+ $this->initialized = true;
+ }
+
+ $context = $record['context'];
+ $payload = [];
+ if (isset($context['payload'])) {
+ $payload = $context['payload'];
+ unset($context['payload']);
+ }
+ $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) {
$exception = $context['exception'];
unset($context['exception']);
- $payload = [];
- if (isset($context['payload'])) {
- $payload = $context['payload'];
- unset($context['payload']);
- }
-
$this->rollbarNotifier->report_exception($exception, $context, $payload);
} else {
- $extraData = [
- 'level' => $record['level'],
- 'channel' => $record['channel'],
- 'datetime' => $record['datetime']->format('U'),
- ];
-
- $context = $record['context'];
- $payload = [];
- if (isset($context['payload'])) {
- $payload = $context['payload'];
- unset($context['payload']);
- }
-
$this->rollbarNotifier->report_message(
$record['message'],
- $record['level_name'],
- array_merge($record['context'], $record['extra'], $extraData),
+ $context['level'],
+ $context,
$payload
);
}
@@ -93,14 +113,19 @@ class RollbarHandler extends AbstractProcessingHandler
$this->hasRecords = true;
}
- /**
- * {@inheritdoc}
- */
- public function close()
+ public function flush()
{
if ($this->hasRecords) {
$this->rollbarNotifier->flush();
$this->hasRecords = false;
}
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ $this->flush();
+ }
}
diff --git a/src/Monolog/Handler/RotatingFileHandler.php b/src/Monolog/Handler/RotatingFileHandler.php
index 8c99f2d..a4a5ba4 100644
--- a/src/Monolog/Handler/RotatingFileHandler.php
+++ b/src/Monolog/Handler/RotatingFileHandler.php
@@ -69,11 +69,12 @@ class RotatingFileHandler extends StreamHandler
public function setFilenameFormat($filenameFormat, $dateFormat)
{
- if (!in_array($dateFormat, [self::FILE_PER_DAY, self::FILE_PER_MONTH, self::FILE_PER_YEAR])) {
+ if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
throw new InvalidArgumentException(
'Invalid date format - format must be one of '.
- 'RotatingFileHandler::FILE_PER_DAY, RotatingFileHandler::FILE_PER_MONTH '.
- 'or RotatingFileHandler::FILE_PER_YEAR.'
+ '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.'
);
}
if (substr_count($filenameFormat, '{date}') === 0) {
diff --git a/src/Monolog/Handler/SendGridHandler.php b/src/Monolog/Handler/SendGridHandler.php
index 3a91cb4..7d82d94 100644
--- a/src/Monolog/Handler/SendGridHandler.php
+++ b/src/Monolog/Handler/SendGridHandler.php
@@ -72,7 +72,7 @@ class SendGridHandler extends MailHandler
/**
* {@inheritdoc}
*/
- protected function send($content, array $records)
+ protected function send(string $content, array $records)
{
$message = [];
$message['api_user'] = $this->apiUser;
diff --git a/src/Monolog/Handler/SlackHandler.php b/src/Monolog/Handler/SlackHandler.php
index a5db721..d311e2d 100644
--- a/src/Monolog/Handler/SlackHandler.php
+++ b/src/Monolog/Handler/SlackHandler.php
@@ -79,9 +79,10 @@ class SlackHandler extends SocketHandler
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @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 bool $printSimpleMessage Whether the attachment should include only the message without extradata
* @throws MissingExtensionException If no OpenSSL PHP extension configured
*/
- public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false)
+ public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false, $printSimpleMessage = false)
{
if (!extension_loaded('openssl')) {
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
@@ -144,19 +145,25 @@ class SlackHandler extends SocketHandler
'attachments' => [],
];
+ if ($this->formatter && !$printSimpleMessage) {
+ $message = $this->formatter->format($record);
+ } else {
+ $message = $record['message'];
+ }
+
if ($this->useAttachment) {
$attachment = [
- 'fallback' => $record['message'],
+ 'fallback' => $message,
'color' => $this->getAttachmentColor($record['level']),
'fields' => [],
];
if ($this->useShortAttachment) {
$attachment['title'] = $record['level_name'];
- $attachment['text'] = $record['message'];
+ $attachment['text'] = $message;
} else {
$attachment['title'] = 'Message';
- $attachment['text'] = $record['message'];
+ $attachment['text'] = $message;
$attachment['fields'][] = [
'title' => 'Level',
'value' => $record['level_name'],
@@ -206,7 +213,7 @@ class SlackHandler extends SocketHandler
$dataArray['attachments'] = json_encode([$attachment]);
} else {
- $dataArray['text'] = $record['message'];
+ $dataArray['text'] = $message;
}
if ($this->iconEmoji) {
diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php
index 06a2019..e2161ff 100644
--- a/src/Monolog/Handler/SocketHandler.php
+++ b/src/Monolog/Handler/SocketHandler.php
@@ -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;
}
diff --git a/src/Monolog/Handler/StreamHandler.php b/src/Monolog/Handler/StreamHandler.php
index 4a7433c..661e164 100644
--- a/src/Monolog/Handler/StreamHandler.php
+++ b/src/Monolog/Handler/StreamHandler.php
@@ -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;
diff --git a/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/src/Monolog/Handler/SyslogUdp/UdpSocket.php
index 7a23ae8..f1801b3 100644
--- a/src/Monolog/Handler/SyslogUdp/UdpSocket.php
+++ b/src/Monolog/Handler/SyslogUdp/UdpSocket.php
@@ -17,6 +17,8 @@ class UdpSocket
protected $ip;
protected $port;
+
+ /** @var resource|null */
protected $socket;
public function __construct($ip, $port = 514)
diff --git a/src/Monolog/Handler/SyslogUdpHandler.php b/src/Monolog/Handler/SyslogUdpHandler.php
index 4e2335d..2f16c3b 100644
--- a/src/Monolog/Handler/SyslogUdpHandler.php
+++ b/src/Monolog/Handler/SyslogUdpHandler.php
@@ -53,19 +53,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);
+ 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;
@@ -75,7 +75,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/Logger.php b/src/Monolog/Logger.php
index 8f981e3..438c770 100644
--- a/src/Monolog/Logger.php
+++ b/src/Monolog/Logger.php
@@ -136,7 +136,7 @@ class Logger implements LoggerInterface
protected $timezone;
/**
- * @param string $name The logging channel
+ * @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
@@ -149,9 +149,6 @@ class Logger implements LoggerInterface
$this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
}
- /**
- * @return string
- */
public function getName(): string
{
return $this->name;
@@ -159,8 +156,6 @@ class Logger implements LoggerInterface
/**
* Return a new cloned instance with the name changed
- *
- * @return static
*/
public function withName(string $name): self
{
@@ -172,9 +167,6 @@ class Logger implements LoggerInterface
/**
* Pushes a handler on to the stack.
- *
- * @param HandlerInterface $handler
- * @return $this
*/
public function pushHandler(HandlerInterface $handler): self
{
@@ -186,7 +178,7 @@ class Logger implements LoggerInterface
/**
* Pops a handler from the stack
*
- * @return HandlerInterface
+ * @throws \LogicException If empty handler stack
*/
public function popHandler(): HandlerInterface
{
@@ -202,8 +194,7 @@ 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): self
{
@@ -225,9 +216,6 @@ class Logger implements LoggerInterface
/**
* Adds a processor on to the stack.
- *
- * @param callable $callback
- * @return $this
*/
public function pushProcessor(callable $callback): self
{
@@ -239,6 +227,7 @@ 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(): callable
@@ -304,16 +293,13 @@ class Logger implements LoggerInterface
return false;
}
- $dateTime = new DateTimeImmutable($this->microsecondTimestamps, $this->timezone);
- $dateTime->setTimezone($this->timezone);
-
$record = [
'message' => $message,
'context' => $context,
'level' => $level,
'level_name' => $levelName,
'channel' => $this->name,
- 'datetime' => $dateTime,
+ 'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
'extra' => [],
];
@@ -345,7 +331,8 @@ 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(int $level): string
@@ -361,6 +348,7 @@ 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): int
@@ -405,13 +393,12 @@ class Logger implements LoggerInterface
* @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
*/
public function log($level, $message, array $context = [])
{
$level = static::toMonologLevel($level);
- return $this->addRecord($level, (string) $message, $context);
+ $this->addRecord($level, (string) $message, $context);
}
/**
@@ -421,11 +408,10 @@ class Logger implements LoggerInterface
*
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
*/
public function debug($message, array $context = [])
{
- return $this->addRecord(static::DEBUG, (string) $message, $context);
+ $this->addRecord(static::DEBUG, (string) $message, $context);
}
/**
@@ -435,11 +421,10 @@ class Logger implements LoggerInterface
*
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
*/
public function info($message, array $context = [])
{
- return $this->addRecord(static::INFO, (string) $message, $context);
+ $this->addRecord(static::INFO, (string) $message, $context);
}
/**
@@ -449,11 +434,10 @@ class Logger implements LoggerInterface
*
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
*/
public function notice($message, array $context = [])
{
- return $this->addRecord(static::NOTICE, (string) $message, $context);
+ $this->addRecord(static::NOTICE, (string) $message, $context);
}
/**
@@ -463,11 +447,10 @@ class Logger implements LoggerInterface
*
* @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 = [])
{
- return $this->addRecord(static::WARNING, (string) $message, $context);
+ $this->addRecord(static::WARNING, (string) $message, $context);
}
/**
@@ -477,11 +460,10 @@ class Logger implements LoggerInterface
*
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
*/
public function error($message, array $context = [])
{
- return $this->addRecord(static::ERROR, (string) $message, $context);
+ $this->addRecord(static::ERROR, (string) $message, $context);
}
/**
@@ -491,11 +473,10 @@ class Logger implements LoggerInterface
*
* @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 = [])
{
- return $this->addRecord(static::CRITICAL, (string) $message, $context);
+ $this->addRecord(static::CRITICAL, (string) $message, $context);
}
/**
@@ -505,11 +486,10 @@ class Logger implements LoggerInterface
*
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
*/
public function alert($message, array $context = [])
{
- return $this->addRecord(static::ALERT, (string) $message, $context);
+ $this->addRecord(static::ALERT, (string) $message, $context);
}
/**
@@ -519,11 +499,10 @@ class Logger implements LoggerInterface
*
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
*/
public function emergency($message, array $context = [])
{
- return $this->addRecord(static::EMERGENCY, (string) $message, $context);
+ $this->addRecord(static::EMERGENCY, (string) $message, $context);
}
/**
@@ -531,9 +510,11 @@ class Logger implements LoggerInterface
*
* @param DateTimeZone $tz Timezone object
*/
- public function setTimezone(DateTimeZone $tz)
+ public function setTimezone(DateTimeZone $tz): self
{
$this->timezone = $tz;
+
+ return $this;
}
/**
diff --git a/src/Monolog/Processor/GitProcessor.php b/src/Monolog/Processor/GitProcessor.php
index cf16be8..9eec186 100644
--- a/src/Monolog/Processor/GitProcessor.php
+++ b/src/Monolog/Processor/GitProcessor.php
@@ -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;
diff --git a/src/Monolog/Processor/IntrospectionProcessor.php b/src/Monolog/Processor/IntrospectionProcessor.php
index 59e2f48..e1b5d3a 100644
--- a/src/Monolog/Processor/IntrospectionProcessor.php
+++ b/src/Monolog/Processor/IntrospectionProcessor.php
@@ -37,18 +37,14 @@ class IntrospectionProcessor
'call_user_func_array',
];
- public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], $skipStackFramesCount = 0)
+ public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
{
$this->level = Logger::toMonologLevel($level);
$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) {
@@ -96,7 +92,7 @@ class IntrospectionProcessor
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 b8fd91c..b6f8acc 100644
--- a/src/Monolog/Processor/MemoryPeakUsageProcessor.php
+++ b/src/Monolog/Processor/MemoryPeakUsageProcessor.php
@@ -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 460caa6..5b06c2e 100644
--- a/src/Monolog/Processor/MemoryProcessor.php
+++ b/src/Monolog/Processor/MemoryProcessor.php
@@ -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 cb6b2ea..31c9396 100644
--- a/src/Monolog/Processor/MemoryUsageProcessor.php
+++ b/src/Monolog/Processor/MemoryUsageProcessor.php
@@ -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
new file mode 100644
index 0000000..87f254b
--- /dev/null
+++ b/src/Monolog/Processor/MercurialProcessor.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * 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\Processor;
+
+use Monolog\Logger;
+
+/**
+ * Injects Hg branch and Hg revision number in all records
+ *
+ * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
+ */
+class MercurialProcessor
+{
+ private $level;
+ private static $cache;
+
+ public function __construct($level = Logger::DEBUG)
+ {
+ $this->level = Logger::toMonologLevel($level);
+ }
+
+ public function __invoke(array $record): array
+ {
+ // return if the level is not high enough
+ if ($record['level'] < $this->level) {
+ return $record;
+ }
+
+ $record['extra']['hg'] = self::getMercurialInfo();
+
+ return $record;
+ }
+
+ private static function getMercurialInfo(): array
+ {
+ if (self::$cache) {
+ return self::$cache;
+ }
+
+ $result = explode(' ', trim(`hg id -nb`));
+
+ if (count($result) >= 3) {
+ return self::$cache = [
+ 'branch' => $result[1],
+ 'revision' => $result[2],
+ ];
+ }
+
+ return self::$cache = [];
+ }
+}
diff --git a/src/Monolog/Processor/ProcessIdProcessor.php b/src/Monolog/Processor/ProcessIdProcessor.php
index 7ddafea..392bd13 100644
--- a/src/Monolog/Processor/ProcessIdProcessor.php
+++ b/src/Monolog/Processor/ProcessIdProcessor.php
@@ -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 e1a42cd..b9a00a4 100644
--- a/src/Monolog/Processor/PsrLogMessageProcessor.php
+++ b/src/Monolog/Processor/PsrLogMessageProcessor.php
@@ -24,7 +24,7 @@ class PsrLogMessageProcessor
* @param array $record
* @return array
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
if (false === strpos($record['message'], '{')) {
return $record;
diff --git a/src/Monolog/Processor/TagProcessor.php b/src/Monolog/Processor/TagProcessor.php
index 19458e2..6371986 100644
--- a/src/Monolog/Processor/TagProcessor.php
+++ b/src/Monolog/Processor/TagProcessor.php
@@ -35,7 +35,7 @@ class TagProcessor
$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 891e9df..601171b 100644
--- a/src/Monolog/Processor/UidProcessor.php
+++ b/src/Monolog/Processor/UidProcessor.php
@@ -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 91abeec..2e7134f 100644
--- a/src/Monolog/Processor/WebProcessor.php
+++ b/src/Monolog/Processor/WebProcessor.php
@@ -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,23 +78,14 @@ 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;
diff --git a/src/Monolog/Registry.php b/src/Monolog/Registry.php
index 64612c8..b63ef2e 100644
--- a/src/Monolog/Registry.php
+++ b/src/Monolog/Registry.php
@@ -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]);
}
/**
@@ -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
index 7cb7fbf..32a0b23 100644
--- a/src/Monolog/Test/TestCase.php
+++ b/src/Monolog/Test/TestCase.php
@@ -13,6 +13,7 @@ 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
@@ -51,12 +52,9 @@ class TestCase extends \PHPUnit_Framework_TestCase
];
}
- /**
- * @return Monolog\Formatter\FormatterInterface
- */
- protected function getIdentityFormatter()
+ protected function getIdentityFormatter(): FormatterInterface
{
- $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
+ $formatter = $this->createMock(FormatterInterface::class);
$formatter->expects($this->any())
->method('format')
->will($this->returnCallback(function ($record) {