Skip to content

Commit

Permalink
Add RequestSizeProcessor and improve resettable processors
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandre-daubois committed Nov 8, 2023
1 parent d7a56db commit 8b653b6
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 7 deletions.
1 change: 1 addition & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
'@Symfony' => true,
'array_syntax' => ['syntax' => 'short'],
])
->setFinder($finder);
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ MPC is engineered for developers who demand more from their logs. Whether you're
monitoring live production environments, processors enrich your log entries with invaluable context, turning
ordinary logs into a rich, actionable dataset.

MPC is compatible with worker mode of web servers, as relevant processors implement the `ResettableInterface`.

## Installation

The recommended way to install MPC is through [Composer](https://getcomposer.org/):
Expand Down Expand Up @@ -51,6 +53,7 @@ The package provides the following processors:
- `IsHttpsProcessor` adds a boolean value indicating whether the request is a secured HTTP request to the log record
- `PhpIniValueProcessor` adds the value of one or more PHP ini settings to the log record
- `ProtocolVersionProcessor` adds the HTTP protocol version to the log record
- `RequestSizeProcessor` adds the size of the request to the log record, headers included, in bytes
- `ResourceUsagesProcessor` adds the resource usage to the log record as returned by [getrusage()](https://www.php.net/manual/en/function.getrusage.php)
- `SapiNameProcessor` adds the name of the SAPI to the log record
- `UuidProcessor` adds a UUID v7 to the log record to track records triggered during the same request
Expand Down
1 change: 0 additions & 1 deletion src/EnvVarProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace MonologProcessorCollection;

use Monolog\Level;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;

Expand Down
10 changes: 8 additions & 2 deletions src/IsHttpsProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@

use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Monolog\ResettableInterface;

/**
* Add the high resolution timestamp to the log record.
*/
final class IsHttpsProcessor implements ProcessorInterface
final class IsHttpsProcessor implements ProcessorInterface, ResettableInterface
{
private static ?bool $isHttps = null;

Expand All @@ -28,6 +29,11 @@ public function __invoke(LogRecord $record): LogRecord

private function isHttps(): bool
{
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] ?? null) === 443;
return (!empty($_SERVER['HTTPS']) && 'off' !== $_SERVER['HTTPS']) || ($_SERVER['SERVER_PORT'] ?? null) === 443;
}

public function reset(): void
{
self::$isHttps = null;
}
}
1 change: 0 additions & 1 deletion src/PhpIniValueProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace MonologProcessorCollection;

use Monolog\Level;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;

Expand Down
8 changes: 7 additions & 1 deletion src/ProtocolVersionProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@

use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Monolog\ResettableInterface;

/**
* Add the protocol version to the log record.
*/
final class ProtocolVersionProcessor implements ProcessorInterface
final class ProtocolVersionProcessor implements ProcessorInterface, ResettableInterface
{
private static ?string $protocol = null;

Expand All @@ -25,4 +26,9 @@ public function __invoke(LogRecord $record): LogRecord

return $record;
}

public function reset(): void
{
self::$protocol = null;
}
}
69 changes: 69 additions & 0 deletions src/RequestSizeProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/*
* (c) Alexandre Daubois <alex.daubois@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace MonologProcessorCollection;

use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Monolog\ResettableInterface;

/**
* Add the request size to the log record.
*/
final class RequestSizeProcessor implements ProcessorInterface, ResettableInterface
{
private static ?array $size = null;

public function __invoke(LogRecord $record): LogRecord
{
if (null === self::$size) {
$headers = $this->getHeaders();
$headersSize = \array_sum(
\array_map(\strlen(...), \array_keys($headers))
) + \array_sum(
\array_map(\strlen(...), $headers)
);

$bodySize = \strlen(\file_get_contents('php://input'));
self::$size = [
'headers' => $headersSize,
'body' => $bodySize,
'total' => $headersSize + $bodySize,
];
}

$record['extra']['request_size'] = self::$size;

return $record;
}

/**
* @return array<string, string>
*/
private function getHeaders(): array
{
if (\function_exists('apache_request_headers')) {
return \apache_request_headers();
}

$headers = [];
foreach ($_SERVER as $k => $v) {
if (\str_starts_with($k, 'HTTP_')) {
$headers[\substr($k, 5)] = $v;
}
}

return $headers;
}

public function reset(): void
{
self::$size = null;
}
}
1 change: 0 additions & 1 deletion tests/AbstractProcessorTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

