mirror of
https://github.com/Seldaek/monolog.git
synced 2025-07-31 02:10:22 +02:00
Bump phpstan to level 8
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
parameters:
|
||||
level: 6
|
||||
level: 8
|
||||
|
||||
treatPhpDocTypesAsCertain: false
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
@@ -19,7 +19,16 @@ parameters:
|
||||
paths:
|
||||
- src/Monolog/Handler/LogglyHandler.php
|
||||
|
||||
# blocked until we only support php8+
|
||||
- '#Parameter \#1 \$socket of function (socket_close|socket_sendto|socket_send) expects Socket, resource\|Socket(\|null)? given\.#'
|
||||
- '#Parameter \#1 \$handle of function (curl_exec|curl_close|curl_error|curl_errno|curl_setopt) expects CurlHandle, CurlHandle\|resource(\|null)? given\.#'
|
||||
|
||||
# blocked by https://github.com/phpstan/phpstan/issues/5091
|
||||
- '#has unknown class Monolog\\Handler\\Record#'
|
||||
- '#::processRecord#'
|
||||
- '#::processRecord\(\) should return array#'
|
||||
- '#::processRecord\(\) has invalid type#'
|
||||
- '#::processRecord\(\) return type has no value type#'
|
||||
- '#::processRecord\(\) has parameter \$record with no value type#'
|
||||
- '#::popProcessor\(\) should return callable#'
|
||||
- '#Parameter \#1 \$ of callable \(callable\(Monolog\\Handler\\Record\): Monolog\\Handler\\Record\)#'
|
||||
- '#is incompatible with native type array.#'
|
||||
|
@@ -65,6 +65,7 @@ class ElasticaFormatter extends NormalizerFormatter
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
@@ -78,6 +79,7 @@ class ElasticaFormatter extends NormalizerFormatter
|
||||
$document = new Document();
|
||||
$document->setData($record);
|
||||
if (method_exists($document, 'setType')) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$document->setType($this->type);
|
||||
}
|
||||
$document->setIndex($this->index);
|
||||
|
@@ -20,6 +20,8 @@ use Monolog\Utils;
|
||||
* @see http://docs.graylog.org/en/latest/pages/gelf.html
|
||||
*
|
||||
* @author Matt Lehner <mlehner@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
class GelfMessageFormatter extends NormalizerFormatter
|
||||
{
|
||||
@@ -49,6 +51,8 @@ class GelfMessageFormatter extends NormalizerFormatter
|
||||
* Translates Monolog log levels to Graylog2 log priorities.
|
||||
*
|
||||
* @var array<int, int>
|
||||
*
|
||||
* @phpstan-var array<Level, int>
|
||||
*/
|
||||
private $logLevels = [
|
||||
Logger::DEBUG => 7,
|
||||
@@ -65,7 +69,7 @@ class GelfMessageFormatter extends NormalizerFormatter
|
||||
{
|
||||
parent::__construct('U.u');
|
||||
|
||||
$this->systemName = (is_null($systemName) || $systemName === '') ? gethostname() : $systemName;
|
||||
$this->systemName = (is_null($systemName) || $systemName === '') ? (string) gethostname() : $systemName;
|
||||
|
||||
$this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix;
|
||||
$this->contextPrefix = $contextPrefix;
|
||||
@@ -73,15 +77,18 @@ class GelfMessageFormatter extends NormalizerFormatter
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record): Message
|
||||
{
|
||||
$context = $extra = [];
|
||||
if (isset($record['context'])) {
|
||||
$record['context'] = parent::format($record['context']);
|
||||
/** @var mixed[] $context */
|
||||
$context = parent::normalize($record['context']);
|
||||
}
|
||||
if (isset($record['extra'])) {
|
||||
$record['extra'] = parent::format($record['extra']);
|
||||
/** @var mixed[] $extra */
|
||||
$extra = parent::normalize($record['extra']);
|
||||
}
|
||||
|
||||
if (!isset($record['datetime'], $record['message'], $record['level'])) {
|
||||
@@ -105,31 +112,31 @@ class GelfMessageFormatter extends NormalizerFormatter
|
||||
if (isset($record['channel'])) {
|
||||
$message->setFacility($record['channel']);
|
||||
}
|
||||
if (isset($record['extra']['line'])) {
|
||||
$message->setLine($record['extra']['line']);
|
||||
unset($record['extra']['line']);
|
||||
if (isset($extra['line'])) {
|
||||
$message->setLine($extra['line']);
|
||||
unset($extra['line']);
|
||||
}
|
||||
if (isset($record['extra']['file'])) {
|
||||
$message->setFile($record['extra']['file']);
|
||||
unset($record['extra']['file']);
|
||||
if (isset($extra['file'])) {
|
||||
$message->setFile($extra['file']);
|
||||
unset($extra['file']);
|
||||
}
|
||||
|
||||
foreach ($record['extra'] as $key => $val) {
|
||||
foreach ($extra as $key => $val) {
|
||||
$val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
|
||||
$len = strlen($this->extraPrefix . $key . $val);
|
||||
if ($len > $this->maxLength) {
|
||||
$message->setAdditional($this->extraPrefix . $key, Utils::substr($val, 0, $this->maxLength));
|
||||
$message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
|
||||
|
||||
continue;
|
||||
}
|
||||
$message->setAdditional($this->extraPrefix . $key, $val);
|
||||
}
|
||||
|
||||
foreach ($record['context'] as $key => $val) {
|
||||
foreach ($context as $key => $val) {
|
||||
$val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
|
||||
$len = strlen($this->contextPrefix . $key . $val);
|
||||
if ($len > $this->maxLength) {
|
||||
$message->setAdditional($this->contextPrefix . $key, Utils::substr($val, 0, $this->maxLength));
|
||||
$message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -137,8 +144,8 @@ class GelfMessageFormatter extends NormalizerFormatter
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (null === $message->getFile() && isset($record['context']['exception']['file'])) {
|
||||
if (preg_match("/^(.+):([0-9]+)$/", $record['context']['exception']['file'], $matches)) {
|
||||
if (null === $message->getFile() && isset($context['exception']['file'])) {
|
||||
if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
|
||||
$message->setFile($matches[1]);
|
||||
$message->setLine($matches[2]);
|
||||
}
|
||||
|
@@ -110,6 +110,9 @@ class LineFormatter extends NormalizerFormatter
|
||||
// remove leftover %extra.xxx% and %context.xxx% if any
|
||||
if (false !== strpos($output, '%')) {
|
||||
$output = preg_replace('/%(?:extra|context)\..+?%/', '', $output);
|
||||
if (null === $output) {
|
||||
throw new \RuntimeException('Failed to run preg_replace: ' . preg_last_error() . ' / ' . preg_last_error_msg());
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
|
@@ -52,7 +52,7 @@ class LogstashFormatter extends NormalizerFormatter
|
||||
// logstash requires a ISO 8601 format date with optional millisecond precision.
|
||||
parent::__construct('Y-m-d\TH:i:s.uP');
|
||||
|
||||
$this->systemName = $systemName === null ? gethostname() : $systemName;
|
||||
$this->systemName = $systemName === null ? (string) gethostname() : $systemName;
|
||||
$this->applicationName = $applicationName;
|
||||
$this->extraKey = $extraKey;
|
||||
$this->contextKey = $contextKey;
|
||||
|
@@ -37,23 +37,26 @@ class MongoDBFormatter implements FormatterInterface
|
||||
$this->maxNestingLevel = max($maxNestingLevel, 0);
|
||||
$this->exceptionTraceAsString = $exceptionTraceAsString;
|
||||
|
||||
$this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare(phpversion('mongodb'), '1.1.9', '<=');
|
||||
$this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<=');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return scalar[]
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function format(array $record): array
|
||||
{
|
||||
return $this->formatArray($record);
|
||||
/** @var mixed[] $res */
|
||||
$res = $this->formatArray($record);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return array<scalar[]>
|
||||
* @return array<mixed[]>
|
||||
*/
|
||||
public function formatBatch(array $records): array
|
||||
{
|
||||
@@ -152,6 +155,7 @@ class MongoDBFormatter implements FormatterInterface
|
||||
? (int) $milliseconds
|
||||
: (string) $milliseconds;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
return new UTCDateTime($milliseconds);
|
||||
}
|
||||
}
|
||||
|
@@ -47,6 +47,8 @@ class NormalizerFormatter implements FormatterInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param mixed[] $record
|
||||
*/
|
||||
public function format(array $record)
|
||||
{
|
||||
@@ -123,7 +125,7 @@ class NormalizerFormatter implements FormatterInterface
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @return scalar|array<scalar>
|
||||
* @return null|scalar|array<array|scalar|null>
|
||||
*/
|
||||
protected function normalize($data, int $depth = 0)
|
||||
{
|
||||
|
@@ -22,20 +22,21 @@ class ScalarFormatter extends NormalizerFormatter
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @phpstan-return scalar[] $record
|
||||
* @phpstan-return array<string, scalar|null> $record
|
||||
*/
|
||||
public function format(array $record): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($record as $key => $value) {
|
||||
$record[$key] = $this->normalizeValue($value);
|
||||
$result[$key] = $this->normalizeValue($value);
|
||||
}
|
||||
|
||||
return $record;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return string|int|bool|null
|
||||
* @param mixed $value
|
||||
* @return scalar|null
|
||||
*/
|
||||
protected function normalizeValue($value)
|
||||
{
|
||||
|
@@ -69,6 +69,7 @@ class WildfireFormatter extends NormalizerFormatter
|
||||
unset($record['extra']['line']);
|
||||
}
|
||||
|
||||
/** @var mixed[] $record */
|
||||
$record = $this->normalize($record);
|
||||
$message = ['message' => $record['message']];
|
||||
$handleError = false;
|
||||
@@ -125,7 +126,7 @@ class WildfireFormatter extends NormalizerFormatter
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return scalar|array<scalar>|object
|
||||
* @return null|scalar|array<array|scalar|null>|object
|
||||
*/
|
||||
protected function normalize($data, int $depth = 0)
|
||||
{
|
||||
|
@@ -21,6 +21,7 @@ namespace Monolog\Handler;
|
||||
*
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed}
|
||||
*/
|
||||
abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
|
||||
@@ -38,6 +39,7 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
|
@@ -94,6 +94,7 @@ class AmqpHandler extends AbstractProcessingHandler
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
$data = $this->getFormatter()->format($record);
|
||||
|
||||
|
@@ -197,7 +197,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
|
||||
static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
|
||||
static $labels = [];
|
||||
|
||||
return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function (array $m) use ($string, &$colors, &$labels) {
|
||||
$style = preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function (array $m) use ($string, &$colors, &$labels) {
|
||||
if (trim($m[1]) === 'autolabel') {
|
||||
// Format the string as a label with consistent auto assigned background color
|
||||
if (!isset($labels[$string])) {
|
||||
@@ -210,6 +210,12 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
|
||||
|
||||
return $m[1];
|
||||
}, $style);
|
||||
|
||||
if (null === $style) {
|
||||
throw new \RuntimeException('Failed to run preg_replace_callback: ' . preg_last_error() . ' / ' . preg_last_error_msg());
|
||||
}
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -80,6 +80,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
|
@@ -22,6 +22,8 @@ use Monolog\Utils;
|
||||
* This also works out of the box with Firefox 43+
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class ChromePHPHandler extends AbstractProcessingHandler
|
||||
{
|
||||
@@ -87,7 +89,9 @@ class ChromePHPHandler extends AbstractProcessingHandler
|
||||
if ($record['level'] < $this->level) {
|
||||
continue;
|
||||
}
|
||||
$messages[] = $this->processRecord($record);
|
||||
/** @var Record $message */
|
||||
$message = $this->processRecord($record);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
|
@@ -46,7 +46,7 @@ class CubeHandler extends AbstractProcessingHandler
|
||||
{
|
||||
$urlInfo = parse_url($url);
|
||||
|
||||
if (!isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
|
||||
if ($urlInfo === false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
|
||||
throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
|
||||
}
|
||||
|
||||
@@ -76,11 +76,12 @@ class CubeHandler extends AbstractProcessingHandler
|
||||
throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
|
||||
}
|
||||
|
||||
$this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
|
||||
if (!$this->udpConnection) {
|
||||
$udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
|
||||
if (false === $udpConnection) {
|
||||
throw new \LogicException('Unable to create a socket');
|
||||
}
|
||||
|
||||
$this->udpConnection = $udpConnection;
|
||||
if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
|
||||
throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
|
||||
}
|
||||
@@ -98,12 +99,12 @@ class CubeHandler extends AbstractProcessingHandler
|
||||
throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler');
|
||||
}
|
||||
|
||||
$this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put');
|
||||
|
||||
if (!$this->httpConnection) {
|
||||
$httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put');
|
||||
if (false === $httpConnection) {
|
||||
throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
|
||||
}
|
||||
|
||||
$this->httpConnection = $httpConnection;
|
||||
curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
|
||||
}
|
||||
@@ -150,6 +151,10 @@ class CubeHandler extends AbstractProcessingHandler
|
||||
$this->connectHttp();
|
||||
}
|
||||
|
||||
if (null === $this->httpConnection) {
|
||||
throw new \LogicException('No connection could be established');
|
||||
}
|
||||
|
||||
curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']');
|
||||
curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Simple handler wrapper that deduplicates log records across multiple requests
|
||||
@@ -34,6 +35,8 @@ use Monolog\Logger;
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
class DeduplicationHandler extends BufferHandler
|
||||
{
|
||||
@@ -43,7 +46,7 @@ class DeduplicationHandler extends BufferHandler
|
||||
protected $deduplicationStore;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @var Level
|
||||
*/
|
||||
protected $deduplicationLevel;
|
||||
|
||||
@@ -63,6 +66,8 @@ class DeduplicationHandler extends BufferHandler
|
||||
* @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
|
||||
* @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel
|
||||
*/
|
||||
public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true)
|
||||
{
|
||||
|
@@ -79,6 +79,9 @@ class ErrorLogHandler extends AbstractProcessingHandler
|
||||
}
|
||||
|
||||
$lines = preg_split('{[\r\n]+}', (string) $record['formatted']);
|
||||
if ($lines === false) {
|
||||
throw new \RuntimeException('Failed to preg_split formatted string: '.preg_last_error().' / '.preg_last_error_msg());
|
||||
}
|
||||
foreach ($lines as $line) {
|
||||
error_log($line, $this->messageType);
|
||||
}
|
||||
|
@@ -13,6 +13,15 @@ namespace Monolog\Handler;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Forwards records to at most one handler
|
||||
*
|
||||
* If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
|
||||
*
|
||||
* As soon as one handler handles a record successfully, the handling stops there.
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class FallbackGroupHandler extends GroupHandler
|
||||
{
|
||||
/**
|
||||
@@ -21,6 +30,7 @@ class FallbackGroupHandler extends GroupHandler
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
foreach ($this->handlers as $handler) {
|
||||
@@ -45,6 +55,7 @@ class FallbackGroupHandler extends GroupHandler
|
||||
foreach ($records as $record) {
|
||||
$processed[] = $this->processRecord($record);
|
||||
}
|
||||
/** @var Record[] $records */
|
||||
$records = $processed;
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $maxLevel
|
||||
*/
|
||||
public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true)
|
||||
{
|
||||
@@ -89,6 +90,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
|
||||
* @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $maxLevel
|
||||
*/
|
||||
public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY): self
|
||||
{
|
||||
@@ -124,6 +126,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Monolog\Handler\FingersCrossed;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Channel and Error level based monolog activation strategy. Allows to trigger activation
|
||||
@@ -35,11 +36,12 @@ use Monolog\Logger;
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @var Level
|
||||
*/
|
||||
private $defaultActionLevel;
|
||||
|
||||
@@ -52,7 +54,8 @@ class ChannelLevelActivationStrategy implements ActivationStrategyInterface
|
||||
* @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any
|
||||
* @param array<string, int> $channelToActionLevel An array that maps channel names to action levels.
|
||||
*
|
||||
* @phpstan-param array<string, Level> $channelToActionLevel
|
||||
* @phpstan-param array<string, Level> $channelToActionLevel
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel
|
||||
*/
|
||||
public function __construct($defaultActionLevel, array $channelToActionLevel = [])
|
||||
{
|
||||
|
@@ -12,21 +12,27 @@
|
||||
namespace Monolog\Handler\FingersCrossed;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Error level based activation strategy.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @var Level
|
||||
*/
|
||||
private $actionLevel;
|
||||
|
||||
/**
|
||||
* @param int|string $actionLevel Level or name or value
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $actionLevel
|
||||
*/
|
||||
public function __construct($actionLevel)
|
||||
{
|
||||
|
@@ -16,6 +16,7 @@ use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\ResettableInterface;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Buffers all records until a certain level is reached
|
||||
@@ -73,6 +74,9 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
|
||||
* @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $passthruLevel
|
||||
* @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy
|
||||
*/
|
||||
public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null)
|
||||
{
|
||||
@@ -127,6 +131,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
@@ -152,7 +157,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
|
||||
{
|
||||
$this->flushBuffer();
|
||||
|
||||
$this->handler->close();
|
||||
$this->getHandler()->close();
|
||||
}
|
||||
|
||||
public function reset()
|
||||
|
@@ -67,11 +67,15 @@ class FirePHPHandler extends AbstractProcessingHandler
|
||||
* @param string $message Log message
|
||||
*
|
||||
* @return array<string, string> Complete header string ready for the client as key and message as value
|
||||
*
|
||||
* @phpstan-return non-empty-array<string, string>
|
||||
*/
|
||||
protected function createHeader(array $meta, string $message): array
|
||||
{
|
||||
$header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta));
|
||||
|
||||
// See https://github.com/phpstan/phpstan/issues/5219
|
||||
// @phpstan-ignore-next-line
|
||||
return [$header => $message];
|
||||
}
|
||||
|
||||
@@ -80,6 +84,8 @@ class FirePHPHandler extends AbstractProcessingHandler
|
||||
*
|
||||
* @return array<string, string>
|
||||
*
|
||||
* @phpstan-return non-empty-array<string, string>
|
||||
*
|
||||
* @see createHeader()
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
|
@@ -43,8 +43,6 @@ class FleepHookHandler extends SocketHandler
|
||||
* see https://fleep.io/integrations/webhooks/
|
||||
*
|
||||
* @param string $token Webhook token
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @throws MissingExtensionException
|
||||
*/
|
||||
public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
|
||||
|
@@ -37,9 +37,6 @@ class FlowdockHandler extends SocketHandler
|
||||
protected $apiToken;
|
||||
|
||||
/**
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*
|
||||
* @throws MissingExtensionException if OpenSSL is missing
|
||||
*/
|
||||
public function __construct(string $apiToken, $level = Logger::DEBUG, bool $bubble = true)
|
||||
|
@@ -25,12 +25,12 @@ use Monolog\Formatter\FormatterInterface;
|
||||
class GelfHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var PublisherInterface|null the publisher object that sends the message to the server
|
||||
* @var PublisherInterface the publisher object that sends the message to the server
|
||||
*/
|
||||
protected $publisher;
|
||||
|
||||
/**
|
||||
* @param PublisherInterface $publisher a publisher object
|
||||
* @param PublisherInterface $publisher a gelf publisher object
|
||||
*/
|
||||
public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
|
@@ -18,6 +18,8 @@ use Monolog\ResettableInterface;
|
||||
* Forwards records to multiple handlers
|
||||
*
|
||||
* @author Lenar Lõhmus <lenar@city.ee>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface
|
||||
{
|
||||
@@ -45,7 +47,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
@@ -59,11 +61,12 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
@@ -75,7 +78,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
@@ -84,6 +87,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
|
||||
foreach ($records as $record) {
|
||||
$processed[] = $this->processRecord($record);
|
||||
}
|
||||
/** @var Record[] $records */
|
||||
$records = $processed;
|
||||
}
|
||||
|
||||
@@ -113,7 +117,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
|
@@ -30,8 +30,6 @@ class InsightOpsHandler extends SocketHandler
|
||||
* @param string $token Log token supplied by InsightOps
|
||||
* @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
|
||||
* @param bool $useSSL Whether or not SSL encryption should be used
|
||||
* @param string|int $level The minimum logging level to trigger this handler
|
||||
* @param bool $bubble Whether or not messages that are handled should bubble up the stack.
|
||||
*
|
||||
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
|
||||
*/
|
||||
|
@@ -26,8 +26,6 @@ class LogEntriesHandler extends SocketHandler
|
||||
/**
|
||||
* @param string $token Log token supplied by LogEntries
|
||||
* @param bool $useSSL Whether or not SSL encryption should be used.
|
||||
* @param string|int $level The minimum logging level to trigger this handler
|
||||
* @param bool $bubble Whether or not messages that are handled should bubble up the stack.
|
||||
* @param string $host Custom hostname to send the data to if needed
|
||||
*
|
||||
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
|
||||
|
@@ -40,8 +40,6 @@ class LogmaticHandler extends SocketHandler
|
||||
* @param string $hostname Host name supplied by Logmatic.
|
||||
* @param string $appname Application name supplied by Logmatic.
|
||||
* @param bool $useSSL Whether or not SSL encryption should be used.
|
||||
* @param int|string $level The minimum logging level to trigger this handler.
|
||||
* @param bool $bubble Whether or not messages that are handled should bubble up the stack.
|
||||
*
|
||||
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
|
||||
*/
|
||||
|
@@ -34,7 +34,9 @@ abstract class MailHandler extends AbstractProcessingHandler
|
||||
if ($record['level'] < $this->level) {
|
||||
continue;
|
||||
}
|
||||
$messages[] = $this->processRecord($record);
|
||||
/** @var Record $message */
|
||||
$message = $this->processRecord($record);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
@@ -61,7 +63,7 @@ abstract class MailHandler extends AbstractProcessingHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record[] $records
|
||||
* @phpstan-param non-empty-array<Record> $records
|
||||
* @phpstan-return Record
|
||||
*/
|
||||
protected function getHighestRecord(array $records): array
|
||||
|
@@ -162,7 +162,7 @@ class ProcessHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
protected function readProcessErrors(): string
|
||||
{
|
||||
return stream_get_contents($this->pipes[2]);
|
||||
return (string) stream_get_contents($this->pipes[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -13,6 +13,7 @@ namespace Monolog\Handler;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Sends notifications through the pushover api to mobile phones
|
||||
@@ -21,6 +22,8 @@ use Monolog\Utils;
|
||||
* @see https://www.pushover.net/api
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class PushoverHandler extends SocketHandler
|
||||
{
|
||||
@@ -28,7 +31,7 @@ class PushoverHandler extends SocketHandler
|
||||
private $token;
|
||||
/** @var array<int|string> */
|
||||
private $users;
|
||||
/** @var ?string */
|
||||
/** @var string */
|
||||
private $title;
|
||||
/** @var string|int|null */
|
||||
private $user = null;
|
||||
@@ -80,8 +83,6 @@ class PushoverHandler extends SocketHandler
|
||||
* @param string $token Pushover api token
|
||||
* @param string|array $users Pushover user id or array of ids the message will be sent to
|
||||
* @param string|null $title Title sent to the Pushover API
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
|
||||
* the pushover.net app owner. OpenSSL is required for this option.
|
||||
* @param string|int $highPriorityLevel The minimum logging level at which this handler will start
|
||||
@@ -93,7 +94,9 @@ class PushoverHandler extends SocketHandler
|
||||
* @param int $expire The expire parameter specifies how many seconds your notification will continue
|
||||
* to be retried for (every retry seconds).
|
||||
*
|
||||
* @phpstan-param string|array<int|string> $users
|
||||
* @phpstan-param string|array<int|string> $users
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel
|
||||
*/
|
||||
public function __construct(
|
||||
string $token,
|
||||
@@ -112,7 +115,7 @@ class PushoverHandler extends SocketHandler
|
||||
|
||||
$this->token = $token;
|
||||
$this->users = (array) $users;
|
||||
$this->title = $title ?: gethostname();
|
||||
$this->title = $title ?: (string) gethostname();
|
||||
$this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
|
||||
$this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
|
||||
$this->retry = $retry;
|
||||
@@ -195,6 +198,8 @@ class PushoverHandler extends SocketHandler
|
||||
|
||||
/**
|
||||
* @param int|string $value
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $value
|
||||
*/
|
||||
public function setHighPriorityLevel($value): self
|
||||
{
|
||||
@@ -205,6 +210,8 @@ class PushoverHandler extends SocketHandler
|
||||
|
||||
/**
|
||||
* @param int|string $value
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $value
|
||||
*/
|
||||
public function setEmergencyLevel($value): self
|
||||
{
|
||||
|
@@ -97,6 +97,7 @@ class RollbarHandler extends AbstractProcessingHandler
|
||||
$toLog = $record['message'];
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$this->rollbarLogger->log($context['level'], $toLog, $context);
|
||||
|
||||
$this->hasRecords = true;
|
||||
|
@@ -46,8 +46,6 @@ class RotatingFileHandler extends StreamHandler
|
||||
/**
|
||||
* @param string $filename
|
||||
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
|
||||
* @param bool $useLocking Try to lock log file before doing any writes
|
||||
*/
|
||||
@@ -116,7 +114,7 @@ class RotatingFileHandler extends StreamHandler
|
||||
{
|
||||
// on the first record written, if the log is new, we should rotate (once per day)
|
||||
if (null === $this->mustRotate) {
|
||||
$this->mustRotate = !file_exists($this->url);
|
||||
$this->mustRotate = null === $this->url || !file_exists($this->url);
|
||||
}
|
||||
|
||||
if ($this->nextRotation <= $record['datetime']) {
|
||||
@@ -142,6 +140,11 @@ class RotatingFileHandler extends StreamHandler
|
||||
}
|
||||
|
||||
$logFiles = glob($this->getGlobPattern());
|
||||
if (false === $logFiles) {
|
||||
// failed to glob
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->maxFiles >= count($logFiles)) {
|
||||
// no files to remove
|
||||
return;
|
||||
@@ -176,7 +179,7 @@ class RotatingFileHandler extends StreamHandler
|
||||
$fileInfo['dirname'] . '/' . $this->filenameFormat
|
||||
);
|
||||
|
||||
if (!empty($fileInfo['extension'])) {
|
||||
if (isset($fileInfo['extension'])) {
|
||||
$timedFilename .= '.'.$fileInfo['extension'];
|
||||
}
|
||||
|
||||
@@ -191,7 +194,7 @@ class RotatingFileHandler extends StreamHandler
|
||||
[$fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'],
|
||||
$fileInfo['dirname'] . '/' . $this->filenameFormat
|
||||
);
|
||||
if (!empty($fileInfo['extension'])) {
|
||||
if (isset($fileInfo['extension'])) {
|
||||
$glob .= '.'.$fileInfo['extension'];
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter
|
||||
|
||||
/**
|
||||
* @var HandlerInterface|callable
|
||||
* @phpstan-var HandlerInterface|callable(Record, HandlerInterface): HandlerInterface
|
||||
* @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
@@ -46,7 +46,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter
|
||||
protected $factor;
|
||||
|
||||
/**
|
||||
* @psalm-param HandlerInterface|callable(Record, HandlerInterface): HandlerInterface $handler
|
||||
* @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler
|
||||
*
|
||||
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
|
||||
* @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled)
|
||||
@@ -71,6 +71,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter
|
||||
{
|
||||
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,7 @@ use Monolog\Formatter\FormatterInterface;
|
||||
* @see https://api.slack.com/docs/message-attachments
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class SlackRecord
|
||||
{
|
||||
@@ -121,7 +122,7 @@ class SlackRecord
|
||||
* is expecting.
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
* @phpstan-return string[]
|
||||
* @phpstan-return mixed[]
|
||||
*/
|
||||
public function getSlackData(array $record): array
|
||||
{
|
||||
@@ -137,6 +138,7 @@ class SlackRecord
|
||||
}
|
||||
|
||||
if ($this->formatter && !$this->useAttachment) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$message = $this->formatter->format($record);
|
||||
} else {
|
||||
$message = $record['message'];
|
||||
@@ -221,6 +223,7 @@ class SlackRecord
|
||||
*/
|
||||
public function stringify(array $fields): string
|
||||
{
|
||||
/** @var Record $fields */
|
||||
$normalized = $this->normalizerFormatter->format($fields);
|
||||
|
||||
$hasSecondDimension = count(array_filter($normalized, 'is_array'));
|
||||
@@ -341,8 +344,11 @@ class SlackRecord
|
||||
*/
|
||||
private function generateAttachmentFields(array $data): array
|
||||
{
|
||||
/** @var Record $data */
|
||||
$normalized = $this->normalizerFormatter->format($data);
|
||||
|
||||
$fields = array();
|
||||
foreach ($this->normalizerFormatter->format($data) as $key => $value) {
|
||||
foreach ($normalized as $key => $value) {
|
||||
$fields[] = $this->generateAttachmentField((string) $key, $value);
|
||||
}
|
||||
|
||||
|
@@ -216,7 +216,7 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @return resource|bool
|
||||
* @return resource|false
|
||||
*/
|
||||
protected function pfsockopen()
|
||||
{
|
||||
@@ -226,7 +226,7 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @return resource|bool
|
||||
* @return resource|false
|
||||
*/
|
||||
protected function fsockopen()
|
||||
{
|
||||
@@ -245,6 +245,10 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
$seconds = floor($this->timeout);
|
||||
$microseconds = round(($this->timeout - $seconds) * 1e6);
|
||||
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
|
||||
}
|
||||
|
||||
@@ -257,6 +261,10 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
protected function streamSetChunkSize()
|
||||
{
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return stream_set_chunk_size($this->resource, $this->chunkSize);
|
||||
}
|
||||
|
||||
@@ -267,6 +275,10 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
protected function fwrite(string $data)
|
||||
{
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('fwrite called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return @fwrite($this->resource, $data);
|
||||
}
|
||||
|
||||
@@ -277,6 +289,10 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
protected function streamGetMetadata()
|
||||
{
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return stream_get_meta_data($this->resource);
|
||||
}
|
||||
|
||||
@@ -325,7 +341,7 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
} else {
|
||||
$resource = $this->fsockopen();
|
||||
}
|
||||
if (!$resource) {
|
||||
if (is_bool($resource)) {
|
||||
throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)");
|
||||
}
|
||||
$this->resource = $resource;
|
||||
@@ -361,7 +377,7 @@ class SocketHandler extends AbstractProcessingHandler
|
||||
}
|
||||
$sent += $chunk;
|
||||
$socketInfo = $this->streamGetMetadata();
|
||||
if ($socketInfo['timed_out']) {
|
||||
if (is_array($socketInfo) && $socketInfo['timed_out']) {
|
||||
throw new \RuntimeException("Write timed-out");
|
||||
}
|
||||
|
||||
|
@@ -101,34 +101,41 @@ class StreamHandler extends AbstractProcessingHandler
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!is_resource($this->stream)) {
|
||||
if (null === $this->url || '' === $this->url) {
|
||||
$url = $this->url;
|
||||
if (null === $url || '' === $url) {
|
||||
throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
|
||||
}
|
||||
$this->createDir();
|
||||
$this->createDir($url);
|
||||
$this->errorMessage = null;
|
||||
set_error_handler([$this, 'customErrorHandler']);
|
||||
$this->stream = fopen($this->url, 'a');
|
||||
$stream = fopen($url, 'a');
|
||||
if ($this->filePermission !== null) {
|
||||
@chmod($this->url, $this->filePermission);
|
||||
@chmod($url, $this->filePermission);
|
||||
}
|
||||
restore_error_handler();
|
||||
if (!is_resource($this->stream)) {
|
||||
if (!is_resource($stream)) {
|
||||
$this->stream = null;
|
||||
|
||||
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $this->url));
|
||||
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $url));
|
||||
}
|
||||
stream_set_chunk_size($this->stream, self::MAX_CHUNK_SIZE);
|
||||
stream_set_chunk_size($stream, self::MAX_CHUNK_SIZE);
|
||||
$this->stream = $stream;
|
||||
}
|
||||
|
||||
$stream = $this->stream;
|
||||
if (!is_resource($stream)) {
|
||||
throw new \LogicException('No stream was opened yet');
|
||||
}
|
||||
|
||||
if ($this->useLocking) {
|
||||
// ignoring errors here, there's not much we can do about them
|
||||
flock($this->stream, LOCK_EX);
|
||||
flock($stream, LOCK_EX);
|
||||
}
|
||||
|
||||
$this->streamWrite($this->stream, $record);
|
||||
$this->streamWrite($stream, $record);
|
||||
|
||||
if ($this->useLocking) {
|
||||
flock($this->stream, LOCK_UN);
|
||||
flock($stream, LOCK_UN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,14 +172,14 @@ class StreamHandler extends AbstractProcessingHandler
|
||||
return null;
|
||||
}
|
||||
|
||||
private function createDir(): void
|
||||
private function createDir(string $url): void
|
||||
{
|
||||
// Do not try to create dir if it has already been tried.
|
||||
if ($this->dirCreated) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dir = $this->getDirFromStream($this->url);
|
||||
$dir = $this->getDirFromStream($url);
|
||||
if (null !== $dir && !is_dir($dir)) {
|
||||
$this->errorMessage = null;
|
||||
set_error_handler([$this, 'customErrorHandler']);
|
||||
|
@@ -36,8 +36,6 @@ class SyslogHandler extends AbstractSyslogHandler
|
||||
/**
|
||||
* @param string $ident
|
||||
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
|
||||
*/
|
||||
public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID)
|
||||
|
@@ -45,7 +45,6 @@ class SyslogUdpHandler extends AbstractSyslogHandler
|
||||
* @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then)
|
||||
* @param int $port Port number, or 0 if $host is a unix socket
|
||||
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param string $ident Program name or tag for each log message.
|
||||
* @param int $rfc RFC to format the message for.
|
||||
@@ -88,7 +87,12 @@ class SyslogUdpHandler extends AbstractSyslogHandler
|
||||
$message = implode("\n", $message);
|
||||
}
|
||||
|
||||
return preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
|
||||
if (false === $lines) {
|
||||
throw new \RuntimeException('Could not preg_split: '.preg_last_error().' / '.preg_last_error_msg());
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -27,6 +27,8 @@ use Monolog\Logger;
|
||||
* @link https://core.telegram.org/bots/api
|
||||
*
|
||||
* @author Mazur Alexandr <alexandrmazur96@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class TelegramBotHandler extends AbstractProcessingHandler
|
||||
{
|
||||
@@ -127,6 +129,7 @@ class TelegramBotHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
/** @var Record[] $messages */
|
||||
$messages = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
@@ -135,6 +138,7 @@ class TelegramBotHandler extends AbstractProcessingHandler
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
@@ -174,6 +178,9 @@ class TelegramBotHandler extends AbstractProcessingHandler
|
||||
]));
|
||||
|
||||
$result = Curl\Util::execute($ch);
|
||||
if (!is_string($result)) {
|
||||
throw new RuntimeException('Telegram API error. Description: No response');
|
||||
}
|
||||
$result = json_decode($result, true);
|
||||
|
||||
if ($result['ok'] === false) {
|
||||
|
@@ -118,6 +118,8 @@ class TestHandler extends AbstractProcessingHandler
|
||||
|
||||
/**
|
||||
* @param string|int $level Logging level value or name
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecords($level): bool
|
||||
{
|
||||
@@ -151,6 +153,8 @@ class TestHandler extends AbstractProcessingHandler
|
||||
|
||||
/**
|
||||
* @param string|int $level Logging level value or name
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecordThatContains(string $message, $level): bool
|
||||
{
|
||||
@@ -214,10 +218,11 @@ class TestHandler extends AbstractProcessingHandler
|
||||
if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
|
||||
$genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
|
||||
$level = constant('Monolog\Logger::' . strtoupper($matches[2]));
|
||||
if (method_exists($this, $genericMethod)) {
|
||||
$callback = [$this, $genericMethod];
|
||||
if (is_callable($callback)) {
|
||||
$args[] = $level;
|
||||
|
||||
return call_user_func_array([$this, $genericMethod], $args);
|
||||
return call_user_func_array($callback, $args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,15 +16,18 @@ namespace Monolog\Handler;
|
||||
* and continuing through to give every handler a chance to succeed.
|
||||
*
|
||||
* @author Craig D'Amelio <craig@damelio.ca>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class WhatFailureGroupHandler extends GroupHandler
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
@@ -40,7 +43,7 @@ class WhatFailureGroupHandler extends GroupHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
@@ -49,6 +52,7 @@ class WhatFailureGroupHandler extends GroupHandler
|
||||
foreach ($records as $record) {
|
||||
$processed[] = $this->processRecord($record);
|
||||
}
|
||||
/** @var Record[] $records */
|
||||
$records = $processed;
|
||||
}
|
||||
|
||||
|
@@ -12,12 +12,16 @@
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Injects Git branch and Git commit SHA in all records
|
||||
*
|
||||
* @author Nick Otter
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class GitProcessor implements ProcessorInterface
|
||||
{
|
||||
@@ -28,6 +32,8 @@ class GitProcessor implements ProcessorInterface
|
||||
|
||||
/**
|
||||
* @param string|int $level The minimum logging level at which this Processor will be triggered
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function __construct($level = Logger::DEBUG)
|
||||
{
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Monolog\Processor;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Injects line/file:class/function where the log message came from
|
||||
@@ -23,6 +24,9 @@ use Monolog\Logger;
|
||||
* triggered the FingersCrossedHandler.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class IntrospectionProcessor implements ProcessorInterface
|
||||
{
|
||||
@@ -41,6 +45,8 @@ class IntrospectionProcessor implements ProcessorInterface
|
||||
/**
|
||||
* @param string|int $level The minimum logging level at which this Processor will be triggered
|
||||
* @param string[] $skipClassesPartials
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
|
||||
{
|
||||
|
@@ -138,6 +138,8 @@ final class Utils
|
||||
* @param int $code return code of json_last_error function
|
||||
* @param mixed $data data that was meant to be encoded
|
||||
* @throws \RuntimeException
|
||||
*
|
||||
* @return never
|
||||
*/
|
||||
private static function throwEncodeError(int $code, $data): void
|
||||
{
|
||||
@@ -186,6 +188,9 @@ final class Utils
|
||||
},
|
||||
$data
|
||||
);
|
||||
if (!is_string($data)) {
|
||||
throw new \RuntimeException('Failed to preg_replace_callback: '.preg_last_error().' / '.preg_last_error_msg());
|
||||
}
|
||||
$data = str_replace(
|
||||
['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'],
|
||||
['€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'],
|
||||
|
Reference in New Issue
Block a user