1
0
mirror of https://github.com/Seldaek/monolog.git synced 2025-10-18 23:26:20 +02:00

Add LogRecord class, drop PHP <8.1

This commit is contained in:
Jordi Boggiano
2022-02-20 14:39:51 +01:00
parent f2f66cd480
commit 22c8b19358
111 changed files with 501 additions and 361 deletions

View File

@@ -16,17 +16,10 @@ jobs:
strategy: strategy:
matrix: matrix:
php-version: php-version:
- "7.2" - "8.1"
- "7.3"
- "7.4"
- "8.0"
# disabled for now as phpspec/prophecy does not allow 8.1
# - "8.1"
dependencies: [highest] dependencies: [highest]
include: include:
- php-version: "7.2" - php-version: "8.1"
dependencies: lowest
- php-version: "8.0"
dependencies: lowest dependencies: lowest
steps: steps:

View File

@@ -13,8 +13,7 @@ jobs:
strategy: strategy:
matrix: matrix:
php-version: php-version:
- "7.2" - "8.1"
- "8.0"
steps: steps:
- name: "Checkout" - name: "Checkout"

View File

@@ -16,7 +16,7 @@ jobs:
strategy: strategy:
matrix: matrix:
php-version: php-version:
- "8.0" - "8.1"
steps: steps:
- name: "Checkout" - name: "Checkout"
@@ -44,8 +44,7 @@ jobs:
run: 'composer require ${{ env.COMPOSER_FLAGS }} mongodb/mongodb --dev --no-update' run: 'composer require ${{ env.COMPOSER_FLAGS }} mongodb/mongodb --dev --no-update'
- name: "Install latest dependencies" - name: "Install latest dependencies"
# --ignore-platform-req=php here needed as long as elasticsearch/elasticsearch does not support php 8 run: "composer update ${{ env.COMPOSER_FLAGS }}"
run: "composer update ${{ env.COMPOSER_FLAGS }} --ignore-platform-req=php"
- name: Run PHPStan - name: Run PHPStan
run: composer phpstan run: composer phpstan

View File

