Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Seldaek/monolog
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.4.0
Choose a base ref
...
head repository: Seldaek/monolog
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.5.0
Choose a head ref
Loading
Showing with 471 additions and 49 deletions.
  1. +4 −3 .github/workflows/continuous-integration.yml
  2. +1 −1 .github/workflows/lint.yml
  3. +1 −1 .github/workflows/phpstan.yml
  4. +2 −0 .gitignore
  5. +28 −0 CHANGELOG.md
  6. +2 −0 README.md
  7. BIN favicon.ico
  8. BIN logo.jpg
  9. +29 −0 src/Monolog/Attribute/WithMonologChannel.php
  10. +2 −1 src/Monolog/ErrorHandler.php
  11. +3 −0 src/Monolog/Formatter/JsonFormatter.php
  12. +48 −3 src/Monolog/Formatter/LineFormatter.php
  13. +6 −0 src/Monolog/Formatter/LogmaticFormatter.php
  14. +0 −1 src/Monolog/Formatter/MongoDBFormatter.php
  15. +20 −0 src/Monolog/Formatter/NormalizerFormatter.php
  16. +2 −0 src/Monolog/Handler/AbstractHandler.php
  17. +2 −2 src/Monolog/Handler/FallbackGroupHandler.php
  18. +1 −0 src/Monolog/Handler/FilterHandler.php
  19. +2 −2 src/Monolog/Handler/GroupHandler.php
  20. +3 −1 src/Monolog/Handler/LogglyHandler.php
  21. +6 −0 src/Monolog/Handler/NativeMailerHandler.php
  22. +4 −0 src/Monolog/Handler/PushoverHandler.php
  23. +3 −0 src/Monolog/Handler/RotatingFileHandler.php
  24. +18 −4 src/Monolog/Handler/Slack/SlackRecord.php
  25. +17 −0 src/Monolog/Handler/SlackHandler.php
  26. +7 −0 src/Monolog/Handler/SocketHandler.php
  27. +7 −4 src/Monolog/Handler/StreamHandler.php
  28. +2 −0 src/Monolog/Handler/SyslogUdpHandler.php
  29. +23 −5 src/Monolog/Handler/TelegramBotHandler.php
  30. +2 −2 src/Monolog/Handler/WhatFailureGroupHandler.php
  31. +18 −4 src/Monolog/Logger.php
  32. +2 −0 src/Monolog/Processor/TagProcessor.php
  33. +3 −0 src/Monolog/Processor/WebProcessor.php
  34. +2 −2 src/Monolog/Test/TestCase.php
  35. +15 −0 tests/Monolog/Attribute/WithMonologChannelTest.php
  36. +51 −0 tests/Monolog/Formatter/LineFormatterTest.php
  37. +14 −0 tests/Monolog/Formatter/NormalizerFormatterTest.php
  38. +1 −3 tests/Monolog/Handler/ExceptionTestHandler.php
  39. +34 −0 tests/Monolog/Handler/FallbackGroupHandlerTest.php
  40. +34 −0 tests/Monolog/Handler/GroupHandlerTest.php
  41. +3 −4 tests/Monolog/Handler/MongoDBHandlerTest.php
  42. +34 −0 tests/Monolog/Handler/WhatFailureGroupHandlerTest.php
  43. +15 −6 tests/Monolog/LoggerTest.php
7 changes: 4 additions & 3 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ jobs:
php-version:
- "8.1"
- "8.2"
- "8.3"

dependencies: [highest]

@@ -39,7 +40,7 @@ jobs:

steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

- name: Run CouchDB
timeout-minutes: 3
@@ -114,7 +115,7 @@ jobs:

steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

# required for elasticsearch
- name: Configure sysctl limits
@@ -190,7 +191,7 @@ jobs:

steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

# required for elasticsearch
- name: Configure sysctl limits
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ jobs:

steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
2 changes: 1 addition & 1 deletion .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ jobs:

steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -7,3 +7,5 @@ composer.lock
.hg
.phpunit.result.cache
.phpunit.cache
favicon.ico
logo.jpg
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
### 3.5.0 (2023-10-27)

