diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index c0fbc53..912df7a 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v7 - name: Install PHP uses: shivammathur/setup-php@v2 @@ -36,7 +36,7 @@ jobs: run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - name: Cache dependencies installed with composer - uses: actions/cache@v3 + uses: actions/cache@v6 with: path: ${{ env.COMPOSER_CACHE_DIR }} key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} @@ -50,6 +50,6 @@ jobs: run: vendor/bin/phpunit --colors=always --coverage-clover clover.xml - name: Send code coverage report to Codecov.io - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 9976515..ac29fc6 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Install PHP uses: shivammathur/setup-php@v2 @@ -36,7 +36,7 @@ jobs: run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - name: Cache dependencies installed with composer - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ${{ env.COMPOSER_CACHE_DIR }} key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} @@ -47,4 +47,4 @@ jobs: run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - name: Run static analysis with PHPStan - run: vendor/bin/phpstan analyse + run: vendor/bin/phpstan analyse diff --git a/README.md b/README.md index e148af4..eaeb466 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,13 @@ dot-errorhandler is Dotkernel's PSR-15 compliant error handler. ## Version History -| Branch | Release | PSR-11 | Log Style Implementation | OSS Lifecycle | PHP Version | -|--------|----------|--------|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| -| 4.1 | `>= 4.2` | 2 | PSR-Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.4.1) | -| 4.1 | `< 4.2` | 2 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.1.1) | -| 4.0 | `< 4.1` | 1 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.0.2) | -| 3.0 | `< 4.0` | 1 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F3.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/3.4.1) | +| Branch | Release | PSR-11 | Log Style Implementation | OSS Lifecycle | PHP Version | +|--------|----------|--------|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| +| 5.0 | `>= 5.0` | 2 | PSR-Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F5.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/5.0.0) | +| 4.1 | `>= 4.2` | 2 | PSR-Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.4.1) | +| 4.1 | `< 4.2` | 2 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.1.1) | +| 4.0 | `< 4.1` | 1 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.0.2) | +| 3.0 | `< 4.0` | 1 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F3.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/3.4.1) | ## Documentation @@ -18,16 +19,16 @@ 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.4.0) +![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/5.0.0) [![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.1/LICENSE) +[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-errorhandler)](https://github.com/dotkernel/dot-errorhandler/blob/5.0/LICENSE) -[![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.1/graph/badge.svg?token=0KIJARS5RS)](https://codecov.io/gh/dotkernel/dot-errorhandler) -[![PHPStan](https://github.com/dotkernel/dot-errorhandler/actions/workflows/static-analysis.yml/badge.svg?branch=4.1)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/static-analysis.yml) +[![Build Static](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml) +[![codecov](https://codecov.io/gh/dotkernel/dot-errorhandler/branch/5.0/graph/badge.svg?token=0KIJARS5RS)](https://codecov.io/gh/dotkernel/dot-errorhandler) +[![PHPStan](https://github.com/dotkernel/dot-errorhandler/actions/workflows/static-analysis.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/static-analysis.yml) ## Adding the error handler diff --git a/SECURITY.md b/SECURITY.md index a471dd1..30ac4d8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,6 +4,7 @@ | Version | Supported | PHP Version | |---------|---------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| +| 5.0 | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F5.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/5.0.0) | | 4.1 | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.4.1) | | 4.1 | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.1.1) | | 4.0 | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.0.2) | @@ -12,9 +13,8 @@ ## Reporting Potential Security Issues -If you have encountered a potential security vulnerability in this project, -please report it to us at . We will work with you to -verify the vulnerability and patch it. +If you have encountered a potential security vulnerability in this project, please report it to us at . +We will work with you to verify the vulnerability and patch it. When reporting issues, please provide the following information: @@ -22,18 +22,12 @@ When reporting issues, please provide the following information: - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact -We request that you contact us via the email address above and give the -project contributors a chance to resolve the vulnerability and issue a new -release prior to any public exposure; this helps protect the project's -users, and provides them with a chance to upgrade and/or update in order to -protect their applications. +We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; +this helps protect the project's users and provides them with a chance to upgrade and/or update to protect their applications. ## Policy If we verify a reported security vulnerability, our policy is: -- We will patch the current release branch, as well as the immediate prior minor - release branch. - -- After patching the release branches, we will immediately issue new security - fix releases for each patched release branch. +- We will patch the current release branch, as well as the immediate prior minor release branch. +- After patching the release branches, we will immediately issue new security fix releases for each patched release branch. diff --git a/composer.json b/composer.json index 7337372..0c253c5 100644 --- a/composer.json +++ b/composer.json @@ -23,20 +23,20 @@ }, "require": { "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "dotkernel/dot-log": "^5.0", + "dotkernel/dot-log": "^5.3", "laminas/laminas-diactoros": "^3.8.0", "laminas/laminas-stdlib": "^3.21", - "laminas/laminas-stratigility": "^3.0 || ^4.0", - "mezzio/mezzio": "^3.19", + "laminas/laminas-stratigility": "^3.0 || ^4.3.1", + "mezzio/mezzio": "^3.28.1", "psr/http-message": "^1.0 || ^2.0", "psr/http-server-middleware": "^1.0.2" }, "require-dev": { - "laminas/laminas-coding-standard": "^3.0.1", + "laminas/laminas-coding-standard": "^3.1.0", "mikey179/vfsstream": "^1.6.12", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^10.5.45" + "phpstan/phpstan": "^2.2.5", + "phpstan/phpstan-phpunit": "^2.0.18", + "phpunit/phpunit": "^10.5.64" }, "autoload": { "psr-4": { diff --git a/docs/book/v5/configuration.md b/docs/book/v5/configuration.md new file mode 100644 index 0000000..77c1e0a --- /dev/null +++ b/docs/book/v5/configuration.md @@ -0,0 +1,61 @@ +# Configuration + +Register `dot-errorhandler` in your project by adding `Dot\ErrorHandler\ConfigProvider::class` to your configuration aggregator (to `config/config.php` for example), and add `\Dot\ErrorHandler\ErrorHandlerInterface::class` (to `config/pipeline.php` for example) **as the outermost layer of the middleware** to catch all exceptions. + +Configure the error handler as shown below. + +In **config/autoload/error-handling.global.php**: + +```php + [ + 'aliases' => [ + ErrorHandlerInterface::class => LogErrorHandler::class, + ], + ], + 'dot-errorhandler' => [ + 'loggerEnabled' => true, + 'logger' => 'dot-log.default_logger', + ] +]; +``` + +A configuration example for the default logger can be found in `config/log.global.php.dist`. + +When configuring the error handler in your application, you can choose between two classes: + +- `Dot\ErrorHandler\LogErrorHandler`: for logging and displaying errors +- `Dot\ErrorHandler\ErrorHandler`: for displaying errors only + +> Both `LogErrorHandler` and `ErrorHandler` have factories declared in the package's `ConfigProvider`. +> If you need a custom ErrorHandler, it must have a factory declared in the config, as in the below example: + +```php + [ + 'factories' => [ + \App\CustomErrorHandler::class => \App\CustomHandlerFactory::class, + ], + 'aliases' => [ + \Dot\ErrorHandler\ErrorHandlerInterface::class => \App\CustomErrorHandler::class, + ], + ], + 'dot-errorhandler' => [ + 'loggerEnabled' => true, + 'logger' => 'dot-log.default_logger', + ], +]; +``` + +Config examples can be found in this project's `config` directory. diff --git a/docs/book/v5/extra/cookie.md b/docs/book/v5/extra/cookie.md new file mode 100644 index 0000000..33abc03 --- /dev/null +++ b/docs/book/v5/extra/cookie.md @@ -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 behavior 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 cookie 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. +> 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. diff --git a/docs/book/v5/extra/header.md b/docs/book/v5/extra/header.md new file mode 100644 index 0000000..22ae4e5 --- /dev/null +++ b/docs/book/v5/extra/header.md @@ -0,0 +1,148 @@ +# Log header data + +Looking at `dot-errorhandler`'s config file, the array found at `HeaderProvider::class` allows you to configure the behavior of this provider: + +- **enabled**: enabled/disable this provider +- **processor**: an array configuring the data processor to be used by the **HeaderProvider**: + - **class**: data processor class implementing `Dot\ErrorHandler\Extra\Processor\ProcessorInterface` + - **replacementStrategy**: whether to replace specific header values completely or partially + - **sensitiveParameters**: an array of header names that may contain sensitive information so their value should be masked partially/completely + +## Configure provider + +By default, **HeaderProvider** 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 `header`. +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 header values using the strategy specified by the **replacementStrategy** + +```php +'sensitiveParameters' => [ + Dot\ErrorHandler\Extra\Processor\ProcessorInterface::ALL, +], +``` + +- use exact strings to list the headers for which the values should be altered using the strategy specified by the **replacementStrategy** + +```php +'sensitiveParameters' => [ + 'Authorization', +], +``` + +> **HeaderProcessor** uses EXACT header name lookups. +> To alter the value of a header, you need to specify the exact header name. + +> The config `sensitiveParameters` is case-insensitive. + +## Why should I use a processor + +Consider the following request headers: + +```text +[ + "Authorization" => "Bearer 63560eb4398d21024b32f2fb45dacca512db0bc725149e1371f493063a03e687", + "Content-Type" => "application/json", +] +``` + +Without a **HeaderProcessor**, the plain text auth token would end up saved in the log file: + +```text +..."extra":{"file":"/path/to/some/class.php","line":314,"header":{"Authorization":"Bearer 63560eb4398d21024b32f2fb45dacca512db0bc725149e1371f493063a03e687","Content-Type":"application/json"},... +``` + +But with a properly configured **HeaderProcessor**: + +```php +'processor' => [ + 'class' => HeaderProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + 'Authorization', + ], +], +``` + +the logged header data becomes: + +```text +..."extra":{"file":"/path/to/some/class.php","line":314,"header":{"Authorization":"***********************************************************************","Content-Type":"application/json"},... +``` + +## Special case + +There is a special case, the `cookie` header, which is handled differently than the rest of the headers. + +Let's take an example of a cookie header: + +```text +FRONTEND_SESSID=feb21b39f9c54e3a49af1f862acc8300; rememberMe=63560eb4398d21024b32f2fb45dacca512db0bc725149e1371f493063a03e687 +``` + +If the existing **HeaderProcessor** is not used, then the log file will contain dangerous data that may compromise user security – in this case exposing the value of both cookies. + +> To avoid this issue, the developer should never use **HeaderProvider** without a **HeaderProcessor** in a production environment. + +Depending on **HeaderProvider**'s configuration, **HeaderProcessor** will partially mask the cookie values: + +```text +FRONTEND_SESSID=feb21b39f9c54e3a****************; rememberMe=63560eb4398d21024b32f2****************************************** +``` + +when using `ReplacementStrategy::Partial` or completely mask the cookie values: + +```text +FRONTEND_SESSID=********************************; rememberMe=**************************************************************** +``` + +when using `ReplacementStrategy::Full`. + +## 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 **HeaderProvider** to use it. +For this, open `dot-errorhandler`'s config file and - under **HeaderProvider::class** - set **processor**.**class** to the class string of your custom processor: + +```php +HeaderProvider::class => [ + 'enabled' => false, + 'processor' => [ + 'class' => CustomHeaderProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + ProcessorInterface::ALL, + ], + ], +], +``` + +Using this, header data will be processed by `CustomHeaderProcessor` and logged as provided by this new processor. diff --git a/docs/book/v5/extra/introduction.md b/docs/book/v5/extra/introduction.md new file mode 100644 index 0000000..43decfb --- /dev/null +++ b/docs/book/v5/extra/introduction.md @@ -0,0 +1,33 @@ +# Extra data + +`dot-errorhandler` provides the following data: + +- **cookie**: an array containing the request cookies +- **header**: an array containing the request headers +- **request**: an array containing the request body (**\$_PATCH**/**\$_POST**/**\$_PUT**) +- **server**: an array containing the **\$_SERVER** values +- **session**: an array containing the **\$_SESSION** values +- **trace**: an array containing the full stack trace of the request + +## Configuring extra data + +At this point, you should already have `dot-errorhandler` configured. +If not, proceed to the [Configuration](../configuration.md) page, and when you're done, return to this page. + +To start logging one or more of the above data, we first need to enable them from the package's config file. +Open the config file and under `dot-errorhandler` locate the `ExtraProvider::CONFIG_KEY` key. +There you will find six associative arrays, each array representing a set of data this package can provide: + +- **CookieProvider::class**: request cookie information – [how to use](cookie.md) +- **HeaderProvider::class**: request header information – [how to use](header.md) +- **RequestProvider::class**: request body contents – [how to use](request.md) +- **ServerProvider::class**: server information – [how to use](server.md) +- **SessionProvider::class**: session contents – [how to use](session.md) +- **TraceProvider::class**: trace route – [how to use](trace.md) + +These providers and their configuration values are all optional. +If any of them is missing from the config file, the provider simply stays disabled and code execution continues normally. +Invalid configuration values are simply ignored because the purpose of these providers is to log the extra data if possible but not to interfere with the app logic. +That's why it does not throw errors on missing/invalid config values. + +> By default, `*Provider` classes are used in fall-through mode; without a processor, they just return the unaltered data they were given. diff --git a/docs/book/v5/extra/request.md b/docs/book/v5/extra/request.md new file mode 100644 index 0000000..2e4238d --- /dev/null +++ b/docs/book/v5/extra/request.md @@ -0,0 +1,127 @@ +# Log request data + +Looking at `dot-errorhandler`'s config file, the array found at `RequestProvider::class` allows you to configure the behavior of this provider: + +- **enabled**: enabled/disable this provider +- **processor**: an array configuring the data processor to be used by the **RequestProvider**: + - **class**: data processor class implementing `Dot\ErrorHandler\Extra\Processor\ProcessorInterface` + - **replacementStrategy**: whether to replace specific cookie values completely or partially + - **sensitiveParameters**: an array of cookie names that may contain sensitive information so their value should be masked partially/completely + +## Configure provider + +By default, **RequestProvider** 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 `request`. +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' => [ + 'password', +], +``` + +> **RequestProcessor** uses recursive search to locate all array keys in a multidimensional array. + +> **RequestProcessor** uses PARTIAL field name lookups. +> To alter the value of a request field, it is enough to specify only part of the field name. + +> The config `sensitiveParameters` is case-insensitive. + +## Why should I use a processor + +Consider the following request body sent via **$_POST**: + +```text +[ + "identity" => "myIdentity", + "password" => "p4$$w0rd", + "passwordConfirm" => "p4$$w0rd", + "details" => [ + "secret" => "s3cr3t", + ] +] +``` + +Without a **RequestProcessor**, the plain text passwords would end up saved in the log file: + +```text +..."extra":{"file":"/path/to/some/class.php","line":314,"request":{"identity":"myIdentity","password":"p4$$w0rd","passwordConfirm":"p4$$w0rd","details":{"secret":"s3cr3t"}}},... +``` + +But with a properly configured **RequestProcessor**: + +```php +'processor' => [ + 'class' => RequestProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + 'password', + 'secret', + ], +], +``` + +the logged request data becomes: + +```text +..."extra":{"file":"/path/to/some/class.php","line":314,"request":{"identity":"myIdentity","password":"********","passwordConfirm":"********","details":{"secret":"******"}}},... +``` + +## 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 **RequestProvider** to use it. +For this, open `dot-errorhandler`'s config file and - under **RequestProvider::class** - set **processor**.**class** to the class string of your custom processor: + +```php +RequestProvider::class => [ + 'enabled' => false, + 'processor' => [ + 'class' => CustomRequestProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + ProcessorInterface::ALL, + ], + ], +], +``` + +Using this, request data will be processed by `CustomRequestProcessor` and logged as provided by this new processor. diff --git a/docs/book/v5/extra/server.md b/docs/book/v5/extra/server.md new file mode 100644 index 0000000..9307fe0 --- /dev/null +++ b/docs/book/v5/extra/server.md @@ -0,0 +1,148 @@ +# Log server data + +Looking at `dot-errorhandler`'s config file, the array found at `ServerProvider::class` allows you to configure the behavior of this provider: + +- **enabled**: enabled/disable this provider +- **processor**: an array configuring the data processor to be used by the **ServerProvider**: + - **class**: data processor class implementing `Dot\ErrorHandler\Extra\Processor\ProcessorInterface` + - **replacementStrategy**: whether to replace specific server config values completely or partially + - **sensitiveParameters**: an array of server config names that may contain sensitive information so their value should be masked partially/completely + +## Configure provider + +By default, **ServerProvider** 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 `server`. +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 server config values using the strategy specified by the **replacementStrategy** + +```php +'sensitiveParameters' => [ + Dot\ErrorHandler\Extra\Processor\ProcessorInterface::ALL, +], +``` + +- use exact strings to list the server configs for which the values should be altered using the strategy specified by the **replacementStrategy** + +```php +'sensitiveParameters' => [ + 'SERVER_ADMIN', +], +``` + +> **ServerProcessor** uses EXACT server config name lookups. +> To alter the value of a server config, you need to specify the exact server config name. + +> The config `sensitiveParameters` is case-insensitive. + +## Why should I use a processor + +Consider the following request server configs: + +```text +[ + "SERVER_ADMIN" => "webmaster@localhost", + "SERVER_SOFTWARE" => "Apache/2.4.62 (AlmaLinux)", +] +``` + +Without a **ServerProcessor**, (for this example) the key **SERVER_ADMIN** would end up saved in the log file: + +```text +..."extra":{"file":"/path/to/some/class.php","line":314,"server":{"SERVER_ADMIN":"webmaster@localhost","SERVER_SOFTWARE":"Apache/2.4.62 (AlmaLinux)"},... +``` + +But with a properly configured **ServerProcessor**: + +```php +'processor' => [ + 'class' => ServerProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + 'SERVER_ADMIN', + ], +], +``` + +the logged server config data becomes: + +```text +..."extra":{"file":"/path/to/some/class.php","line":314,"server":{"SERVER_ADMIN":"*******************","SERVER_SOFTWARE":"Apache/2.4.62 (AlmaLinux)"},... +``` + +## Special case + +There is a special case, the `HTTP_COOKIE` server config value, which is handled differently than the rest of the values. + +Let's take an example of an **HTTP_COOKIE** value: + +```text +FRONTEND_SESSID=feb21b39f9c54e3a49af1f862acc8300; rememberMe=63560eb4398d21024b32f2fb45dacca512db0bc725149e1371f493063a03e687 +``` + +If the existing **ServerProcessor** is not used, then the log file will contain dangerous data that may compromise user security – in this case exposing the value of both cookies. + +> To avoid this issue, the developer should never use **ServerProvider** without a **ServerProcessor** in a production environment. + +Depending on **ServerProvider**'s configuration, **ServerProcessor** will partially mask the cookie values: + +```text +FRONTEND_SESSID=feb21b39f9c54e3a****************; rememberMe=63560eb4398d21024b32f2****************************************** +``` + +when using `ReplacementStrategy::Partial` or completely mask the cookie values: + +```text +FRONTEND_SESSID=********************************; rememberMe=**************************************************************** +``` + +when using `ReplacementStrategy::Full`. + +## 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 **ServerProvider** to use it. +For this, open `dot-errorhandler`'s config file and - under **ServerProvider::class** - set **processor**.**class** to the class string of your custom processor: + +```php +ServerProvider::class => [ + 'enabled' => false, + 'processor' => [ + 'class' => CustomServerProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + ProcessorInterface::ALL, + ], + ], +], +``` + +Using this, server config data will be processed by `CustomServerProcessor` and logged as provided by this new processor. diff --git a/docs/book/v5/extra/session.md b/docs/book/v5/extra/session.md new file mode 100644 index 0000000..c925249 --- /dev/null +++ b/docs/book/v5/extra/session.md @@ -0,0 +1,113 @@ +# Log session data + +Looking at `dot-errorhandler`'s config file, the array found at `SessionProvider::class` allows you to configure the behavior of this provider: + +- **enabled**: enabled/disable this provider +- **processor**: an array configuring the data processor to be used by the **SessionProvider**: + - **class**: data processor class implementing `Dot\ErrorHandler\Extra\Processor\ProcessorInterface` + +## Configure provider + +By default, **SessionProvider** 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 `session`. +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 + +**SessionProcessor** does not use **replacementStrategy**. + +> If you create a custom session processor, you may add **replacementStrategy** to the config file; it will get passed to your processor. + +### Sensitive parameters + +**SessionProcessor** does not use **sensitiveParameters**. + +> If you create a custom session processor, you may add **sensitiveParameters** to the config file; it will get passed to your processor. + +## Why should I use a processor + +The only advantage of using **SessionProcessor** is to reduce the size of the session data that you log. +In the below example, **$_SESSION** contains an **array** in _SessionContainer1_ and an **ArrayObject** in _SessionContainer2_. + +```text + "SessionContainer1" => array:3 [▼ + "_REQUEST_ACCESS_TIME" => 1739973274.7284 + "_VALID" => array:1 [▼ + "Laminas\Session\Validator\Id" => "feb21b39f9c54e3a49af1f862acc8300" + ] + "Default" => array:1 [▼ + "EXPIRE" => 1739969278 + ] + ] + "SessionContainer2" => Laminas\Stdlib\ArrayObject {#795 ▼ + #storage: array:2 [▼ + "tokenList" => array:1 [▼ + "b222251fb72d49ae0643bff11e11057d" => "389b5e5b415409abb61cfe718e7841bf" + ] + "hash" => "389b5e5b415409abb61cfe718e7841bf-b222251fb72d49ae0643bff11e11057d" + ] + #flag: 2 + #iteratorClass: "ArrayIterator" + #protectedProperties: array:4 [▼ + 0 => "storage" + 1 => "flag" + 2 => "iteratorClass" + 3 => "protectedProperties" + ] + } +``` + +By using **SessionProcessor**, the two items are reduced to: + +```text + "SessionContainer1" => array:3 [▼ + "_REQUEST_ACCESS_TIME" => 1739973274.7284 + "_VALID" => array:1 [▼ + "Laminas\Session\Validator\Id" => "feb21b39f9c54e3a49af1f862acc8300" + ] + "Default" => array:1 [▼ + "EXPIRE" => 1739969278 + ] + ] + "SessionContainer2" => array:2 [▼ + "tokenList" => array:1 [▼ + "b222251fb72d49ae0643bff11e11057d" => "389b5e5b415409abb61cfe718e7841bf" + ] + "hash" => "389b5e5b415409abb61cfe718e7841bf-b222251fb72d49ae0643bff11e11057d" + ] +``` + +As you can see, with arrays the difference is almost ignorable, but with ArrayObjects, the difference is significant. + +## 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 **SessionProvider** to use it. +For this, open `dot-errorhandler`'s config file and - under **SessionProvider::class** - set **processor**.**class** to the class string of your custom processor: + +```php +SessionProvider::class => [ + 'enabled' => false, + 'processor' => [ + 'class' => CustomSessionProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + ProcessorInterface::ALL, + ], + ], +], +``` + +Using this, cookie data will be processed by `CustomSessionProcessor` and logged as provided by this new processor. diff --git a/docs/book/v5/extra/trace.md b/docs/book/v5/extra/trace.md new file mode 100644 index 0000000..0082686 --- /dev/null +++ b/docs/book/v5/extra/trace.md @@ -0,0 +1,98 @@ +# Log trace data + +Looking at `dot-errorhandler`'s config file, the array found at `TraceProvider::class` allows you to configure the behavior of this provider: + +- **enabled**: enabled/disable this provider +- **processor**: an array configuring the data processor to be used by the **TraceProvider**: + - **class**: data processor class implementing `Dot\ErrorHandler\Extra\Processor\ProcessorInterface` + +## Configure provider + +By default, **TraceProvider** is enabled. +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 `trace`. +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 + +**TraceProcessor** does not use **replacementStrategy**. + +> If you create a custom session processor, you may add **replacementStrategy** to the config file; it will get passed to your processor. + +### Sensitive parameters + +**TraceProcessor** does not use **sensitiveParameters**. + +> If you create a custom session processor, you may add **sensitiveParameters** to the config file; it will get passed to your processor. + +## Why should I use a processor + +The only advantage of using **TraceProcessor** is to reduce the size of the trace data that you log. +In the below example, the trace route contains an array with dozens of items, each with the same structure (except for the last one). + +```text + 0 => array:5 [▼ + "file" => "/path/to/some/file.php" + "line" => 66 + "function" => "someFunction" + "class" => "Path\To\Some\File" + "type" => "->" + ] + 1 => array:5 [▼ + "file" => "/path/to/some/other/file.php" + "line" => 33 + "function" => "someOtherFunction" + "class" => "Path\To\Some\Other\File" + "type" => "->" + ] + ... + 58 => array:3 [▼ + "file" => "/path/to/index.php" + "line" => 36 + "function" => "{closure}" + ] +``` + +By using **TraceProcessor**, the array is reduced to: + +```text + 0 => "Path\To\Some\File->someFunction:66" + 1 => "Path\To\Some\Other\File->someOtherFunction:33" + ... + 58 => "/path/to/index.php->{closure}:36" +``` + +Yet it maintains the relevant information, but in a compact form. +This works because, since using namespaced classes, it's easy to determine file paths just by looking at a FQCN. + +## 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 **TraceProvider** to use it. +For this, open `dot-errorhandler`'s config file and - under **TraceProvider::class** - set **processor**.**class** to the class string of your custom processor: + +```php +TraceProvider::class => [ + 'enabled' => false, + 'processor' => [ + 'class' => CustomTraceProcessor::class, + 'replacementStrategy' => ReplacementStrategy::Full, + 'sensitiveParameters' => [ + ProcessorInterface::ALL, + ], + ], +], +``` + +Using this, trace data will be processed by `CustomTraceProcessor` and logged as provided by this new processor. diff --git a/docs/book/v5/installation.md b/docs/book/v5/installation.md new file mode 100644 index 0000000..3d2d181 --- /dev/null +++ b/docs/book/v5/installation.md @@ -0,0 +1,7 @@ +# Installation + +Install `dotkernel/dot-errorhandler` by executing the following Composer command: + +```shell +composer require dotkernel/dot-errorhandler +``` diff --git a/docs/book/v5/log-files.md b/docs/book/v5/log-files.md new file mode 100644 index 0000000..c94d3df --- /dev/null +++ b/docs/book/v5/log-files.md @@ -0,0 +1,23 @@ +# Log files + +## What is a log file + +Log files are plain text files, containing rows of log activity, each row being a standalone activity formatted as specified in `dot-errorhandler`'s configuration file. +By default, log activities are formatted with JSON, so each row should be a decodable JSON string. + +## What is in a log file + +Each row in a log file should contain the following values: + +- **timestamp**: string representation of the date and time when the error occurred +- **priority**: numeric representation of the error level +- **priorityName**: string representation of the error level +- **message**: error message describing the error +- **extra**: an array of extra information that may help the developer debug the error: + - **file**: the file in which the error occurred + - **line**: the line from **file** where the error occurred + +By leveraging `dot-errorhandler`'s extra providers, you can also log additional request parameters. +Learn more about what additional parameters are available on the [extra data](extra/introduction.md) page. + +> For a clear separation between different types of logs, we recommend that you store files from each type in their own directory. diff --git a/docs/book/v5/overview.md b/docs/book/v5/overview.md new file mode 100644 index 0000000..3a32091 --- /dev/null +++ b/docs/book/v5/overview.md @@ -0,0 +1,34 @@ +# Overview + +`dot-errorhandler` is Dotkernel's logging error handler, providing two options: + +## Version History + +| Branch | Release | PSR-11 | Log Style Implementation | OSS Lifecycle | PHP Version | +|--------|----------|--------|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| +| 5.0 | `>= 5.0` | 2 | PSR-Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F5.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/5.0.0) | +| 4.1 | `>= 4.2` | 2 | PSR-Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.4.1) | +| 4.1 | `< 4.2` | 2 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.1%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.1.1) | +| 4.0 | `< 4.1` | 1 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F4.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/4.0.2) | +| 3.0 | `< 4.0` | 1 | Laminas Log | ![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-errorhandler%2Fblob%2F3.0%2FOSSMETADATA) | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-errorhandler/3.4.1) | + +## 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/5.0.0) + +[![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/5.0/LICENSE) + +[![Build Static](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/continuous-integration.yml) +[![codecov](https://codecov.io/gh/dotkernel/dot-errorhandler/branch/5.0/graph/badge.svg?token=0KIJARS5RS)](https://codecov.io/gh/dotkernel/dot-errorhandler) +[![PHPStan](https://github.com/dotkernel/dot-errorhandler/actions/workflows/static-analysis.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/dot-errorhandler/actions/workflows/static-analysis.yml) + +## Features + +This package provides two features: + +- `Dot\ErrorHandler\ErrorHandler`, same as the Mezzio error handling class with the only difference being the removal of the `final` statement for making extension possible +- `Dot\ErrorHandler\LogErrorHandler` adds logging support to the default `ErrorHandler` class diff --git a/mkdocs.yml b/mkdocs.yml index 9d2f48e..f1bcfa7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,12 +2,26 @@ docs_dir: docs/book site_dir: docs/html extra: project: Packages - current_version: v4 + current_version: v5 versions: + - v5 - v4 - v3 nav: - Home: index.md + - v5: + - Overview: v5/overview.md + - Installation: v5/installation.md + - Configuration: v5/configuration.md + - "Log files": v5/log-files.md + - "Extra data": + - Introduction: v5/extra/introduction.md + - Cookie: v5/extra/cookie.md + - Header: v5/extra/header.md + - Request: v5/extra/request.md + - Server: v5/extra/server.md + - Session: v5/extra/session.md + - "Trace route": v5/extra/trace.md - v4: - Overview: v4/overview.md - Installation: v4/installation.md diff --git a/src/ErrorHandlerInterface.php b/src/ErrorHandlerInterface.php index 9e5cbb7..7542e5c 100644 --- a/src/ErrorHandlerInterface.php +++ b/src/ErrorHandlerInterface.php @@ -52,7 +52,7 @@ * error response, and can then react to them. They are best suited for * logging and monitoring purposes. * - * Listeners are attached using the attachListener() method, and triggered + * Listeners are attached using the attachListener() method and triggered * in the order attached. */ interface ErrorHandlerInterface extends MiddlewareInterface diff --git a/src/LogErrorHandler.php b/src/LogErrorHandler.php index 45fe3c2..d971cf8 100644 --- a/src/LogErrorHandler.php +++ b/src/LogErrorHandler.php @@ -82,7 +82,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface * triggers all listeners with the same arguments (but using the response * returned from createErrorResponse()), and then returns the response. * - * If a valid Logger is available, the error, and it's message are logged in the + * If a valid Logger is available, the error and its message are logged in the * configured format. */ public function handleThrowable(Throwable $e, ServerRequestInterface $request): ResponseInterface