Skip to content

Commit

Permalink
Issue #43: Control the contents of 'extra' in error log.
Browse files Browse the repository at this point in the history
Signed-off-by: alexmerlin <[email protected]>
  • Loading branch information
alexmerlin committed Feb 6, 2025
1 parent c0dcf58 commit 7d408e3
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 11 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"dotkernel/dot-log": "^4.1.0",
"laminas/laminas-diactoros": "^3.3",
"laminas/laminas-stdlib": "^3.20",
"laminas/laminas-stratigility": "^3.11",
"mezzio/mezzio": "^3.19",
"psr/http-message": "^1.0 || ^2.0",
Expand Down
47 changes: 43 additions & 4 deletions config/error-handling.global.php.dist
Original file line number Diff line number Diff line change
@@ -1,16 +1,55 @@
<?php

declare(strict_types=1);

use Dot\ErrorHandler\ErrorHandlerInterface;
use Dot\ErrorHandler\Extra\Processor\CookieProcessor;
use Dot\ErrorHandler\Extra\Processor\HeaderProcessor;
use Dot\ErrorHandler\Extra\Processor\RequestProcessor;
use Dot\ErrorHandler\Extra\Processor\SessionProcessor;
use Dot\ErrorHandler\Extra\Processor\TraceProcessor;
use Dot\ErrorHandler\Extra\Provider\CookieProvider;
use Dot\ErrorHandler\Extra\Provider\HeaderProvider;
use Dot\ErrorHandler\Extra\Provider\RequestProvider;
use Dot\ErrorHandler\Extra\Provider\ServerProvider;
use Dot\ErrorHandler\Extra\Provider\SessionProvider;
use Dot\ErrorHandler\Extra\Provider\TraceProvider;
use Dot\ErrorHandler\LogErrorHandler;

return [
'dependencies' => [
'dependencies' => [
'aliases' => [
ErrorHandlerInterface::class => LogErrorHandler::class,
]
],
],
'dot-errorhandler' => [
'loggerEnabled' => true,
'logger' => 'dot-log.default_logger'
]
'logger' => 'dot-log.default_logger',
'loggerExtra' => [
CookieProvider::class => [
'enabled' => true,
'processor' => CookieProcessor::class,
],
HeaderProvider::class => [
'enabled' => true,
'processor' => HeaderProcessor::class,
],
RequestProvider::class => [
'enabled' => true,
'processor' => RequestProcessor::class,
],
ServerProvider::class => [
'enabled' => true,
'processor' => null,
],
SessionProvider::class => [
'enabled' => true,
'processor' => SessionProcessor::class,
],
TraceProvider::class => [
'enabled' => true,
'processor' => TraceProcessor::class,
],
],
],
];
92 changes: 92 additions & 0 deletions src/Extra/ExtraProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra;

use Dot\ErrorHandler\Extra\Processor\ProcessorInterface;
use Dot\ErrorHandler\Extra\Provider\CookieProvider;
use Dot\ErrorHandler\Extra\Provider\HeaderProvider;
use Dot\ErrorHandler\Extra\Provider\RequestProvider;
use Dot\ErrorHandler\Extra\Provider\ServerProvider;
use Dot\ErrorHandler\Extra\Provider\SessionProvider;
use Dot\ErrorHandler\Extra\Provider\TraceProvider;

use function array_key_exists;
use function class_exists;
use function is_bool;
use function is_string;

class ExtraProvider
{
private CookieProvider $cookie;
private HeaderProvider $header;
private RequestProvider $request;
private ServerProvider $server;
private SessionProvider $session;
private TraceProvider $trace;

public function __construct(array $options = [])
{
$extras = [
'cookie' => CookieProvider::class,
'header' => HeaderProvider::class,
'request' => RequestProvider::class,
'server' => ServerProvider::class,
'session' => SessionProvider::class,
'trace' => TraceProvider::class,
];

foreach ($extras as $logKey => $logClass) {
$enabled = false;
$processor = null;
if (array_key_exists($logClass, $options)) {
if (isset($options[$logClass]['enabled']) && is_bool($options[$logClass]['enabled'])) {
$enabled = $options[$logClass]['enabled'];
}
if (
isset($options[$logClass]['processor'])
&& is_string($options[$logClass]['processor'])
&& class_exists($options[$logClass]['processor'])
) {
$processor = new $options[$logClass]['processor']();
if (! $processor instanceof ProcessorInterface) {
$processor = null;
}
}
}

$this->$logKey = new $logClass($enabled, $processor);
}
}

public function getCookie(): CookieProvider
{
return $this->cookie;
}

public function getHeader(): HeaderProvider
{
return $this->header;
}

public function getRequest(): RequestProvider
{
return $this->request;
}

public function getServer(): ServerProvider
{
return $this->server;
}

public function getSession(): SessionProvider
{
return $this->session;
}

public function getTrace(): TraceProvider
{
return $this->trace;
}
}
18 changes: 18 additions & 0 deletions src/Extra/Processor/CookieProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