* Added ability to indent stack traces in LineFormatter via e.g. `indentStacktraces(' ')` (#1835)
* Added ability to configure a max level name length in LineFormatter via e.g. `setMaxLevelNameLength(3)` (#1850)
* Added support for indexed arrays (i.e. `[]` and not `{}` arrays once json serialized) containing inline linebreaks in LineFormatter (#1818)
* Added `WithMonologChannel` attribute for integrators to use to configure autowiring (#1847)
* Fixed log record `extra` data leaking between handlers that have handler-specific processors set (#1819)
* Fixed LogglyHandler issue with record level filtering (#1841)
* Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
* Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
* Fixed normalization error when normalizing incomplete classes (#1833)

### 3.4.0 (2023-06-21)

* Added `LoadAverageProcessor` to track one of the 1, 5 or 15min load averages (#1803)
* Added support for priority to the `AsMonologProcessor` attribute (#1797)
* Added `TelegramBotHandler` `topic`/`message_thread_id` support (#1802)
* Fixed `FingersCrossedHandler` passthruLevel checking (#1801)
* Fixed support of yearly and monthly rotation log file to rotate only once a month/year (#1805)
* Fixed `TestHandler` method docs (#1794)
* Fixed handling of falsey `display_errors` string values (#1804)

### 3.3.1 (2023-02-06)

* Fixed Logger not being serializable anymore (#1792)
@@ -84,6 +106,12 @@ New deprecations:
value equal to what `Logger::WARNING` was giving you.
- `Logger::getLevelName()` is now deprecated.

### 2.9.2 (2023-10-27)

* Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
* Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
* Fixed normalization error when normalizing incomplete classes (#1833)

### 2.9.1 (2023-02-06)

* Fixed Logger not being serializable anymore (#1792)
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
![Monolog](logo.jpg)

# Monolog - Logging for PHP [![Continuous Integration](https://github.com/Seldaek/monolog/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/Seldaek/monolog/actions)

[![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
Binary file added favicon.ico
Binary file not shown.
Binary file added logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions src/Monolog/Attribute/WithMonologChannel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types=1);

/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Monolog\Attribute;

/**
* A reusable attribute to help configure a class as expecting a given logger channel.
*
* Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer.
*
* Using it with the Monolog library only has no effect at all: wiring the logger instance into
* other classes is not managed by Monolog.
*/
#[\Attribute(\Attribute::TARGET_CLASS)]
final class WithMonologChannel
{
public function __construct(
public readonly string $channel
) {
}
}
3 changes: 2 additions & 1 deletion src/Monolog/ErrorHandler.php
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ public function __construct(
* @param array<int, LogLevel::*>|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
* @param array<class-string, LogLevel::*>|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
* @param LogLevel::*|null|false $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
* @return ErrorHandler
* @return static
*/
public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self
{
@@ -126,6 +126,7 @@ public function registerErrorHandler(array $levelMap = [], bool $callPrevious =
/**
* @param LogLevel::*|null $level a LogLevel::* constant, null to use the default LogLevel::ALERT
* @param int $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done
* @return $this
*/
public function registerFatalHandler($level = null, int $reservedMemorySize = 20): self
{
3 changes: 3 additions & 0 deletions src/Monolog/Formatter/JsonFormatter.php
Original file line number Diff line number Diff line change
@@ -107,6 +107,9 @@ public function formatBatch(array $records): string
};
}

/**
* @return $this
*/
public function includeStacktraces(bool $include = true): self
{
$this->includeStacktraces = $include;
51 changes: 48 additions & 3 deletions src/Monolog/Formatter/LineFormatter.php
Original file line number Diff line number Diff line change
@@ -31,6 +31,8 @@ class LineFormatter extends NormalizerFormatter
protected bool $allowInlineLineBreaks;
protected bool $ignoreEmptyContextAndExtra;
protected bool $includeStacktraces;
protected ?int $maxLevelNameLength = null;
protected string $indentStacktraces = '';
protected Closure|null $stacktracesParser = null;

/**
@@ -49,6 +51,9 @@ public function __construct(?string $format = null, ?string $dateFormat = null,
parent::__construct($dateFormat);
}

/**
* @return $this
*/
public function includeStacktraces(bool $include = true, ?Closure $parser = null): self
{
$this->includeStacktraces = $include;
@@ -60,27 +65,63 @@ public function includeStacktraces(bool $include = true, ?Closure $parser = null
return $this;
}

/**
* Indent stack traces to separate them a bit from the main log record messages
*
* @param string $indent The string used to indent, for example " "
* @return $this
*/
public function indentStacktraces(string $indent): self
{
$this->indentStacktraces = $indent;

return $this;
}

/**
* @return $this
*/
public function allowInlineLineBreaks(bool $allow = true): self
{
$this->allowInlineLineBreaks = $allow;

return $this;
}

/**
* @return $this
*/
public function ignoreEmptyContextAndExtra(bool $ignore = true): self
{
$this->ignoreEmptyContextAndExtra = $ignore;

return $this;
}

/**
* Allows cutting the level name to get fixed-length levels like INF for INFO, ERR for ERROR if you set this to 3 for example
*
* @param int|null $maxLevelNameLength Maximum characters for the level name. Set null for infinite length (default)
* @return $this
*/
public function setMaxLevelNameLength(?int $maxLevelNameLength = null): self
{
$this->maxLevelNameLength = $maxLevelNameLength;

return $this;
}

/**
* @inheritDoc
*/
public function format(LogRecord $record): string
{
$vars = parent::format($record);

if ($this->maxLevelNameLength !== null) {
$vars['level_name'] = substr($vars['level_name'], 0, $this->maxLevelNameLength);
}

$output = $this->format;
foreach ($vars['extra'] as $var => $val) {
if (false !== strpos($output, '%extra.'.$var.'%')) {
@@ -153,7 +194,7 @@ protected function normalizeException(\Throwable $e, int $depth = 0): string
do {
$depth++;
if ($depth > $this->maxNormalizeDepth) {
$str .= '\n[previous exception] Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
$str .= "\n[previous exception] Over " . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
break;
}

@@ -183,7 +224,7 @@ protected function convertToString($data): string
protected function replaceNewlines(string $str): string
{
if ($this->allowInlineLineBreaks) {
if (0 === strpos($str, '{')) {
if (0 === strpos($str, '{') || 0 === strpos($str, '[')) {
$str = preg_replace('/(?<!\\\\)\\\\[rn]/', "\n", $str);
if (null === $str) {
$pcreErrorCode = preg_last_error();
@@ -234,7 +275,11 @@ private function stacktracesParser(\Throwable $e): string
$trace = $this->stacktracesParserCustom($trace);
}

return "\n[stacktrace]\n" . $trace . "\n";
if ($this->indentStacktraces !== '') {
$trace = str_replace("\n", "\n{$this->indentStacktraces}", $trace);
}

return "\n{$this->indentStacktraces}[stacktrace]\n{$this->indentStacktraces}" . $trace . "\n";
}

private function stacktracesParserCustom(string $trace): string
6 changes: 6 additions & 0 deletions src/Monolog/Formatter/LogmaticFormatter.php
Original file line number Diff line number Diff line change
@@ -26,13 +26,19 @@ class LogmaticFormatter extends JsonFormatter

protected string $appName = '';

/**
* @return $this
*/
public function setHostname(string $hostname): self
{
$this->hostname = $hostname;

return $this;
}

/**
* @return $this
*/
public function setAppName(string $appName): self
{
$this->appName = $appName;
1 change: 0 additions & 1 deletion src/Monolog/Formatter/MongoDBFormatter.php
Original file line number Diff line number Diff line change
@@ -154,7 +154,6 @@ private function legacyGetMongoDbDateTime(\DateTimeInterface $value): UTCDateTim
? (int) $milliseconds
: (string) $milliseconds;

// @phpstan-ignore-next-line
return new UTCDateTime($milliseconds);
}
}
20 changes: 20 additions & 0 deletions src/Monolog/Formatter/NormalizerFormatter.php
Original file line number Diff line number Diff line change
@@ -78,6 +78,9 @@ public function getDateFormat(): string
return $this->dateFormat;
}

/**
* @return $this
*/
public function setDateFormat(string $dateFormat): self
{
$this->dateFormat = $dateFormat;
@@ -93,6 +96,9 @@ public function getMaxNormalizeDepth(): int
return $this->maxNormalizeDepth;
}

/**
* @return $this
*/
public function setMaxNormalizeDepth(int $maxNormalizeDepth): self
{
$this->maxNormalizeDepth = $maxNormalizeDepth;
@@ -108,6 +114,9 @@ public function getMaxNormalizeItemCount(): int
return $this->maxNormalizeItemCount;
}

/**
* @return $this
*/
public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): self
{
$this->maxNormalizeItemCount = $maxNormalizeItemCount;
@@ -117,6 +126,8 @@ public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): self

/**
* Enables `json_encode` pretty print.
*
* @return $this
*/
public function setJsonPrettyPrint(bool $enable): self
{
@@ -195,6 +206,9 @@ protected function normalize(mixed $data, int $depth = 0): mixed
if ($data instanceof \JsonSerializable) {
/** @var null|scalar|array<mixed[]|scalar|null> $value */
$value = $data->jsonSerialize();
} elseif (\get_class($data) === '__PHP_Incomplete_Class') {
$accessor = new \ArrayObject($data);
$value = (string) $accessor['__PHP_Incomplete_Class_Name'];
} elseif (method_exists($data, '__toString')) {
/** @var string $value */
$value = $data->__toString();
@@ -289,13 +303,19 @@ protected function formatDate(\DateTimeInterface $date): string
return $date->format($this->dateFormat);
}

/**
* @return $this
*/
public function addJsonEncodeOption(int $option): self
{
$this->jsonEncodeOptions |= $option;

return $this;
}

/**
* @return $this
*/
public function removeJsonEncodeOption(int $option): self
{
$this->jsonEncodeOptions &= ~$option;
2 changes: 2 additions & 0 deletions src/Monolog/Handler/AbstractHandler.php
Original file line number Diff line number Diff line change
@@ -51,6 +51,7 @@ public function isHandling(LogRecord $record): bool
* Sets minimum logging level at which this handler will be triggered.
*
* @param Level|LogLevel::* $level Level or level name
* @return $this
*
* @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
*/
@@ -74,6 +75,7 @@ public function getLevel(): Level
*
* @param bool $bubble true means that this handler allows bubbling.
* false means that bubbling is not permitted.
* @return $this
*/
public function setBubble(bool $bubble): self
{
Loading