ivuorinen/monolog-gdpr-filter

Monolog processor for GDPR masking with regex and dot-notation paths

1.0.0 2025-07-28 12:14 UTC

This package is auto-updated.

Last update: 2025-07-28 12:16:21 UTC


README

Monolog GDPR Filter is a PHP library that provides a Monolog processor for GDPR compliance. It allows masking, removing, or replacing sensitive data in logs using regex patterns, field-level configuration, and custom callbacks. Designed for easy integration with Monolog and Laravel.

Features

  • Regex-based masking for patterns like SSNs, credit cards, emails
  • Field-level masking/removal/replacement using dot-notation paths
  • Custom callbacks for advanced masking logic per field
  • Audit logging for compliance tracking
  • Easy integration with Monolog and Laravel

Installation

Install via Composer:

composer require ivuorinen/monolog-gdpr-filter

Usage

Basic Monolog Setup

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Ivuorinen\MonologGdprFilter\GdprProcessor;
use Ivuorinen\MonologGdprFilter\FieldMaskConfig;

$patterns = GdprProcessor::getDefaultPatterns();
$fieldPaths = [
    'user.ssn' => GdprProcessor::removeField(),
    'payment.card' => GdprProcessor::replaceWith('[CC]'),
    'contact.email' => GdprProcessor::maskWithRegex(),
    'metadata.session' => GdprProcessor::replaceWith('[SESSION]'),
];

// Optional: custom callback for advanced masking
$customCallbacks = [
    'user.name' => fn($value) => strtoupper($value),
];

// Optional: audit logger for compliance
$auditLogger = function($path, $original, $masked) {
    error_log("GDPR mask: $path: $original => $masked");
};

$logger = new Logger('app');
$logger->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
$logger->pushProcessor(
    new GdprProcessor($patterns, $fieldPaths, $customCallbacks, $auditLogger)
);

$logger->warning('This is a warning message.', [
    'user' => ['ssn' => '123456-900T'],
    'contact' => ['email' => 'user@example.com'],
    'payment' => ['card' => '1234567812345678'],
]);

FieldMaskConfig Options

  • GdprProcessor::maskWithRegex() — Mask field value using regex patterns
  • GdprProcessor::removeField() — Remove field from context
  • GdprProcessor::replaceWith($value) — Replace field value with static value

Custom Callbacks

Provide custom callbacks for specific fields:

$customCallbacks = [
    'user.name' => fn($value) => strtoupper($value),
];

Audit Logger

Optionally provide an audit logger callback to record masking actions:

$auditLogger = function($path, $original, $masked) {
    // Log or store audit info
};

IMPORTANT: Be mindful what you send to your audit log. Passing the original value might defeat the whole purpose of this project.

Laravel Integration

You can integrate the GDPR processor with Laravel logging in two ways:

1. Service Provider

// app/Providers/AppServiceProvider.php
use Illuminate\Support\ServiceProvider;
use Ivuorinen\MonologGdprFilter\GdprProcessor;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $patterns = GdprProcessor::getDefaultPatterns();
        $fieldPaths = [
            'user.ssn' => '[GDPR]',
            'payment.card' => '[CC]',
            'contact.email' => '', // empty string = regex mask
            'metadata.session' => '[SESSION]',
        ];
        $this->app['log']->getLogger()
            ->pushProcessor(new GdprProcessor($patterns, $fieldPaths));
    }
}

2. Tap Class (config/logging.php)

// app/Logging/GdprTap.php
namespace App\Logging;
use Monolog\Logger;
use Ivuorinen\MonologGdprFilter\GdprProcessor;

class GdprTap
{
    public function __invoke(Logger $logger)
    {
        $patterns = GdprProcessor::getDefaultPatterns();
        $fieldPaths = [
            'user.ssn' => '[GDPR]',
            'payment.card' => '[CC]',
            'contact.email' => '',
            'metadata.session' => '[SESSION]',
        ];
        $logger->pushProcessor(new GdprProcessor($patterns, $fieldPaths));
    }
}

Reference in config/logging.php:

'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single'],
        'tap' => [App\Logging\GdprTap::class],
    ],
    // ...
],

Configuration

You can configure the processor to filter out sensitive data by specifying:

  • Regex patterns: Used for masking values in messages and context
  • Field paths: Dot-notation paths for masking/removal/replacement
  • Custom callbacks: For advanced per-field masking
  • Audit logger: For compliance tracking

Testing & Quality

This project uses PHPUnit for testing, Psalm and PHPStan for static analysis, and PHP_CodeSniffer for code style checks.

Running Tests

To run the test suite:

composer test

To generate a code coverage report (HTML output in the coverage/ directory):

composer test:coverage

Linting & Static Analysis

To run all linters and static analysis:

composer lint

To automatically fix code style and static analysis issues:

composer lint:fix

Notable Implementation Details

  • If a regex replacement in regExpMessage results in an empty string or the string "0", the original message is returned. This is covered by dedicated PHPUnit tests.
  • If a regex pattern is invalid, the audit logger (if set) is called, and the original message is returned.

Directory Structure

  • src/ — Main library source code
  • tests/ — PHPUnit tests
  • coverage/ — Code coverage reports
  • vendor/ — Composer dependencies

Legal Disclaimer

CAUTION: This library helps mask/filter sensitive data for GDPR compliance, but it is your responsibility to ensure your application fully complies with all legal requirements. Review your logging and data handling policies regularly.

Contributing

If you would like to contribute to this project, please fork the repository and submit a pull request.

License

This project is licensed under the MIT License. See the LICENSE file for more details.