use Monolog\Level;
use Monolog\LogRecord;
use MonologProcessorCollection\BacktraceProcessor;
use PHPUnit\Framework\TestCase;

abstract class AbstractProcessorTestCase extends TestCase
Expand Down
24 changes: 23 additions & 1 deletion tests/IsHttpsProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use Monolog\Handler\TestHandler;
use Monolog\Level;
use MonologProcessorCollection\IsHttpsProcessor;
use MonologProcessorCollection\ProtocolVersionProcessor;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(IsHttpsProcessor::class)]
Expand All @@ -32,4 +31,27 @@ public function testItWorks(): void
$this->assertArrayHasKey('is_https', $record->extra);
$this->assertFalse($record->extra['is_https']);
}

public function testResettable(): void
{
$processor = new IsHttpsProcessor();

$handler = new TestHandler();
$handler->pushProcessor($processor);
$handler->handle($this->createRecord(Level::Notice));
$record = $handler->getRecords()[0];

$this->assertArrayHasKey('is_https', $record->extra);
$this->assertFalse($record->extra['is_https']);

$processor->reset();

$_SERVER['HTTPS'] = 'on';

$handler->handle($this->createRecord(Level::Notice));
$record = $handler->getRecords()[1];

$this->assertArrayHasKey('is_https', $record->extra);
$this->assertTrue($record->extra['is_https']);
}
}
22 changes: 22 additions & 0 deletions tests/ProtocolVersionProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,26 @@ public function testItWorks(): void
$this->assertArrayHasKey('protocol', $record->extra);
$this->assertSame('Unknown', $record->extra['protocol']);
}

public function testResettable(): void
{
$processor = new ProtocolVersionProcessor();

$handler = new TestHandler();
$handler->pushProcessor($processor);
$handler->handle($this->createRecord(Level::Notice));
$record = $handler->getRecords()[0];

$this->assertArrayHasKey('protocol', $record->extra);
$this->assertSame('Unknown', $record->extra['protocol']);

$processor->reset();

$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
$handler->handle($this->createRecord(Level::Notice));
$record = $handler->getRecords()[1];

$this->assertArrayHasKey('protocol', $record->extra);
$this->assertSame('HTTP/1.1', $record->extra['protocol']);
}
}
57 changes: 57 additions & 0 deletions tests/RequestSizeProcessorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/*
* (c) Alexandre Daubois <alex.daubois@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Monolog\Handler\TestHandler;
use Monolog\Level;
use MonologProcessorCollection\RequestSizeProcessor;
use MonologProcessorCollection\Tests\AbstractProcessorTestCase;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(RequestSizeProcessor::class)]
class RequestSizeProcessorTest extends AbstractProcessorTestCase
{
public function testItWorks(): void
{
$processor = new RequestSizeProcessor();

$handler = new TestHandler();
$handler->pushProcessor($processor);

$_SERVER['HTTP_USER_AGENT'] = 'My agent';

$handler->handle($this->createRecord(Level::Notice));
$this->assertTrue($handler->hasNoticeRecords());
$record = $handler->getRecords()[0];

$this->assertArrayHasKey('request_size', $record->extra);
$this->assertEquals(\strlen('USER_AGENT') + \strlen('My agent'), $record->extra['request_size']['headers']);
}

public function testResettable(): void
{
$processor = new RequestSizeProcessor();

$handler = new TestHandler();
$handler->pushProcessor($processor);

$_SERVER['HTTP_USER_AGENT'] = 'My agent';

$handler->handle($this->createRecord(Level::Notice));
$record = $handler->getRecords()[0];

$this->assertEquals(\strlen('USER_AGENT') + \strlen('My agent'), $record->extra['request_size']['headers']);

$processor->reset();

$_SERVER['HTTP_USER_AGENT'] = 'My agent 2';
$handler->handle($this->createRecord(Level::Notice));
$record = $handler->getRecords()[1];
$this->assertEquals(\strlen('USER_AGENT') + \strlen('My agent 2'), $record->extra['request_size']['headers']);
}
}

0 comments on commit 8b653b6

Please sign in to comment.