From dc4bc7e66005c3084e3a329612a49c8fd357ba3e Mon Sep 17 00:00:00 2001 From: Johan Vlaar Date: Tue, 20 Jun 2023 16:13:13 +0200 Subject: [PATCH] Add LoadAverageProcessor (#1803) Co-authored-by: johan Vlaar Co-authored-by: Jordi Boggiano --- doc/02-handlers-formatters-processors.md | 1 + .../Processor/LoadAverageProcessor.php | 66 +++++++++++++++++++ .../Processor/LoadAverageProcessorTest.php | 38 +++++++++++ 3 files changed, 105 insertions(+) create mode 100644 src/Monolog/Processor/LoadAverageProcessor.php create mode 100644 tests/Monolog/Processor/LoadAverageProcessorTest.php diff --git a/doc/02-handlers-formatters-processors.md b/doc/02-handlers-formatters-processors.md index 615731bc..8e98d2b8 100644 --- a/doc/02-handlers-formatters-processors.md +++ b/doc/02-handlers-formatters-processors.md @@ -160,6 +160,7 @@ ## Processors - [_PsrLogMessageProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/PsrLogMessageProcessor.php): Processes a log record's message according to PSR-3 rules, replacing `{foo}` with the value from `$context['foo']`. +- [_LoadAverageProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/LoadAverageProcessor.php): Adds the current system load average to a log record. - [_ClosureContextProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/ClosureContextProcessor.php): Allows delaying the creation of context data by setting a Closure in context which is called when the log record is used - [_IntrospectionProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/IntrospectionProcessor.php): Adds the line/file/class/method from which the log call originated. - [_WebProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/WebProcessor.php): Adds the current request URI, request method and client IP to a log record. diff --git a/src/Monolog/Processor/LoadAverageProcessor.php b/src/Monolog/Processor/LoadAverageProcessor.php new file mode 100644 index 00000000..64e3c474 --- /dev/null +++ b/src/Monolog/Processor/LoadAverageProcessor.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\LogRecord; + +/** + * Injects sys_getloadavg in all records @see https://www.php.net/manual/en/function.sys-getloadavg.php + * + * @author Johan Vlaar + */ +class LoadAverageProcessor implements ProcessorInterface +{ + public const LOAD_1_MINUTE = 0; + public const LOAD_5_MINUTE = 1; + public const LOAD_15_MINUTE = 2; + + private const AVAILABLE_LOAD = [ + self::LOAD_1_MINUTE, + self::LOAD_5_MINUTE, + self::LOAD_15_MINUTE, + ]; + + /** + * @var int + */ + protected $avgSystemLoad; + + /** + * @param self::LOAD_* $avgSystemLoad + */ + public function __construct(int $avgSystemLoad = self::LOAD_1_MINUTE) + { + if (!in_array($avgSystemLoad, self::AVAILABLE_LOAD, true)) { + throw new \InvalidArgumentException(sprintf('Invalid average system load: `%s`', $avgSystemLoad)); + } + $this->avgSystemLoad = $avgSystemLoad; + } + + /** + * {@inheritDoc} + */ + public function __invoke(LogRecord $record): LogRecord + { + if (!function_exists('sys_getloadavg')) { + return $record; + } + $usage = sys_getloadavg(); + if (false === $usage) { + return $record; + } + + $record->extra['load_average'] = $usage[$this->avgSystemLoad]; + + return $record; + } +} diff --git a/tests/Monolog/Processor/LoadAverageProcessorTest.php b/tests/Monolog/Processor/LoadAverageProcessorTest.php new file mode 100644 index 00000000..8882b0f0 --- /dev/null +++ b/tests/Monolog/Processor/LoadAverageProcessorTest.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\Test\TestCase; + +class LoadAverageProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\LoadAverageProcessor::__invoke + */ + public function testProcessor() + { + $processor = new LoadAverageProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('load_average', $record->extra); + $this->assertIsFloat($record->extra['load_average']); + } + + /** + * @covers Monolog\Processor\LoadAverageProcessor::__invoke + */ + public function testProcessorWithInvalidAvgSystemLoad() + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid average system load: `3`'); + new LoadAverageProcessor(3); + } +}