@@ -13,8 +13,8 @@
} }
], ],
"require": { "require": {
"php": ">=7.2", "php": ">=8.1",
"psr/log": "^1.0.1 || ^2.0 || ^3.0" "psr/log": "^2.0 || ^3.0"
}, },
"require-dev": { "require-dev": {
"aws/aws-sdk-php": "^2.4.9 || ^3.0", "aws/aws-sdk-php": "^2.4.9 || ^3.0",
@@ -25,12 +25,11 @@
"php-amqplib/php-amqplib": "~2.4 || ^3", "php-amqplib/php-amqplib": "~2.4 || ^3",
"php-console/php-console": "^3.1.3", "php-console/php-console": "^3.1.3",
"phpspec/prophecy": "^1.6.1", "phpspec/prophecy": "^1.6.1",
"phpunit/phpunit": "^8.5", "phpunit/phpunit": "^9",
"predis/predis": "^1.1", "predis/predis": "^1.1",
"rollbar/rollbar": "^1.3 || ^2 || ^3", "rollbar/rollbar": "^3",
"ruflin/elastica": ">=0.90@dev", "ruflin/elastica": ">=0.90@dev",
"swiftmailer/swiftmailer": "^5.3|^6.0", "phpstan/phpstan": "^1.4"
"phpstan/phpstan": "^0.12.91"
}, },
"suggest": { "suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
@@ -56,11 +55,11 @@
"psr-4": {"Monolog\\": "tests/Monolog"} "psr-4": {"Monolog\\": "tests/Monolog"}
}, },
"provide": { "provide": {
"psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" "psr/log-implementation": "3.0.0"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "2.x-dev" "dev-main": "3.x-dev"
} }
}, },
"scripts": { "scripts": {

View File

@@ -36,7 +36,7 @@ class PDOHandler extends AbstractProcessingHandler
parent::__construct($level, $bubble); parent::__construct($level, $bubble);
} }
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!$this->initialized) { if (!$this->initialized) {
$this->initialize(); $this->initialize();

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Formats a log message according to the ChromePHP array format * Formats a log message according to the ChromePHP array format
@@ -39,7 +40,7 @@ class ChromePHPFormatter implements FormatterInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record) public function format(LogRecord $record)
{ {
// Retrieve the line and file if set and remove them from the formatted extra // Retrieve the line and file if set and remove them from the formatted extra
$backtrace = 'unknown'; $backtrace = 'unknown';

View File

@@ -12,13 +12,12 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Elastica\Document; use Elastica\Document;
use Monolog\LogRecord;
/** /**
* Format a log message into an Elastica Document * Format a log message into an Elastica Document
* *
* @author Jelle Vink <jelle.vink@gmail.com> * @author Jelle Vink <jelle.vink@gmail.com>
*
* @phpstan-import-type Record from \Monolog\Logger
*/ */
class ElasticaFormatter extends NormalizerFormatter class ElasticaFormatter extends NormalizerFormatter
{ {
@@ -48,7 +47,7 @@ class ElasticaFormatter extends NormalizerFormatter
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record) public function format(LogRecord $record)
{ {
$record = parent::format($record); $record = parent::format($record);
@@ -71,8 +70,6 @@ class ElasticaFormatter extends NormalizerFormatter
/** /**
* Convert a log message into an Elastica Document * Convert a log message into an Elastica Document
*
* @phpstan-param Record $record
*/ */
protected function getDocument(array $record): Document protected function getDocument(array $record): Document
{ {

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use DateTimeInterface; use DateTimeInterface;
use Monolog\LogRecord;
/** /**
* Format a log message into an Elasticsearch record * Format a log message into an Elasticsearch record
@@ -46,7 +47,7 @@ class ElasticsearchFormatter extends NormalizerFormatter
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record) public function format(LogRecord $record)
{ {
$record = parent::format($record); $record = parent::format($record);
@@ -79,7 +80,7 @@ class ElasticsearchFormatter extends NormalizerFormatter
* @param mixed[] $record Log message * @param mixed[] $record Log message
* @return mixed[] * @return mixed[]
*/ */
protected function getDocument(array $record): array protected function getDocument(LogRecord $record): array
{ {
$record['_index'] = $this->index; $record['_index'] = $this->index;
$record['_type'] = $this->type; $record['_type'] = $this->type;

View File

@@ -11,6 +11,8 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\LogRecord;
/** /**
* formats the record to be used in the FlowdockHandler * formats the record to be used in the FlowdockHandler
* *
@@ -39,7 +41,7 @@ class FlowdockFormatter implements FormatterInterface
* *
* @return mixed[] * @return mixed[]
*/ */
public function format(array $record): array public function format(LogRecord $record): array
{ {
$tags = [ $tags = [
'#logs', '#logs',

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Class FluentdFormatter * Class FluentdFormatter
@@ -55,7 +56,7 @@ class FluentdFormatter implements FormatterInterface
return $this->levelTag; return $this->levelTag;
} }
public function format(array $record): string public function format(LogRecord $record): string
{ {
$tag = $record['channel']; $tag = $record['channel'];
if ($this->levelTag) { if ($this->levelTag) {

View File

@@ -11,32 +11,28 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\LogRecord;
/** /**
* Interface for formatters * Interface for formatters
* *
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/ */
interface FormatterInterface interface FormatterInterface
{ {
/** /**
* Formats a log record. * Formats a log record.
* *
* @param array $record A record to format * @param LogRecord $record A record to format
* @return mixed The formatted record * @return mixed The formatted record
*
* @phpstan-param Record $record
*/ */
public function format(array $record); public function format(LogRecord $record);
/** /**
* Formats a set of log records. * Formats a set of log records.
* *
* @param array $records A set of records to format * @param array<LogRecord> $records A set of records to format
* @return mixed The formatted set of records * @return mixed The formatted set of records
*
* @phpstan-param Record[] $records
*/ */
public function formatBatch(array $records); public function formatBatch(array $records);
} }

View File

@@ -14,6 +14,7 @@ namespace Monolog\Formatter;
use Monolog\Logger; use Monolog\Logger;
use Gelf\Message; use Gelf\Message;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Serializes a log message to GELF * Serializes a log message to GELF
@@ -83,7 +84,7 @@ class GelfMessageFormatter extends NormalizerFormatter
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record): Message public function format(LogRecord $record): Message
{ {
$context = $extra = []; $context = $extra = [];
if (isset($record['context'])) { if (isset($record['context'])) {

View File

@@ -13,6 +13,7 @@ namespace Monolog\Formatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Formats incoming records into an HTML table * Formats incoming records into an HTML table
@@ -83,7 +84,7 @@ class HtmlFormatter extends NormalizerFormatter
* *
* @return string The formatted record * @return string The formatted record
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
$output = $this->addTitle($record['level_name'], $record['level']); $output = $this->addTitle($record['level_name'], $record['level']);
$output .= '<table cellspacing="1" width="100%" class="monolog-output">'; $output .= '<table cellspacing="1" width="100%" class="monolog-output">';

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Throwable; use Throwable;
use Monolog\LogRecord;
/** /**
* Encodes whatever record data is passed to it as json * Encodes whatever record data is passed to it as json
@@ -72,7 +73,7 @@ class JsonFormatter extends NormalizerFormatter
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
$normalized = $this->normalize($record); $normalized = $this->normalize($record);

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Formats incoming records into a one-line string * Formats incoming records into a one-line string
@@ -76,7 +77,7 @@ class LineFormatter extends NormalizerFormatter
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
$vars = parent::format($record); $vars = parent::format($record);

View File

@@ -11,6 +11,8 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\LogRecord;
/** /**
* Encodes message information into JSON in a format compatible with Loggly. * Encodes message information into JSON in a format compatible with Loggly.
* *
@@ -33,7 +35,7 @@ class LogglyFormatter extends JsonFormatter
* @see https://www.loggly.com/docs/automated-parsing/#json * @see https://www.loggly.com/docs/automated-parsing/#json
* @see \Monolog\Formatter\JsonFormatter::format() * @see \Monolog\Formatter\JsonFormatter::format()
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) { if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) {
$record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO");

View File

@@ -11,6 +11,8 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\LogRecord;
/** /**
* Encodes message information into JSON in a format compatible with Logmatic. * Encodes message information into JSON in a format compatible with Logmatic.
* *
@@ -50,7 +52,7 @@ class LogmaticFormatter extends JsonFormatter
* @see http://doc.logmatic.io/docs/basics-to-send-data * @see http://doc.logmatic.io/docs/basics-to-send-data
* @see \Monolog\Formatter\JsonFormatter::format() * @see \Monolog\Formatter\JsonFormatter::format()
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
if (!empty($this->hostname)) { if (!empty($this->hostname)) {
$record["hostname"] = $this->hostname; $record["hostname"] = $this->hostname;

View File

@@ -11,6 +11,8 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\LogRecord;
/** /**
* Serializes a log message to Logstash Event Format * Serializes a log message to Logstash Event Format
* *
@@ -61,7 +63,7 @@ class LogstashFormatter extends NormalizerFormatter
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
$record = parent::format($record); $record = parent::format($record);

View File

@@ -14,6 +14,7 @@ namespace Monolog\Formatter;
use MongoDB\BSON\Type; use MongoDB\BSON\Type;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Formats a record for use with the MongoDBHandler. * Formats a record for use with the MongoDBHandler.
@@ -46,7 +47,7 @@ class MongoDBFormatter implements FormatterInterface
* *
* @return mixed[] * @return mixed[]
*/ */
public function format(array $record): array public function format(LogRecord $record): array
{ {
/** @var mixed[] $res */ /** @var mixed[] $res */
$res = $this->formatArray($record); $res = $this->formatArray($record);

View File

@@ -14,6 +14,7 @@ namespace Monolog\Formatter;
use Monolog\DateTimeImmutable; use Monolog\DateTimeImmutable;
use Monolog\Utils; use Monolog\Utils;
use Throwable; use Throwable;
use Monolog\LogRecord;
/** /**
* Normalizes incoming records to remove objects/resources so it's easier to dump to various targets * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
@@ -50,8 +51,10 @@ class NormalizerFormatter implements FormatterInterface
* *
* @param mixed[] $record * @param mixed[] $record
*/ */
public function format(array $record) public function format(LogRecord $record)
{ {
$record = $record->toArray();
return $this->normalize($record); return $this->normalize($record);
} }

View File

@@ -11,6 +11,8 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\LogRecord;
/** /**
* Formats data into an associative array of scalar values. * Formats data into an associative array of scalar values.
* Objects and arrays will be JSON encoded. * Objects and arrays will be JSON encoded.
@@ -24,7 +26,7 @@ class ScalarFormatter extends NormalizerFormatter
* *
* @phpstan-return array<string, scalar|null> $record * @phpstan-return array<string, scalar|null> $record
*/ */
public function format(array $record): array public function format(LogRecord $record): array
{ {
$result = []; $result = [];
foreach ($record as $key => $value) { foreach ($record as $key => $value) {

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Serializes a log message according to Wildfire's header requirements * Serializes a log message according to Wildfire's header requirements
@@ -56,7 +57,7 @@ class WildfireFormatter extends NormalizerFormatter
* *
* @return string * @return string
*/ */
public function format(array $record): string public function format(LogRecord $record): string
{ {
// Retrieve the line and file if set and remove them from the formatted extra // Retrieve the line and file if set and remove them from the formatted extra
$file = $line = ''; $file = $line = '';

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Base Handler class providing basic level/bubble support * Base Handler class providing basic level/bubble support
@@ -48,7 +49,7 @@ abstract class AbstractHandler extends Handler implements ResettableInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return $record['level'] >= $this->level; return $record['level'] >= $this->level;
} }

View File

@@ -11,6 +11,8 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\LogRecord;
/** /**
* Base Handler class providing the Handler structure, including processors and formatters * Base Handler class providing the Handler structure, including processors and formatters
* *
@@ -32,14 +34,13 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if (!$this->isHandling($record)) { if (!$this->isHandling($record)) {
return false; return false;
} }
if ($this->processors) { if ($this->processors) {
/** @var Record $record */
$record = $this->processRecord($record); $record = $this->processRecord($record);
} }
@@ -55,7 +56,7 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
abstract protected function write(array $record): void; abstract protected function write(LogRecord $record): void;
/** /**
* @return void * @return void

View File

@@ -17,6 +17,7 @@ use Monolog\Formatter\JsonFormatter;
use PhpAmqpLib\Message\AMQPMessage; use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Channel\AMQPChannel; use PhpAmqpLib\Channel\AMQPChannel;
use AMQPExchange; use AMQPExchange;
use Monolog\LogRecord;
/** /**
* @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Record from \Monolog\Logger
@@ -54,7 +55,7 @@ class AmqpHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$data = $record["formatted"]; $data = $record["formatted"];
$routingKey = $this->getRoutingKey($record); $routingKey = $this->getRoutingKey($record);
@@ -113,7 +114,7 @@ class AmqpHandler extends AbstractProcessingHandler
* *
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
protected function getRoutingKey(array $record): string protected function getRoutingKey(LogRecord $record): string
{ {
$routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']); $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter; use Monolog\Formatter\LineFormatter;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
use function count; use function count;
use function headers_list; use function headers_list;
@@ -57,7 +58,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
// Accumulate records // Accumulate records
static::$records[] = $record; static::$records[] = $record;

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Buffers all records until closing the handler and then pass them as batch. * Buffers all records until closing the handler and then pass them as batch.
@@ -58,7 +59,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($record['level'] < $this->level) { if ($record['level'] < $this->level) {
return false; return false;

View File

@@ -15,6 +15,7 @@ use Monolog\Formatter\ChromePHPFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
@@ -115,7 +116,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
* @see sendHeader() * @see sendHeader()
* @see send() * @see send()
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!$this->isWebRequest()) { if (!$this->isWebRequest()) {
return; return;

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter; use Monolog\Formatter\JsonFormatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* CouchDB handler * CouchDB handler
@@ -44,7 +45,7 @@ class CouchDBHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$basicAuth = null; $basicAuth = null;
if ($this->options['username']) { if ($this->options['username']) {

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Logs to Cube. * Logs to Cube.
@@ -112,7 +113,7 @@ class CubeHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$date = $record['datetime']; $date = $record['datetime'];

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Simple handler wrapper that deduplicates log records across multiple requests * Simple handler wrapper that deduplicates log records across multiple requests
@@ -110,7 +111,7 @@ class DeduplicationHandler extends BufferHandler
/** /**
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
private function isDuplicate(array $record): bool private function isDuplicate(LogRecord $record): bool
{ {
if (!file_exists($this->deduplicationStore)) { if (!file_exists($this->deduplicationStore)) {
return false; return false;
@@ -179,7 +180,7 @@ class DeduplicationHandler extends BufferHandler
/** /**
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
private function appendRecord(array $record): void private function appendRecord(LogRecord $record): void
{ {
file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND); file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND);
} }

View File

@@ -15,6 +15,7 @@ use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Doctrine\CouchDB\CouchDBClient; use Doctrine\CouchDB\CouchDBClient;
use Monolog\LogRecord;
/** /**
* CouchDB handler for Doctrine CouchDB ODM * CouchDB handler for Doctrine CouchDB ODM
@@ -35,7 +36,7 @@ class DoctrineCouchDBHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->client->postDocument($record['formatted']); $this->client->postDocument($record['formatted']);
} }

View File

@@ -17,6 +17,7 @@ use Monolog\Formatter\FormatterInterface;
use Aws\DynamoDb\Marshaler; use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter; use Monolog\Formatter\ScalarFormatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
@@ -67,7 +68,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$filtered = $this->filterEmptyFields($record['formatted']); $filtered = $this->filterEmptyFields($record['formatted']);
if ($this->version === 3) { if ($this->version === 3) {
@@ -87,7 +88,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
* @param mixed[] $record * @param mixed[] $record
* @return mixed[] * @return mixed[]
*/ */
protected function filterEmptyFields(array $record): array protected function filterEmptyFields(LogRecord $record): array
{ {
return array_filter($record, function ($value) { return array_filter($record, function ($value) {
return !empty($value) || false === $value || 0 === $value; return !empty($value) || false === $value || 0 === $value;

View File

@@ -17,6 +17,7 @@ use Monolog\Formatter\ElasticaFormatter;
use Monolog\Logger; use Monolog\Logger;
use Elastica\Client; use Elastica\Client;
use Elastica\Exception\ExceptionInterface; use Elastica\Exception\ExceptionInterface;
use Monolog\LogRecord;
/** /**
* Elastic Search handler * Elastic Search handler
@@ -67,7 +68,7 @@ class ElasticaHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->bulkSend([$record['formatted']]); $this->bulkSend([$record['formatted']]);
} }

View File

@@ -19,6 +19,7 @@ use Monolog\Formatter\ElasticsearchFormatter;
use InvalidArgumentException; use InvalidArgumentException;
use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException; use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException;
use Elasticsearch\Client; use Elasticsearch\Client;
use Monolog\LogRecord;
/** /**
* Elasticsearch handler * Elasticsearch handler
@@ -74,7 +75,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->bulkSend([$record['formatted']]); $this->bulkSend([$record['formatted']]);
} }

View File

@@ -15,6 +15,7 @@ use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Stores to PHP error_log() handler. * Stores to PHP error_log() handler.
@@ -71,7 +72,7 @@ class ErrorLogHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!$this->expandNewlines) { if (!$this->expandNewlines) {
error_log((string) $record['formatted'], $this->messageType); error_log((string) $record['formatted'], $this->messageType);

View File

@@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Throwable; use Throwable;
use Monolog\LogRecord;
/** /**
* Forwards records to at most one handler * Forwards records to at most one handler
@@ -27,7 +28,7 @@ class FallbackGroupHandler extends GroupHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($this->processors) { if ($this->processors) {
/** @var Record $record */ /** @var Record $record */

View File

@@ -15,6 +15,7 @@ use Monolog\Logger;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Simple handler wrapper that filters records based on a list of levels * Simple handler wrapper that filters records based on a list of levels
@@ -111,7 +112,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return isset($this->acceptedLevels[$record['level']]); return isset($this->acceptedLevels[$record['level']]);
} }
@@ -119,7 +120,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if (!$this->isHandling($record)) { if (!$this->isHandling($record)) {
return false; return false;
@@ -161,7 +162,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
* *
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
public function getHandler(array $record = null) public function getHandler(LogRecord $record = null)
{ {
if (!$this->handler instanceof HandlerInterface) { if (!$this->handler instanceof HandlerInterface) {
$this->handler = ($this->handler)($record, $this); $this->handler = ($this->handler)($record, $this);

View File

@@ -11,6 +11,8 @@
namespace Monolog\Handler\FingersCrossed; namespace Monolog\Handler\FingersCrossed;
use Monolog\LogRecord;
/** /**
* Interface for activation strategies for the FingersCrossedHandler. * Interface for activation strategies for the FingersCrossedHandler.
* *
@@ -25,5 +27,5 @@ interface ActivationStrategyInterface
* *
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
public function isHandlerActivated(array $record): bool; public function isHandlerActivated(LogRecord $record): bool;
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler\FingersCrossed;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Channel and Error level based monolog activation strategy. Allows to trigger activation * Channel and Error level based monolog activation strategy. Allows to trigger activation
@@ -66,7 +67,7 @@ class ChannelLevelActivationStrategy implements ActivationStrategyInterface
/** /**
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
public function isHandlerActivated(array $record): bool public function isHandlerActivated(LogRecord $record): bool
{ {
if (isset($this->channelToActionLevel[$record['channel']])) { if (isset($this->channelToActionLevel[$record['channel']])) {
return $record['level'] >= $this->channelToActionLevel[$record['channel']]; return $record['level'] >= $this->channelToActionLevel[$record['channel']];

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler\FingersCrossed;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Error level based activation strategy. * Error level based activation strategy.
@@ -39,7 +40,7 @@ class ErrorLevelActivationStrategy implements ActivationStrategyInterface
$this->actionLevel = Logger::toMonologLevel($actionLevel); $this->actionLevel = Logger::toMonologLevel($actionLevel);
} }
public function isHandlerActivated(array $record): bool public function isHandlerActivated(LogRecord $record): bool
{ {
return $record['level'] >= $this->actionLevel; return $record['level'] >= $this->actionLevel;
} }

View File

@@ -17,6 +17,7 @@ use Monolog\Logger;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Buffers all records until a certain level is reached * Buffers all records until a certain level is reached
@@ -107,7 +108,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return true; return true;
} }
@@ -128,7 +129,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($this->processors) { if ($this->processors) {
/** @var Record $record */ /** @var Record $record */
@@ -210,7 +211,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
* *
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
public function getHandler(array $record = null) public function getHandler(LogRecord $record = null)
{ {
if (!$this->handler instanceof HandlerInterface) { if (!$this->handler instanceof HandlerInterface) {
$this->handler = ($this->handler)($record, $this); $this->handler = ($this->handler)($record, $this);

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\WildfireFormatter; use Monolog\Formatter\WildfireFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
@@ -88,7 +89,7 @@ class FirePHPHandler extends AbstractProcessingHandler
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
protected function createRecordHeader(array $record): array protected function createRecordHeader(LogRecord $record): array
{ {
// Wildfire is extensible to support multiple protocols & plugins in a single request, // 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. // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
@@ -140,7 +141,7 @@ class FirePHPHandler extends AbstractProcessingHandler
* @see sendHeader() * @see sendHeader()
* @see sendInitHeaders() * @see sendInitHeaders()
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!self::$sendHeaders || !$this->isWebRequest()) { if (!self::$sendHeaders || !$this->isWebRequest()) {
return; return;

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter; use Monolog\Formatter\LineFormatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Sends logs to Fleep.io using Webhook integrations * Sends logs to Fleep.io using Webhook integrations
@@ -89,7 +90,7 @@ class FleepHookHandler extends SocketHandler
/** /**
* Handles a log record * Handles a log record
*/ */
public function write(array $record): void public function write(LogRecord $record): void
{ {
parent::write($record); parent::write($record);
$this->closeSocket(); $this->closeSocket();
@@ -98,7 +99,7 @@ class FleepHookHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
$content = $this->buildContent($record); $content = $this->buildContent($record);
@@ -124,7 +125,7 @@ class FleepHookHandler extends SocketHandler
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
private function buildContent(array $record): string private function buildContent(LogRecord $record): string
{ {
$dataArray = [ $dataArray = [
'message' => $record['formatted'], 'message' => $record['formatted'],

View File

@@ -15,6 +15,7 @@ use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\Formatter\FlowdockFormatter; use Monolog\Formatter\FlowdockFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Sends notifications through the Flowdock push API * Sends notifications through the Flowdock push API
@@ -89,7 +90,7 @@ class FlowdockHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
parent::write($record); parent::write($record);
@@ -99,7 +100,7 @@ class FlowdockHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
$content = $this->buildContent($record); $content = $this->buildContent($record);
@@ -111,7 +112,7 @@ class FlowdockHandler extends SocketHandler
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
private function buildContent(array $record): string private function buildContent(LogRecord $record): string
{ {
return Utils::jsonEncode($record['formatted']['flowdock']); return Utils::jsonEncode($record['formatted']['flowdock']);
} }

View File

@@ -15,6 +15,7 @@ use Gelf\PublisherInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter; use Monolog\Formatter\GelfMessageFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Handler to send messages to a Graylog2 (http://www.graylog2.org) server * Handler to send messages to a Graylog2 (http://www.graylog2.org) server
@@ -42,7 +43,7 @@ class GelfHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->publisher->publish($record['formatted']); $this->publisher->publish($record['formatted']);
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\LogRecord;
/** /**
* Forwards records to multiple handlers * Forwards records to multiple handlers
@@ -49,7 +50,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
foreach ($this->handlers as $handler) { foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) { if ($handler->isHandling($record)) {
@@ -63,7 +64,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($this->processors) { if ($this->processors) {
/** @var Record $record */ /** @var Record $record */

View File

@@ -11,12 +11,13 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\LogRecord;
/** /**
* Interface that all Monolog Handlers must implement * Interface that all Monolog Handlers must implement
* *
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
* *
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger
*/ */
interface HandlerInterface interface HandlerInterface
@@ -30,13 +31,11 @@ interface HandlerInterface
* is no guarantee that handle() will not be called, and isHandling() might not be called * is no guarantee that handle() will not be called, and isHandling() might not be called
* for a given record. * for a given record.
* *
* @param array $record Partial log record containing only a level key * @param LogRecord $record Partial log record having only a level initialized
* *
* @return bool * @return bool
*
* @phpstan-param array{level: Level} $record
*/ */
public function isHandling(array $record): bool; public function isHandling(LogRecord $record): bool;
/** /**
* Handles a record. * Handles a record.
@@ -48,20 +47,16 @@ interface HandlerInterface
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on * Unless the bubbling is interrupted (by returning true), the Logger class will keep on
* calling further handlers in the stack with a given log record. * calling further handlers in the stack with a given log record.
* *
* @param array $record The record to handle * @param LogRecord $record The record to handle
* @return bool true means that this handler handled the record, and that bubbling is not permitted. * @return bool 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. * false means the record was either not processed or that this handler allows bubbling.
*
* @phpstan-param Record $record
*/ */
public function handle(array $record): bool; public function handle(LogRecord $record): bool;
/** /**
* Handles a set of records at once. * Handles a set of records at once.
* *
* @param array $records The records to handle (an array of record arrays) * @param array<LogRecord> $records The records to handle
*
* @phpstan-param Record[] $records
*/ */
public function handleBatch(array $records): void; public function handleBatch(array $records): void;

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* This simple wrapper class can be used to extend handlers functionality. * This simple wrapper class can be used to extend handlers functionality.
@@ -21,7 +22,7 @@ use Monolog\Formatter\FormatterInterface;
* *
* Inherit from this class and override handle() like this: * Inherit from this class and override handle() like this:
* *
* public function handle(array $record) * public function handle(LogRecord $record)
* { * {
* if ($record meets certain conditions) { * if ($record meets certain conditions) {
* return false; * return false;
@@ -46,7 +47,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return $this->handler->isHandling($record); return $this->handler->isHandling($record);
} }
@@ -54,7 +55,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
return $this->handler->handle($record); return $this->handler->handle($record);
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* IFTTTHandler uses cURL to trigger IFTTT Maker actions * IFTTTHandler uses cURL to trigger IFTTT Maker actions
@@ -51,7 +52,7 @@ class IFTTTHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function write(array $record): void public function write(LogRecord $record): void
{ {
$postData = [ $postData = [
"value1" => $record["channel"], "value1" => $record["channel"],

View File

@@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Inspired on LogEntriesHandler. * Inspired on LogEntriesHandler.
@@ -69,7 +70,7 @@ class InsightOpsHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
return $this->logToken . ' ' . $record['formatted']; return $this->logToken . ' ' . $record['formatted'];
} }

View File

@@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* @author Robert Kaufmann III <rok3@rok3.me> * @author Robert Kaufmann III <rok3@rok3.me>
@@ -63,7 +64,7 @@ class LogEntriesHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
return $this->logToken . ' ' . $record['formatted']; return $this->logToken . ' ' . $record['formatted'];
} }

View File

@@ -16,6 +16,7 @@ use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogglyFormatter; use Monolog\Formatter\LogglyFormatter;
use function array_key_exists; use function array_key_exists;
use CurlHandle; use CurlHandle;
use Monolog\LogRecord;
/** /**
* Sends errors to Loggly. * Sends errors to Loggly.
@@ -119,7 +120,7 @@ class LogglyHandler extends AbstractProcessingHandler
return $this; return $this;
} }
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->send($record["formatted"], static::ENDPOINT_SINGLE); $this->send($record["formatted"], static::ENDPOINT_SINGLE);
} }

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogmaticFormatter; use Monolog\Formatter\LogmaticFormatter;
use Monolog\LogRecord;
/** /**
* @author Julien Breux <julien.breux@gmail.com> * @author Julien Breux <julien.breux@gmail.com>
@@ -82,7 +83,7 @@ class LogmaticHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
return $this->logToken . ' ' . $record['formatted']; return $this->logToken . ' ' . $record['formatted'];
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\HtmlFormatter; use Monolog\Formatter\HtmlFormatter;
use Monolog\LogRecord;
/** /**
* Base class for all mail handlers * Base class for all mail handlers
@@ -57,7 +58,7 @@ abstract class MailHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->send((string) $record['formatted'], [$record]); $this->send((string) $record['formatted'], [$record]);
} }

View File

@@ -17,6 +17,7 @@ use MongoDB\Client;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\MongoDBFormatter; use Monolog\Formatter\MongoDBFormatter;
use Monolog\LogRecord;
/** /**
* Logs to a MongoDB database. * Logs to a MongoDB database.
@@ -63,7 +64,7 @@ class MongoDBHandler extends AbstractProcessingHandler
parent::__construct($level, $bubble); parent::__construct($level, $bubble);
} }
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (isset($this->collection)) { if (isset($this->collection)) {
$this->collection->insertOne($record['formatted']); $this->collection->insertOne($record['formatted']);

View File

@@ -15,6 +15,7 @@ use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Class to record a log on a NewRelic application. * Class to record a log on a NewRelic application.
@@ -73,7 +74,7 @@ class NewRelicHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!$this->isNewRelicEnabled()) { if (!$this->isNewRelicEnabled()) {
throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');

View File

@@ -11,6 +11,8 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\LogRecord;
/** /**
* No-op * No-op
* *
@@ -25,7 +27,7 @@ class NoopHandler extends Handler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return true; return true;
} }
@@ -33,7 +35,7 @@ class NoopHandler extends Handler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
return false; return false;
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Blackhole * Blackhole
@@ -45,7 +46,7 @@ class NullHandler extends Handler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return $record['level'] >= $this->level; return $record['level'] >= $this->level;
} }
@@ -53,7 +54,7 @@ class NullHandler extends Handler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
return $record['level'] >= $this->level; return $record['level'] >= $this->level;
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Handler to only pass log messages when a certain threshold of number of messages is reached. * Handler to only pass log messages when a certain threshold of number of messages is reached.
@@ -87,7 +88,7 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter
* *
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($record['level'] < $this->level) { if ($record['level'] < $this->level) {
return false; return false;

View File

@@ -18,6 +18,7 @@ use Monolog\Utils;
use PhpConsole\Connector; use PhpConsole\Connector;
use PhpConsole\Handler as VendorPhpConsoleHandler; use PhpConsole\Handler as VendorPhpConsoleHandler;
use PhpConsole\Helper; use PhpConsole\Helper;
use Monolog\LogRecord;
/** /**
* Monolog handler for Google Chrome extension "PHP Console" * Monolog handler for Google Chrome extension "PHP Console"
@@ -167,7 +168,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
return $this->options; return $this->options;
} }
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($this->options['enabled'] && $this->connector->isActiveClient()) { if ($this->options['enabled'] && $this->connector->isActiveClient()) {
return parent::handle($record); return parent::handle($record);
@@ -179,7 +180,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
/** /**
* Writes the record down to the log of the implementing handler * Writes the record down to the log of the implementing handler
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if ($record['level'] < Logger::NOTICE) { if ($record['level'] < Logger::NOTICE) {
$this->handleDebugRecord($record); $this->handleDebugRecord($record);
@@ -193,7 +194,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
/** /**
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
private function handleDebugRecord(array $record): void private function handleDebugRecord(LogRecord $record): void
{ {
$tags = $this->getRecordTags($record); $tags = $this->getRecordTags($record);
$message = $record['message']; $message = $record['message'];
@@ -206,7 +207,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
/** /**
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
private function handleExceptionRecord(array $record): void private function handleExceptionRecord(LogRecord $record): void
{ {
$this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']); $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
} }
@@ -214,7 +215,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
/** /**
* @phpstan-param Record $record * @phpstan-param Record $record
*/ */
private function handleErrorRecord(array $record): void private function handleErrorRecord(LogRecord $record): void
{ {
$context = $record['context']; $context = $record['context'];

View File

@@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Stores to STDIN of any process, specified by a command. * Stores to STDIN of any process, specified by a command.
@@ -83,7 +84,7 @@ class ProcessHandler extends AbstractProcessingHandler
* *
* @throws \UnexpectedValueException * @throws \UnexpectedValueException
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->ensureProcessIsStarted(); $this->ensureProcessIsStarted();

View File

@@ -13,19 +13,18 @@ namespace Monolog\Handler;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\Processor\ProcessorInterface; use Monolog\Processor\ProcessorInterface;
use Monolog\LogRecord;
/** /**
* Helper trait for implementing ProcessableInterface * Helper trait for implementing ProcessableInterface
* *
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
*
* @phpstan-import-type Record from \Monolog\Logger
*/ */
trait ProcessableHandlerTrait trait ProcessableHandlerTrait
{ {
/** /**
* @var callable[] * @var callable[]
* @phpstan-var array<ProcessorInterface|callable(Record): Record> * @phpstan-var array<array<(callable(LogRecord): LogRecord)|ProcessorInterface>>
*/ */
protected $processors = []; protected $processors = [];
@@ -51,13 +50,7 @@ trait ProcessableHandlerTrait
return array_shift($this->processors); return array_shift($this->processors);
} }
/** protected function processRecord(LogRecord $record): LogRecord
* Processes a record.
*
* @phpstan-param Record $record
* @phpstan-return Record
*/
protected function processRecord(array $record): array
{ {
foreach ($this->processors as $processor) { foreach ($this->processors as $processor) {
$record = $processor($record); $record = $processor($record);

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Proxies log messages to an existing PSR-3 compliant logger. * Proxies log messages to an existing PSR-3 compliant logger.
@@ -51,7 +52,7 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if (!$this->isHandling($record)) { if (!$this->isHandling($record)) {
return false; return false;

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Sends notifications through the pushover api to mobile phones * Sends notifications through the pushover api to mobile phones
@@ -136,7 +137,7 @@ class PushoverHandler extends SocketHandler
$this->expire = $expire; $this->expire = $expire;
} }
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
$content = $this->buildContent($record); $content = $this->buildContent($record);
@@ -146,7 +147,7 @@ class PushoverHandler extends SocketHandler
/** /**
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
private function buildContent(array $record): string private function buildContent(LogRecord $record): string
{ {
// Pushover has a limit of 512 characters on title and message combined. // Pushover has a limit of 512 characters on title and message combined.
$maxMessageLength = 512 - strlen($this->title); $maxMessageLength = 512 - strlen($this->title);
@@ -198,7 +199,7 @@ class PushoverHandler extends SocketHandler
return $header; return $header;
} }
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
foreach ($this->users as $user) { foreach ($this->users as $user) {
$this->user = $user; $this->user = $user;

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter; use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Logs to a Redis key using rpush * Logs to a Redis key using rpush
@@ -58,7 +59,7 @@ class RedisHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if ($this->capSize) { if ($this->capSize) {
$this->writeCapped($record); $this->writeCapped($record);
@@ -73,7 +74,7 @@ class RedisHandler extends AbstractProcessingHandler
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
protected function writeCapped(array $record): void protected function writeCapped(LogRecord $record): void
{ {
if ($this->redisClient instanceof \Redis) { if ($this->redisClient instanceof \Redis) {
$mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1; $mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1;

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter; use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Sends the message to a Redis Pub/Sub channel using PUBLISH * Sends the message to a Redis Pub/Sub channel using PUBLISH
@@ -52,7 +53,7 @@ class RedisPubSubHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->redisClient->publish($this->channelKey, $record["formatted"]); $this->redisClient->publish($this->channelKey, $record["formatted"]);
} }

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Rollbar\RollbarLogger; use Rollbar\RollbarLogger;
use Throwable; use Throwable;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Sends errors to Rollbar * Sends errors to Rollbar
@@ -73,7 +74,7 @@ class RollbarHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!$this->initialized) { if (!$this->initialized) {
// __destructor() doesn't get called on Fatal errors // __destructor() doesn't get called on Fatal errors

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use InvalidArgumentException; use InvalidArgumentException;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Stores logs to files that are rotated every day and a limited number of files are kept. * Stores logs to files that are rotated every day and a limited number of files are kept.
@@ -110,7 +111,7 @@ class RotatingFileHandler extends StreamHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
// on the first record written, if the log is new, we should rotate (once per day) // on the first record written, if the log is new, we should rotate (once per day)
if (null === $this->mustRotate) { if (null === $this->mustRotate) {

View File

@@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Sampling handler * Sampling handler
@@ -62,12 +63,12 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter
} }
} }
public function isHandling(array $record): bool public function isHandling(LogRecord $record): bool
{ {
return $this->getHandler($record)->isHandling($record); return $this->getHandler($record)->isHandling($record);
} }
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
if ($this->processors) { if ($this->processors) {
@@ -90,7 +91,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter
* *
* @return HandlerInterface * @return HandlerInterface
*/ */
public function getHandler(array $record = null) public function getHandler(LogRecord $record = null)
{ {
if (!$this->handler instanceof HandlerInterface) { if (!$this->handler instanceof HandlerInterface) {
$this->handler = ($this->handler)($record, $this); $this->handler = ($this->handler)($record, $this);

View File

@@ -15,6 +15,7 @@ use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\LogRecord;
/** /**
* Slack record utility helping to log to Slack webhooks or API. * Slack record utility helping to log to Slack webhooks or API.
@@ -124,7 +125,7 @@ class SlackRecord
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
* @phpstan-return mixed[] * @phpstan-return mixed[]
*/ */
public function getSlackData(array $record): array public function getSlackData(LogRecord $record): array
{ {
$dataArray = array(); $dataArray = array();
$record = $this->removeExcludedFields($record); $record = $this->removeExcludedFields($record);
@@ -364,7 +365,7 @@ class SlackRecord
* *
* @return mixed[] * @return mixed[]
*/ */
private function removeExcludedFields(array $record): array private function removeExcludedFields(LogRecord $record): array
{ {
foreach ($this->excludeFields as $field) { foreach ($this->excludeFields as $field) {
$keys = explode('.', $field); $keys = explode('.', $field);

View File

@@ -15,6 +15,7 @@ use Monolog\Formatter\FormatterInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord; use Monolog\Handler\Slack\SlackRecord;
use Monolog\LogRecord;
/** /**
* Sends notifications through Slack API * Sends notifications through Slack API
@@ -107,7 +108,7 @@ class SlackHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
$content = $this->buildContent($record); $content = $this->buildContent($record);
@@ -119,7 +120,7 @@ class SlackHandler extends SocketHandler
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
private function buildContent(array $record): string private function buildContent(LogRecord $record): string
{ {
$dataArray = $this->prepareContentData($record); $dataArray = $this->prepareContentData($record);
@@ -130,7 +131,7 @@ class SlackHandler extends SocketHandler
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
* @return string[] * @return string[]
*/ */
protected function prepareContentData(array $record): array protected function prepareContentData(LogRecord $record): array
{ {
$dataArray = $this->slackRecord->getSlackData($record); $dataArray = $this->slackRecord->getSlackData($record);
$dataArray['token'] = $this->token; $dataArray['token'] = $this->token;
@@ -159,7 +160,7 @@ class SlackHandler extends SocketHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
parent::write($record); parent::write($record);
$this->finalizeWrite(); $this->finalizeWrite();

View File

@@ -15,6 +15,7 @@ use Monolog\Formatter\FormatterInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord; use Monolog\Handler\Slack\SlackRecord;
use Monolog\LogRecord;
/** /**
* Sends notifications through Slack Webhooks * Sends notifications through Slack Webhooks
@@ -90,7 +91,7 @@ class SlackWebhookHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$postData = $this->slackRecord->getSlackData($record); $postData = $this->slackRecord->getSlackData($record);
$postString = Utils::jsonEncode($postData); $postString = Utils::jsonEncode($postData);

View File

@@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Stores to any socket - uses fsockopen() or pfsockopen(). * Stores to any socket - uses fsockopen() or pfsockopen().
@@ -92,7 +93,7 @@ class SocketHandler extends AbstractProcessingHandler
* @throws \UnexpectedValueException * @throws \UnexpectedValueException
* @throws \RuntimeException * @throws \RuntimeException
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->connectIfNotConnected(); $this->connectIfNotConnected();
$data = $this->generateDataStream($record); $data = $this->generateDataStream($record);
@@ -345,7 +346,7 @@ class SocketHandler extends AbstractProcessingHandler
/** /**
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
protected function generateDataStream(array $record): string protected function generateDataStream(LogRecord $record): string
{ {
return (string) $record['formatted']; return (string) $record['formatted'];
} }

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Aws\Sqs\SqsClient; use Aws\Sqs\SqsClient;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Writes to any sqs queue. * Writes to any sqs queue.
@@ -43,7 +44,7 @@ class SqsHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) { if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) {
throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record)); throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record));

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Stores to any stream resource * Stores to any stream resource
@@ -125,7 +126,7 @@ class StreamHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!is_resource($this->stream)) { if (!is_resource($this->stream)) {
$url = $this->url; $url = $this->url;
@@ -173,7 +174,7 @@ class StreamHandler extends AbstractProcessingHandler
* *
* @phpstan-param FormattedRecord $record * @phpstan-param FormattedRecord $record
*/ */
protected function streamWrite($stream, array $record): void protected function streamWrite($stream, LogRecord $record): void
{ {
fwrite($stream, (string) $record['formatted']); fwrite($stream, (string) $record['formatted']);
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Logs to syslog service. * Logs to syslog service.
@@ -58,7 +59,7 @@ class SyslogHandler extends AbstractSyslogHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
if (!openlog($this->ident, $this->logopts, $this->facility)) { if (!openlog($this->ident, $this->logopts, $this->facility)) {
throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"' . Utils::getRecordMessageForException($record)); throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"' . Utils::getRecordMessageForException($record));

View File

@@ -15,6 +15,7 @@ use DateTimeInterface;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Handler\SyslogUdp\UdpSocket; use Monolog\Handler\SyslogUdp\UdpSocket;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* A Handler for logging to a remote syslogd server. * A Handler for logging to a remote syslogd server.
@@ -67,7 +68,7 @@ class SyslogUdpHandler extends AbstractSyslogHandler
$this->socket = new UdpSocket($host, $port); $this->socket = new UdpSocket($host, $port);
} }
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$lines = $this->splitMessageIntoLines($record['formatted']); $lines = $this->splitMessageIntoLines($record['formatted']);

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use RuntimeException; use RuntimeException;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Handler send logs to Telegram using Telegram Bot API. * Handler send logs to Telegram using Telegram Bot API.
@@ -209,7 +210,7 @@ class TelegramBotHandler extends AbstractProcessingHandler
/** /**
* @inheritDoc * @inheritDoc
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->send($record['formatted']); $this->send($record['formatted']);
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Used for testing purposes. * Used for testing purposes.
@@ -66,23 +67,20 @@ use Psr\Log\LogLevel;
* @method bool hasInfoThatPasses($message) * @method bool hasInfoThatPasses($message)
* @method bool hasDebugThatPasses($message) * @method bool hasDebugThatPasses($message)
* *
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger
* @phpstan-import-type LevelName from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger
*/ */
class TestHandler extends AbstractProcessingHandler class TestHandler extends AbstractProcessingHandler
{ {
/** @var Record[] */ /** @var LogRecord[] */
protected $records = []; protected $records = [];
/** @var array<Level, Record[]> */ /** @var array<Level, LogRecord[]> */
protected $recordsByLevel = []; protected $recordsByLevel = [];
/** @var bool */ /** @var bool */
private $skipReset = false; private $skipReset = false;
/** /**
* @return array * @return array<LogRecord>
*
* @phpstan-return Record[]
*/ */
public function getRecords() public function getRecords()
{ {
@@ -127,7 +125,7 @@ class TestHandler extends AbstractProcessingHandler
} }
/** /**
* @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records * @param string|LogRecord $record Either a message string or an array containing message and optionally context keys that will be checked against all records
* @param string|int $level Logging level value or name * @param string|int $level Logging level value or name
* *
* @phpstan-param array{message: string, context?: mixed[]}|string $record * @phpstan-param array{message: string, context?: mixed[]}|string $record
@@ -139,11 +137,11 @@ class TestHandler extends AbstractProcessingHandler
$record = array('message' => $record); $record = array('message' => $record);
} }
return $this->hasRecordThatPasses(function ($rec) use ($record) { return $this->hasRecordThatPasses(function (LogRecord $rec) use ($record) {
if ($rec['message'] !== $record['message']) { if ($rec->message !== $record['message']) {
return false; return false;
} }
if (isset($record['context']) && $rec['context'] !== $record['context']) { if (isset($record['context']) && $rec->context !== $record['context']) {
return false; return false;
} }
@@ -179,7 +177,7 @@ class TestHandler extends AbstractProcessingHandler
* @param string|int $level Logging level value or name * @param string|int $level Logging level value or name
* @return bool * @return bool
* *
* @psalm-param callable(Record, int): mixed $predicate * @psalm-param callable(LogRecord, int): mixed $predicate
* @phpstan-param Level|LevelName|LogLevel::* $level * @phpstan-param Level|LevelName|LogLevel::* $level
*/ */
public function hasRecordThatPasses(callable $predicate, $level) public function hasRecordThatPasses(callable $predicate, $level)
@@ -202,7 +200,7 @@ class TestHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->recordsByLevel[$record['level']][] = $record; $this->recordsByLevel[$record['level']][] = $record;
$this->records[] = $record; $this->records[] = $record;

View File

@@ -11,6 +11,8 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\LogRecord;
/** /**
* Forwards records to multiple handlers suppressing failures of each handler * Forwards records to multiple handlers suppressing failures of each handler
* and continuing through to give every handler a chance to succeed. * and continuing through to give every handler a chance to succeed.
@@ -24,7 +26,7 @@ class WhatFailureGroupHandler extends GroupHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handle(array $record): bool public function handle(LogRecord $record): bool
{ {
if ($this->processors) { if ($this->processors) {
/** @var Record $record */ /** @var Record $record */

View File

@@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\NormalizerFormatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
/** /**
* Handler sending logs to Zend Monitor * Handler sending logs to Zend Monitor
@@ -59,7 +60,7 @@ class ZendMonitorHandler extends AbstractProcessingHandler
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function write(array $record): void protected function write(LogRecord $record): void
{ {
$this->writeZendMonitorCustomEvent( $this->writeZendMonitorCustomEvent(
Logger::getLevelName($record['level']), Logger::getLevelName($record['level']),

View File

@@ -14,21 +14,109 @@ namespace Monolog;
use ArrayAccess; use ArrayAccess;
/** /**
* Monolog log record interface for forward compatibility with Monolog 3.0 * Monolog log record
*
* This is just present in Monolog 2.4+ to allow interoperable code to be written against
* both versions by type-hinting arguments as `array|\Monolog\LogRecord $record`
*
* Do not rely on this interface for other purposes, and do not implement it.
* *
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
* @template-extends \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', mixed> * @template-implements \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra', int|string|\DateTimeImmutable|array<mixed>>
* @phpstan-import-type Record from Logger * @phpstan-import-type Level from Logger
* @phpstan-import-type LevelName from Logger
*/ */
interface LogRecord extends \ArrayAccess class LogRecord implements \ArrayAccess
{ {
private const MODIFIABLE_FIELDS = [
'extra' => true,
'formatted' => true,
];
/** @var 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY' */
public readonly string $levelName; // TODO enum?
public function __construct(
public readonly \DateTimeImmutable $datetime,
public readonly string $channel,
/** @var Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY */
public readonly int $level, // TODO enum?
public readonly string $message,
/** @var array<mixed> */
public readonly array $context = [],
/** @var array<mixed> */
public array $extra = [],
public mixed $formatted = null,
) {
$this->levelName = Logger::getLevelName($level);
}
public function offsetSet(mixed $offset, mixed $value): void
{
if ($offset === 'extra') {
if (!is_array($value)) {
throw new \InvalidArgumentException('extra must be an array');
}
$this->extra = $value;
return;
}
if ($offset === 'formatted') {
$this->formatted = $value;
return;
}
throw new \LogicException('Unsupported operation: setting '.$offset);
}
public function offsetExists(mixed $offset): bool
{
if ($offset === 'level_name') {
return true;
}
return isset($this->{$offset});
}
public function offsetUnset(mixed $offset): void
{
throw new \LogicException('Unsupported operation');
}
public function &offsetGet(mixed $offset): mixed
{
if ($offset === 'level_name') {
$offset = 'levelName';
}
if (isset(self::MODIFIABLE_FIELDS[$offset])) {
return $this->{$offset};
}
// avoid returning readonly props by ref as this is illegal
$copy = $this->{$offset};
return $copy;
}
/** /**
* @phpstan-return Record * @phpstan-return array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
*/ */
public function toArray(): array; public function toArray(): array
{
return [
'message' => $this->message,
'context' => $this->context,
'level' => $this->level,
'level_name' => $this->levelName,
'channel' => $this->channel,
'datetime' => $this->datetime,
'extra' => $this->extra,
];
}
public function with(mixed ...$args): self
{
foreach (['message', 'context', 'level', 'channel', 'datetime', 'extra'] as $prop) {
$args[$prop] ??= $this->{$prop};
}
return new self(...$args);
}
} }

View File

@@ -13,6 +13,7 @@ namespace Monolog;
use DateTimeZone; use DateTimeZone;
use Monolog\Handler\HandlerInterface; use Monolog\Handler\HandlerInterface;
use Monolog\Processor\ProcessorInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException; use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
@@ -29,7 +30,6 @@ use Stringable;
* *
* @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY
* @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY' * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY'
* @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
*/ */
class Logger implements LoggerInterface, ResettableInterface class Logger implements LoggerInterface, ResettableInterface
{ {
@@ -128,7 +128,7 @@ class Logger implements LoggerInterface, ResettableInterface
* *
* To process records of a single handler instead, add the processor on that specific handler * To process records of a single handler instead, add the processor on that specific handler
* *
* @var callable[] * @var array<(callable(LogRecord): LogRecord)|ProcessorInterface>
*/ */
protected $processors; protected $processors;
@@ -148,12 +148,12 @@ class Logger implements LoggerInterface, ResettableInterface
protected $exceptionHandler; protected $exceptionHandler;
/** /**
* @psalm-param array<callable(array): array> $processors
*
* @param string $name The logging channel, a simple descriptive name that is attached to all log records * @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 HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
* @param callable[] $processors Optional array of processors * @param callable[] $processors Optional array of processors
* @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used * @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used
*
* @phpstan-param array<(callable(LogRecord): LogRecord)|ProcessorInterface> $processors
*/ */
public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null) public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null)
{ {
@@ -291,31 +291,29 @@ class Logger implements LoggerInterface, ResettableInterface
*/ */
public function addRecord(int $level, string $message, array $context = []): bool public function addRecord(int $level, string $message, array $context = []): bool
{ {
$record = null; $recordInitialized = count($this->processors) === 0;
$record = new LogRecord(
message: $message,
context: $context,
level: $level,
channel: $this->name,
datetime: new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
extra: [],
);
foreach ($this->handlers as $handler) { foreach ($this->handlers as $handler) {
if (null === $record) { if (false === $recordInitialized) {
// skip creating the record as long as no handler is going to handle it // skip initializing the record as long as no handler is going to handle it
if (!$handler->isHandling(['level' => $level])) { if (!$handler->isHandling($record)) {
continue; continue;
} }
$levelName = static::getLevelName($level);
$record = [
'message' => $message,
'context' => $context,
'level' => $level,
'level_name' => $levelName,
'channel' => $this->name,
'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
'extra' => [],
];
try { try {
foreach ($this->processors as $processor) { foreach ($this->processors as $processor) {
$record = $processor($record); $record = $processor($record);
} }
$recordInitialized = true;
} catch (Throwable $e) { } catch (Throwable $e) {
$this->handleException($e, $record); $this->handleException($e, $record);
@@ -323,7 +321,7 @@ class Logger implements LoggerInterface, ResettableInterface
} }
} }
// once the record exists, send it to all handlers as long as the bubbling chain is not interrupted // once the record is initialized, send it to all handlers as long as the bubbling chain is not interrupted
try { try {
if (true === $handler->handle($record)) { if (true === $handler->handle($record)) {
break; break;
@@ -449,9 +447,12 @@ class Logger implements LoggerInterface, ResettableInterface
*/ */
public function isHandling(int $level): bool public function isHandling(int $level): bool
{ {
$record = [ $record = new LogRecord(
'level' => $level, datetime: new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
]; channel: $this->name,
message: '',
level: $level,
);
foreach ($this->handlers as $handler) { foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) { if ($handler->isHandling($record)) {
@@ -490,7 +491,7 @@ class Logger implements LoggerInterface, ResettableInterface
* *
* @phpstan-param Level|LevelName|LogLevel::* $level * @phpstan-param Level|LevelName|LogLevel::* $level
*/ */
public function log($level, $message, array $context = []): void public function log($level, string|\Stringable $message, array $context = []): void
{ {
if (!is_int($level) && !is_string($level)) { if (!is_int($level) && !is_string($level)) {
throw new \InvalidArgumentException('$level is expected to be a string or int'); throw new \InvalidArgumentException('$level is expected to be a string or int');
@@ -509,7 +510,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function debug($message, array $context = []): void public function debug(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::DEBUG, (string) $message, $context); $this->addRecord(static::DEBUG, (string) $message, $context);
} }
@@ -522,7 +523,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function info($message, array $context = []): void public function info(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::INFO, (string) $message, $context); $this->addRecord(static::INFO, (string) $message, $context);
} }
@@ -535,7 +536,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function notice($message, array $context = []): void public function notice(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::NOTICE, (string) $message, $context); $this->addRecord(static::NOTICE, (string) $message, $context);
} }
@@ -548,7 +549,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function warning($message, array $context = []): void public function warning(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::WARNING, (string) $message, $context); $this->addRecord(static::WARNING, (string) $message, $context);
} }
@@ -561,7 +562,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function error($message, array $context = []): void public function error(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::ERROR, (string) $message, $context); $this->addRecord(static::ERROR, (string) $message, $context);
} }
@@ -574,7 +575,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function critical($message, array $context = []): void public function critical(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::CRITICAL, (string) $message, $context); $this->addRecord(static::CRITICAL, (string) $message, $context);
} }
@@ -587,7 +588,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function alert($message, array $context = []): void public function alert(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::ALERT, (string) $message, $context); $this->addRecord(static::ALERT, (string) $message, $context);
} }
@@ -600,7 +601,7 @@ class Logger implements LoggerInterface, ResettableInterface
* @param string|Stringable $message The log message * @param string|Stringable $message The log message
* @param mixed[] $context The log context * @param mixed[] $context The log context
*/ */
public function emergency($message, array $context = []): void public function emergency(string|\Stringable $message, array $context = []): void
{ {
$this->addRecord(static::EMERGENCY, (string) $message, $context); $this->addRecord(static::EMERGENCY, (string) $message, $context);
} }
@@ -626,11 +627,8 @@ class Logger implements LoggerInterface, ResettableInterface
/** /**
* Delegates exception management to the custom exception handler, * Delegates exception management to the custom exception handler,
* or throws the exception if no custom handler is set. * or throws the exception if no custom handler is set.
*
* @param array $record
* @phpstan-param Record $record
*/ */
protected function handleException(Throwable $e, array $record): void protected function handleException(Throwable $e, LogRecord $record): void
{ {
if (!$this->exceptionHandler) { if (!$this->exceptionHandler) {
throw $e; throw $e;

View File

@@ -13,6 +13,7 @@ namespace Monolog\Processor;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Injects Git branch and Git commit SHA in all records * Injects Git branch and Git commit SHA in all records
@@ -43,7 +44,7 @@ class GitProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
// return if the level is not high enough // return if the level is not high enough
if ($record['level'] < $this->level) { if ($record['level'] < $this->level) {

View File

@@ -11,6 +11,8 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* Injects value of gethostname in all records * Injects value of gethostname in all records
*/ */
@@ -27,7 +29,7 @@ class HostnameProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
$record['extra']['hostname'] = self::$host; $record['extra']['hostname'] = self::$host;

View File

@@ -13,6 +13,7 @@ namespace Monolog\Processor;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Injects line/file:class/function where the log message came from * Injects line/file:class/function where the log message came from
@@ -58,7 +59,7 @@ class IntrospectionProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
// return if the level is not high enough // return if the level is not high enough
if ($record['level'] < $this->level) { if ($record['level'] < $this->level) {

View File

@@ -11,6 +11,8 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* Injects memory_get_peak_usage in all records * Injects memory_get_peak_usage in all records
* *
@@ -22,7 +24,7 @@ class MemoryPeakUsageProcessor extends MemoryProcessor
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
$usage = memory_get_peak_usage($this->realUsage); $usage = memory_get_peak_usage($this->realUsage);

View File

@@ -11,6 +11,8 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* Injects memory_get_usage in all records * Injects memory_get_usage in all records
* *
@@ -22,7 +24,7 @@ class MemoryUsageProcessor extends MemoryProcessor
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
$usage = memory_get_usage($this->realUsage); $usage = memory_get_usage($this->realUsage);

View File

@@ -13,6 +13,7 @@ namespace Monolog\Processor;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\LogRecord;
/** /**
* Injects Hg branch and Hg revision number in all records * Injects Hg branch and Hg revision number in all records
@@ -42,7 +43,7 @@ class MercurialProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
// return if the level is not high enough // return if the level is not high enough
if ($record['level'] < $this->level) { if ($record['level'] < $this->level) {

View File

@@ -11,6 +11,8 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* Adds value of getmypid into records * Adds value of getmypid into records
* *
@@ -21,7 +23,7 @@ class ProcessIdProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
$record['extra']['process_id'] = getmypid(); $record['extra']['process_id'] = getmypid();

View File

@@ -11,20 +11,17 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* An optional interface to allow labelling Monolog processors. * An optional interface to allow labelling Monolog processors.
* *
* @author Nicolas Grekas <p@tchwork.com> * @author Nicolas Grekas <p@tchwork.com>
*
* @phpstan-import-type Record from \Monolog\Logger
*/ */
interface ProcessorInterface interface ProcessorInterface
{ {
/** /**
* @return array The processed record * @return LogRecord The processed record
*
* @phpstan-param Record $record
* @phpstan-return Record
*/ */
public function __invoke(array $record); public function __invoke(LogRecord $record);
} }

View File

@@ -12,6 +12,7 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\Utils; use Monolog\Utils;
use Monolog\LogRecord;
/** /**
* Processes a record's message according to PSR-3 rules * Processes a record's message according to PSR-3 rules
@@ -43,14 +44,16 @@ class PsrLogMessageProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
if (false === strpos($record['message'], '{')) { if (false === strpos($record['message'], '{')) {
return $record; return $record;
} }
$replacements = []; $replacements = [];
foreach ($record['context'] as $key => $val) { $context = $record['context'];
foreach ($context as $key => $val) {
$placeholder = '{' . $key . '}'; $placeholder = '{' . $key . '}';
if (strpos($record['message'], $placeholder) === false) { if (strpos($record['message'], $placeholder) === false) {
continue; continue;
@@ -75,12 +78,10 @@ class PsrLogMessageProcessor implements ProcessorInterface
} }
if ($this->removeUsedContextFields) { if ($this->removeUsedContextFields) {
unset($record['context'][$key]); unset($context[$key]);
} }
} }
$record['message'] = strtr($record['message'], $replacements); return $record->with(message: strtr($record['message'], $replacements), context: $context);
return $record;
} }
} }

View File

@@ -11,6 +11,8 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* Adds a tags array into record * Adds a tags array into record
* *
@@ -52,9 +54,9 @@ class TagProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
$record['extra']['tags'] = $this->tags; $record->extra['tags'] = $this->tags;
return $record; return $record;
} }

View File

@@ -12,6 +12,7 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\ResettableInterface; use Monolog\ResettableInterface;
use Monolog\LogRecord;
/** /**
* Adds a unique identifier into records * Adds a unique identifier into records
@@ -35,7 +36,7 @@ class UidProcessor implements ProcessorInterface, ResettableInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
$record['extra']['uid'] = $this->uid; $record['extra']['uid'] = $this->uid;

View File

@@ -11,6 +11,8 @@
namespace Monolog\Processor; namespace Monolog\Processor;
use Monolog\LogRecord;
/** /**
* Injects url/method and remote IP of the current web request in all records * Injects url/method and remote IP of the current web request in all records
* *
@@ -76,7 +78,7 @@ class WebProcessor implements ProcessorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function __invoke(array $record): array public function __invoke(LogRecord $record): LogRecord
{ {
// skip processing if for some reason request data // skip processing if for some reason request data
// is not present (CLI or wonky SAPIs) // is not present (CLI or wonky SAPIs)

View File

@@ -12,6 +12,7 @@
namespace Monolog\Test; namespace Monolog\Test;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
use Monolog\DateTimeImmutable; use Monolog\DateTimeImmutable;
use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\FormatterInterface;
@@ -20,7 +21,6 @@ use Monolog\Formatter\FormatterInterface;
* *
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
* *
* @phpstan-import-type Record from \Monolog\Logger
* @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger
*/ */
class TestCase extends \PHPUnit\Framework\TestCase class TestCase extends \PHPUnit\Framework\TestCase
@@ -28,26 +28,22 @@ class TestCase extends \PHPUnit\Framework\TestCase
/** /**
* @param mixed[] $context * @param mixed[] $context
* *
* @return array Record
*
* @phpstan-param Level $level * @phpstan-param Level $level
* @phpstan-return Record
*/ */
protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []): array protected function getRecord(int $level = Logger::WARNING, string|\Stringable $message = 'test', array $context = [], string $channel = 'test', \DateTimeImmutable $datetime = new DateTimeImmutable(true), array $extra = []): LogRecord
{ {
return [ return new LogRecord(
'message' => (string) $message, message: (string) $message,
'context' => $context, context: $context,
'level' => $level, level: $level,
'level_name' => Logger::getLevelName($level), channel: $channel,
'channel' => 'test', datetime: $datetime,
'datetime' => new DateTimeImmutable(true), extra: $extra,
'extra' => [], );
];
} }
/** /**
* @phpstan-return Record[] * @phpstan-return list<LogRecord>
*/ */
protected function getMultipleRecords(): array protected function getMultipleRecords(): array
{ {
@@ -66,7 +62,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
$formatter->expects($this->any()) $formatter->expects($this->any())
->method('format') ->method('format')
->will($this->returnCallback(function ($record) { ->will($this->returnCallback(function ($record) {
return $record['message']; return $record->message;
})); }));
return $formatter; return $formatter;

View File

@@ -261,24 +261,21 @@ final class Utils
return $val; return $val;
} }
/** public static function getRecordMessageForException(LogRecord $record): string
* @param array<mixed> $record
*/
public static function getRecordMessageForException(array $record): string
{ {
$context = ''; $context = '';
$extra = ''; $extra = '';
try { try {
if ($record['context']) { if ($record->context) {
$context = "\nContext: " . json_encode($record['context']); $context = "\nContext: " . json_encode($record->context);
} }
if ($record['extra']) { if ($record->extra) {
$extra = "\nExtra: " . json_encode($record['extra']); $extra = "\nExtra: " . json_encode($record->extra);
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
// noop // noop
} }
return "\nThe exception occurred while attempting to log: " . $record['message'] . $context . $extra; return "\nThe exception occurred while attempting to log: " . $record->message . $context . $extra;
} }
} }

View File

@@ -12,6 +12,7 @@
namespace Monolog\Formatter; namespace Monolog\Formatter;
use Monolog\Logger; use Monolog\Logger;
use Monolog\LogRecord;
class ElasticaFormatterTest extends \PHPUnit\Framework\TestCase class ElasticaFormatterTest extends \PHPUnit\Framework\TestCase
{ {
@@ -30,18 +31,18 @@ class ElasticaFormatterTest extends \PHPUnit\Framework\TestCase
public function testFormat() public function testFormat()
{ {
// test log message // test log message
$msg = [ $msg = new LogRecord(
'level' => Logger::ERROR, level: Logger::ERROR,
'level_name' => 'ERROR', levelName: 'ERROR',
'channel' => 'meh', channel: 'meh',
'context' => ['foo' => 7, 'bar', 'class' => new \stdClass], context: ['foo' => 7, 'bar', 'class' => new \stdClass],
'datetime' => new \DateTimeImmutable("@0"), datetime: new \DateTimeImmutable("@0"),
'extra' => [], message: 'log',
'message' => 'log', );
];
// expected values // expected values
$expected = $msg; $expected = (array) $msg;
unset($expected['formatted']);
$expected['datetime'] = '1970-01-01T00:00:00.000000+00:00'; $expected['datetime'] = '1970-01-01T00:00:00.000000+00:00';
$expected['context'] = [ $expected['context'] = [
'class' => ['stdClass' => []], 'class' => ['stdClass' => []],

View File

@@ -152,7 +152,7 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
$path = str_replace('\\/', '/', json_encode(__FILE__)); $path = str_replace('\\/', '/', json_encode(__FILE__));
$this->assertRegexp('{^\['.date('Y-m-d').'] core\.CRITICAL: foobar \{"exception":"\[object] \(RuntimeException\(code: 0\): Foo at '.preg_quote(substr($path, 1, -1)).':'.(__LINE__ - 8).'\)\n\[stacktrace]\n#0}', $message); $this->assertMatchesRegularExpression('{^\['.date('Y-m-d').'] core\.CRITICAL: foobar \{"exception":"\[object] \(RuntimeException\(code: 0\): Foo at '.preg_quote(substr($path, 1, -1)).':'.(__LINE__ - 8).'\)\n\[stacktrace]\n#0}', $message);
} }
public function testDefFormatWithPreviousException() public function testDefFormatWithPreviousException()
@@ -242,7 +242,7 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
] ]
); );
$this->assertRegExp('/foo bar/', $message); $this->assertMatchesRegularExpression('/foo bar/', $message);
} }
public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet() public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet()
@@ -256,7 +256,7 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase
] ]
); );
$this->assertRegExp('/foo\nbar/', $message); $this->assertMatchesRegularExpression('/foo\nbar/', $message);
} }
} }

Some files were not shown because too many files have changed in this diff Show More