aubes/shadow-logger-bundle
Symfony bundle adding a Monolog processor to transform/anonymize sensitive log data for GDPR compliance. Supports IP anonymization, hashing, encryption, and field removal via configurable mappings for context/extra, with strict and debug modes.
Installation:
composer require aubes/shadow-logger-bundle
Publish Configuration:
php artisan vendor:publish --tag=shadow-logger
This creates config/packages/shadow_logger.yaml.
Basic Setup:
Configure the bundle in config/packages/shadow_logger.yaml to target specific handlers/channels (e.g., handlers: ['app']).
Define field mappings for anonymization (e.g., user_ip: ['ip']).
First Use Case: Log a request with sensitive data:
$logger = $this->container->get('logger');
$logger->info('User action', [
'user_ip' => $request->ip(),
'user_name' => $user->name,
]);
The user_ip and user_name fields will be anonymized based on your configuration.
shadow_logger:
mapping:
context:
user_ip: ['ip'] # Replaces with anonymized IP (e.g., 192.0.2.0/24)
shadow_logger:
mapping:
context:
user_email: ['hash'] # One-way hash with salt
shadow_logger:
mapping:
extra:
credit_card: ['remove'] # Replaced with `--obfuscated--`
Combine multiple transformations for complex fields:
shadow_logger:
mapping:
context:
user_token: ['string', 'hash'] # Ensure Stringable objects are hashed
user_birthdate: ['truncate'] # Mask dates (e.g., "1990-01-**")
Use encryption when you need to recover original values (e.g., for GDPR requests):
shadow_logger:
encryptor:
key: '%env(SHADOW_LOGGER_ENCRYPTOR_KEY)%'
mapping:
context:
user_password_hash: ['encrypt'] # Stored as `['iv' => '...', 'value' => '...']`
Target nested arrays using dot notation:
shadow_logger:
mapping:
extra:
user.address.city: ['remove'] # Removes nested `city` field
user.metadata.token: ['hash'] # Hashes nested `token`
Enable debug mode to log transformer errors:
shadow_logger:
debug: '%kernel.debug%' # Only active in dev
strict: true # Set field to `null` on transformer errors
Extend functionality by creating a custom transformer:
// app/Transformer/CustomTransformer.php
namespace App\Transformer;
use Aubes\ShadowLoggerBundle\Transformer\TransformerInterface;
class CustomTransformer implements TransformerInterface {
public function transform(mixed $data): mixed {
return strtoupper($data); // Example: uppercase all strings
}
}
Register it in config/services.yaml:
services:
App\Transformer\CustomTransformer:
tags:
- { name: 'shadow_logger.transformer', alias: 'uppercase' }
Use it in config:
shadow_logger:
mapping:
context:
user_name: ['uppercase']
ShadowProcessor to specific handlers/channels (e.g., handlers: ['app']) to minimize overhead.PropertyAccessor, which is slower than direct key access. Prefer flat field names where possible.strict: true, transformer errors set the field to null. Set to false to preserve original values.debug: true in development to avoid logging sensitive errors in production.encoder.salt in .env and rotate it periodically (requires re-hashing all existing logs).remove for truly sensitive metadata.debug: true to log transformer errors in development.context/extra arrays in Monolog handlers.Stringable objects).encrypt for reversible anonymization to fulfill GDPR requests.remove or hash with log retention policies to delete or pseudonymize data.EncryptorInterface for algorithm-specific needs (e.g., AES-GCM).monolog.logger events to log or audit anonymization actions.shadow_logger.transformer and have a unique alias.user.data.user).string first to cast objects (e.g., ['string', 'hash']).How can I help you explore Laravel packages today?