Skip to content

Commit

Permalink
Merge pull request #44 from dotkernel/issue-43
Browse files Browse the repository at this point in the history
Issue #43: Control the contents of `extra` in error log.
  • Loading branch information
arhimede authored Feb 24, 2025
2 parents c0dcf58 + 51786fc commit 84f8368
Show file tree
Hide file tree
Showing 43 changed files with 2,719 additions and 69 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ clover.xml
coveralls-upload.json
.phpunit.result.cache
.phpcs-cache
config/log.global.php
config/error-handling.global.php

# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
# dot-errorhandler

Error Logging Handler for Dotkernel
dot-errorhandler is Dotkernel's PSR-15 compliant error handler.

## Documentation

Documentation is available at: https://docs.dotkernel.org/dot-errorhandler/

## Badges

![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-errorhandler)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.1.1)

[![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-errorhandler)](https://github.com/dotkernel/dot-errorhandler/issues)
[![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-errorhandler)](https://github.com/dotkernel/dot-errorhandler/network)
[![GitHub stars](https://img.shields.io/github/stars/dotkernel/dot-errorhandler)](https://github.com/dotkernel/dot-errorhandler/stargazers)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-errorhandler)](https://github.com/dotkernel/dot-errorhandler/blob/4.0/LICENSE)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-errorhandler)](https://github.com/dotkernel/dot-errorhandler/blob/4.1/LICENSE)

[![Build Static](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml)
[![Build Static](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml/badge.svg?branch=4.1)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-errorhandler/branch/4.0/graph/badge.svg?token=0KIJARS5RS)](https://codecov.io/gh/dotkernel/dot-errorhandler)

## Adding the error handler
Expand Down
28 changes: 12 additions & 16 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@
"homepage": "https://github.com/dotkernel/dot-errorhandler",
"authors": [
{
"name": "DotKernel Team",
"name": "Dotkernel Team",
"email": "[email protected]"
}
],
"keywords": [
"error",
"errorhandler",
"factories",
"container",
"laminas",
"mezzio",
"service-manager"
"error_log"
],
"config": {
"sort-packages": true,
Expand All @@ -27,18 +23,19 @@
},
"require": {
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"dotkernel/dot-log": "^4.1.0",
"laminas/laminas-diactoros": "^3.3",
"laminas/laminas-stratigility": "^3.11",
"mezzio/mezzio": "^3.19",
"dotkernel/dot-log": "^5.0",
"laminas/laminas-diactoros": "^3.5",
"laminas/laminas-stdlib": "^3.20",
"laminas/laminas-stratigility": "^3.13",
"mezzio/mezzio": "^3.20.1",
"psr/http-message": "^1.0 || ^2.0",
"psr/http-server-middleware": "^1.0"
"psr/http-server-middleware": "^1.0.2"
},
"require-dev": {
"laminas/laminas-coding-standard": "^3.0",
"mikey179/vfsstream": "^1.6.7",
"phpunit/phpunit": "^10.5",
"vimeo/psalm": "^6.0"
"laminas/laminas-coding-standard": "^3.0.1",
"mikey179/vfsstream": "^1.6.12",
"phpunit/phpunit": "^10.5.45",
"vimeo/psalm": "6.6.2"
},
"autoload": {
"psr-4": {
Expand All @@ -60,7 +57,6 @@
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"static-analysis": "psalm --shepherd --stats"
}
}
78 changes: 73 additions & 5 deletions config/error-handling.global.php.dist
Original file line number Diff line number Diff line change
@@ -1,16 +1,84 @@
<?php

declare(strict_types=1);

use Dot\ErrorHandler\ErrorHandlerInterface;
use Dot\ErrorHandler\Extra\ExtraProvider;
use Dot\ErrorHandler\Extra\Processor\CookieProcessor;
use Dot\ErrorHandler\Extra\Processor\HeaderProcessor;
use Dot\ErrorHandler\Extra\Processor\ProcessorInterface;
use Dot\ErrorHandler\Extra\Processor\RequestProcessor;
use Dot\ErrorHandler\Extra\Processor\ServerProcessor;
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\Extra\ReplacementStrategy;
use Dot\ErrorHandler\LogErrorHandler;

return [
'dependencies' => [
'dependencies' => [
'aliases' => [
ErrorHandlerInterface::class => LogErrorHandler::class,
]
],
],
'dot-errorhandler' => [
'loggerEnabled' => true,
'logger' => 'dot-log.default_logger'
]
'loggerEnabled' => true,
'logger' => 'dot-log.default_logger',
ExtraProvider::CONFIG_KEY => [
CookieProvider::class => [
'enabled' => false,
'processor' => [
'class' => CookieProcessor::class,
'replacementStrategy' => ReplacementStrategy::Full,
'sensitiveParameters' => [
ProcessorInterface::ALL,
],
],
],
HeaderProvider::class => [
'enabled' => false,
'processor' => [
'class' => HeaderProcessor::class,
'replacementStrategy' => ReplacementStrategy::Full,
],
],
RequestProvider::class => [
'enabled' => false,
'processor' => [
'class' => RequestProcessor::class,
'replacementStrategy' => ReplacementStrategy::Full,
'sensitiveParameters' => [
'password',
],
],
],
ServerProvider::class => [
'enabled' => false,
'processor' => [
'class' => ServerProcessor::class,
'replacementStrategy' => ReplacementStrategy::Full,
'sensitiveParameters' => [
ProcessorInterface::ALL,
],
],
],
SessionProvider::class => [
'enabled' => false,
'processor' => [
'class' => SessionProcessor::class,
],
],
TraceProvider::class => [
'enabled' => true,
'processor' => [
'class' => TraceProcessor::class,
],
],
],
],
];
17 changes: 11 additions & 6 deletions config/log.global.php.dist
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
<?php

declare(strict_types=1);

use Dot\Log\Formatter\Json;
use Dot\Log\Logger;

return [
'dot_log' => [
'loggers' => [
'default_logger' => [
'writers' => [
'FileWriter' => [
'name' => 'stream',
'priority' => \Dot\Log\Logger::ALERT,
'name' => 'stream',
'level' => Logger::ALERT,
'options' => [
'stream' => __DIR__ . '/../../log/error-log-{Y}-{m}-{d}.log',
// explicitly log all messages
'filters' => [
'filters' => [
'allMessages' => [
'name' => 'priority',
'name' => 'level',
'options' => [
'operator' => '>=',
'priority' => \Dot\Log\Logger::EMERG,
'level' => Logger::EMERG,
],
],
],
'formatter' => [
'name' => \Dot\Log\Formatter\Json::class,
'name' => Json::class,
],
],
],
Expand Down
120 changes: 120 additions & 0 deletions docs/book/v4/extra/cookie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Log cookie data

Looking at `dot-errorhandler`'s config file, the array found at `CookieProvider::class` allows you to configure the behaviour of this provider:

- **enabled**: enabled/disable this provider
- **processor**: an array configuring the data processor to be used by the **CookieProvider**:
- **class**: data processor class implementing `Dot\ErrorHandler\Extra\Processor\ProcessorInterface`
- **replacementStrategy**: whether to replace specific cookie values completely or partially
- **sensitiveParameters**: an array of cookies names that may contain sensitive information so their value should be masked partially/completely

## Configure provider

By default, **CookieProvider** is disabled.
It can be enabled only by setting **enabled** to **true**.

If **enabled** is set to **true**, your log file will contain an additional field under the `extra` key, called `cookie`.
If **enabled** is set to **false**, no additional field is added under the `extra` key.

## Configure processor

From here, we assume that **enabled** is set to **true**.

If **processor** is missing/empty, the processor is ignored the provider will log the raw data available.
If **processor** is specified, but **class** is missing/invalid, the processor is ignored and the provider will log the raw data available.

From here, we assume that **processor**.**class** is valid.

### Replacement strategy

This value should be an instance of `Dot\ErrorHandler\Extra\ReplacementStrategy`.

If **replacementStrategy** is missing/invalid, the default **replacementStrategy** is used, which is `ReplacementStrategy::Full`.
Else, the value used should be one of:

- `ReplacementStrategy::Partial` for half-string replacements (e.g.: "abcdef" becomes "abc***")
- `ReplacementStrategy::Full` for full-string replacements (e.g.: "abcdef" becomes "******")

### Sensitive parameters

If **sensitiveParameters** is missing/empty, the processor is ignored the provider will log the raw data available.
This is because without a set of **sensitiveParameters**, the processor is unable to determine which key needs to be processed or left untouched.
When specifying the array of **sensitiveParameters**, there are two possibilities:

- use the constant `ProcessorInterface::ALL`, meaning alter all cookie values using the strategy specified by the **replacementStrategy**

```php
'sensitiveParameters' => [
Dot\ErrorHandler\Extra\Processor\ProcessorInterface::ALL,
],
```

- use exact strings to list the cookies for which the values should be altered using the strategy specified by the **replacementStrategy**

```php
'sensitiveParameters' => [
'rememberMe',
],
```

> **CookieProcessor** uses EXACT cookie name lookups.
> In order to alter the value of a cookie, you need to specify the exact cookie name.
> The config `sensitiveParameters` is case-insensitive.
## Why should I use a processor

Consider the following request cookies:

```text
[
"sessionId" => "feb21b39f9c54e3a49af1f862acc8300",
"language" => "en",
]
```

Without a **CookieProcessor**, the plain text session cookie identifier would end up saved in the log file:

```text
..."extra":{"file":"/path/to/some/class.php","line":314,"cookie":{"sessionId":"feb21b39f9c54e3a49af1f862acc8300","language":"en"},...
```

But, with a properly configured **CookieProcessor**:

```php
'processor' => [
'class' => CookieProcessor::class,
'replacementStrategy' => ReplacementStrategy::Full,
'sensitiveParameters' => [
'sessionId',
],
],
```

the logged cookie data becomes:

```text
..."extra":{"file":"/path/to/some/class.php","line":314,"cookie":{"sessionId":"********************************","language":"en"},...
```

## Custom processor

If the existing processor does not offer enough features, you can create a custom processor.
The custom processor must implement `Dot\ErrorHandler\Extra\Processor\ProcessorInterface` or extend `Dot\ErrorHandler\Extra\Processor\AbstractProcessor`, which already implements `Dot\ErrorHandler\Extra\Processor\ProcessorInterface`.
Once the custom processor is ready, you need to configure **CookieProvider** to use it.
For this, open `dot-errorhandler`'s config file and - under **CookieProvider::class** - set **processor**.**class** to the class string of your custom processor:

```php
CookieProvider::class => [
'enabled' => false,
'processor' => [
'class' => CustomCookieProcessor::class,
'replacementStrategy' => ReplacementStrategy::Full,
'sensitiveParameters' => [
ProcessorInterface::ALL,
],
],
],
```

Using this, cookie data will be processed by `CustomCookieProcessor` and logged as provided by this new processor.
Loading

0 comments on commit 84f8368

Please sign in to comment.