use function array_map;
use function str_pad;
use function strlen;
use function substr;

class CookieProcessor implements ProcessorInterface
{
public function process(array $data): array
{
return array_map(fn (string $cookie): string => str_pad(substr($cookie, 0, 8), strlen($cookie), '.'), $data);
}
}
16 changes: 16 additions & 0 deletions src/Extra/Processor/HeaderProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

use function array_map;
use function implode;

class HeaderProcessor implements ProcessorInterface
{
public function process(array $data): array
{
return array_map(fn (array $headerSet): string => implode("; ", $headerSet), $data);
}
}
10 changes: 10 additions & 0 deletions src/Extra/Processor/ProcessorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

interface ProcessorInterface
{
public function process(array $data): array;
}
40 changes: 40 additions & 0 deletions src/Extra/Processor/RequestProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

use function is_array;
use function is_string;
use function preg_replace;
use function str_contains;
use function strtolower;

class RequestProcessor implements ProcessorInterface
{
public function process(array $data): array
{
$return = [];
foreach ($data as $key => $value) {
if (is_array($value)) {
$return[$key] = $this->process($value);
} elseif (is_string($value)) {
$lowerKey = strtolower($key);
if (
str_contains($lowerKey, 'password') ||
str_contains($lowerKey, 'key') ||
str_contains($lowerKey, 'csrf') ||
str_contains($lowerKey, 'token')
) {
$return[$key] = preg_replace('/[\da-z]/i', 'x', $value);
} else {
$return[$key] = $value;
}
} else {
$return[$key] = $value;
}
}

return $return;
}
}
13 changes: 13 additions & 0 deletions src/Extra/Processor/ServerProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

class ServerProcessor implements ProcessorInterface
{
public function process(array $data): array
{
return $data;
}
}
17 changes: 17 additions & 0 deletions src/Extra/Processor/SessionProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

use Laminas\Stdlib\ArrayUtils;

use function array_map;

class SessionProcessor implements ProcessorInterface
{
public function process(array $data): array
{
return array_map(fn ($container): array => ArrayUtils::iteratorToArray($container), $data);
}
}
25 changes: 25 additions & 0 deletions src/Extra/Processor/TraceProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Processor;

use function array_map;
use function sprintf;

class TraceProcessor implements ProcessorInterface
{
public function process(array $data): array
{
return array_map(
fn ($trace): string => sprintf(
'%s%s%s:%d',
$trace['class'] ?? $trace['file'] ?? 'unknown',
$trace['type'] ?? '->',
$trace['function'] ?? 'unknown',
$trace['line'] ?? 0
),
$data
);
}
}
25 changes: 25 additions & 0 deletions src/Extra/Provider/CookieProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Provider;

use Dot\ErrorHandler\Extra\Processor\ProcessorInterface;

readonly class CookieProvider
{
public function __construct(
public bool $enabled = false,
public ?ProcessorInterface $processor = null,
) {
}

public function provide(array $cookies): array
{
if ($this->processor instanceof ProcessorInterface) {
return $this->processor->process($cookies);
}

return $cookies;
}
}
25 changes: 25 additions & 0 deletions src/Extra/Provider/HeaderProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Provider;

use Dot\ErrorHandler\Extra\Processor\ProcessorInterface;

readonly class HeaderProvider
{
public function __construct(
public bool $enabled = false,
public ?ProcessorInterface $processor = null,
) {
}

public function provide(array $headers): array
{
if ($this->processor instanceof ProcessorInterface) {
return $this->processor->process($headers);
}

return $headers;
}
}
25 changes: 25 additions & 0 deletions src/Extra/Provider/RequestProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Dot\ErrorHandler\Extra\Provider;

use Dot\ErrorHandler\Extra\Processor\ProcessorInterface;

readonly class RequestProvider
{
public function __construct(
public bool $enabled = false,
public ?ProcessorInterface $processor = null,
) {
}

public function provide(array $request): array
{
if ($this->processor instanceof ProcessorInterface) {
return $this->processor->process($request);
}

return $request;
}
}
Loading

0 comments on commit 7d408e3

Please sign in to comment.