aubes/shadow-logger-bundle
Composer 安装命令:
composer require aubes/shadow-logger-bundle
包简介
Monolog processor for anonymization
README 文档
README
This Symfony bundle provides a Monolog processor to transform log data in order to respect GDPR or anonymize sensitive data.
It allows IP anonymization, hashing, encryption, or removal of sensitive fields in logs.
Requirements
- PHP >= 8.1
- Symfony 6, 7 or 8
- Monolog 2 or 3
Installation
composer require aubes/shadow-logger-bundle
Configuration
# config/packages/shadow-logger.yaml shadow_logger: # Add "shadow-debug" in "extra" when a transformer throws an exception. # Recommended to use '%kernel.debug%' so it is only active in development. debug: '%kernel.debug%' # When a transformer throws an exception: # true → the field value is set to null # false → the original (untransformed) value is kept strict: true # Register ShadowProcessor on handlers OR channels (not both). # Scoping to specific handlers/channels is recommended for performance. handlers: ['app'] #channels: ['app'] # Salt used by the "hash" transformer (see Hash transformer section). encoder: salt: '%env(SHADOW_LOGGER_ENCODER_SALT)%' mapping: # Fields to transform in the log "context" context: user_ip: ['ip'] user_name: ['hash'] user_birthdate: ['remove'] # Fields to transform in the log "extra" extra: custom_field: ['remove']
Choosing between hashing and encryption
Both the hash and encrypt transformers protect sensitive data in logs, but they serve different purposes. Choosing the right one depends on what you need to do with the data after it is logged.
Hashing (hash)
Hashing is a one-way, irreversible operation. The original value cannot be recovered from the hash.
Use it when:
- You do not need to read back the original value
- You want to correlate log entries belonging to the same user (e.g. trace a user across multiple requests) without storing their identity — the same input always produces the same hash
- You want to pseudonymize data in compliance with GDPR
Limitations:
- If the space of possible values is small (e.g. an IP address), an attacker with access to the logs could reconstruct the original values through brute force
- The salt must be kept secret; rotating it means previously hashed values can no longer be correlated with new ones
- You cannot fulfill a GDPR "right of access" request using only the hashed value
Configuration:
shadow_logger: encoder: algo: 'sha256' # any algorithm from hash_algos() salt: '%env(SHADOW_LOGGER_ENCODER_SALT)%' binary: false
Always configure a
saltto prevent rainbow table attacks. Store it as a secret environment variable.
Encryption (encrypt)
Encryption is a reversible operation. The original value can be recovered using the key and the IV stored alongside it.
Use it when:
- You may need to read back the original value later (e.g. to respond to a GDPR right of access or right of erasure request, or to debug a production issue with proper authorization)
- You want to store sensitive data in logs in a protected form without losing it permanently
Limitations:
- Requires secure key management: if the key is compromised, all encrypted log entries are exposed
- Key rotation is complex: old entries encrypted with a previous key can no longer be decrypted with the new one
- The presence of the IV in the log reveals that the original field was non-empty, which may itself be sensitive
- More computationally expensive than hashing
Quick comparison
hash |
encrypt |
remove |
|
|---|---|---|---|
| Reversible | No | Yes (with key) | No |
| Correlate entries | Yes (same input → same output) | No (IV is random) | No |
| Protect against brute force | With a strong salt | Yes | Yes |
| GDPR right of access | No | Yes | No |
| Key management required | Salt only | Key + IV | None |
Transformers
The following transformers are available out of the box:
| Alias | Description |
|---|---|
ip |
Anonymizes an IPv4 or IPv6 address |
hash |
Hashes the value using the configured algorithm |
string |
Casts a scalar or Stringable object to string |
remove |
Replaces the value with --obfuscated-- |
encrypt |
Encrypts the value (requires encryptor configuration) |
truncate |
Masks the middle of a value, keeping start and/or end visible (requires truncator configuration) |
Chaining transformers
Transformers can be chained. They are applied in order, the output of one becoming the input of the next. For example, to hash a Stringable object:
shadow_logger: mapping: context: custom_field: ['string', 'hash']
Hash transformer
The hash transformer uses the configured encoder. See the Hashing section above for configuration options.
Encrypt transformer
The encrypt transformer supports two modes: a built-in encryptor based on OpenSSL, or a custom implementation.
Built-in encryptor
shadow_logger: encryptor: key: '%env(SHADOW_LOGGER_ENCRYPTOR_KEY)%' cipher: 'aes-256-cbc' # optional, default: aes-256-cbc
The key must be kept secret and should be provided via an environment variable. The cipher can be any algorithm supported by OpenSSL (openssl_get_cipher_methods()).
Custom encryptor
If you need a different encryption strategy, implement EncryptorInterface:
// src/Encryptor/EncryptorAdapter.php namespace App\Encryptor; use Aubes\ShadowLoggerBundle\Encryptor\EncryptorInterface; class EncryptorAdapter implements EncryptorInterface { public function encrypt(string $data, string $iv): string { // your encryption logic return $encryptedValue; } public function generateIv(): string { // generate a random IV return $iv; } }
Register it as a service (if not using autoconfiguration):
# config/services.yaml services: App\Encryptor\EncryptorAdapter: ~
Then reference it by its service ID:
shadow_logger: encryptor: 'App\Encryptor\EncryptorAdapter'
Output format
In both cases, the transformer replaces the field value with:
[
'iv' => 'abc123', // base64-encoded IV used during encryption
'value' => '...', // encrypted value
]
Truncate transformer
The truncate transformer masks the middle of a value while keeping a configurable number of characters visible at the start and/or end. It is useful for partially revealing values like card numbers, email addresses, or tokens.
Named variants are declared under truncators. Each variant becomes available as a transformer alias: default → truncate, others → truncate_{name}.
shadow_logger: truncators: default: # alias: "truncate" keep_start: 2 keep_end: 2 mask: '***' card: # alias: "truncate_card" keep_start: 4 keep_end: 4 mask: '****' email: # alias: "truncate_email" keep_start: 1 keep_end: 0 mask: '***' mapping: context: card_number: ['truncate_card'] # 4242424242424242 → 4242****4242 email: ['truncate_email'] # john@example.com → j*** token: ['truncate'] # abcdef1234 → ab***34
| Option | Description | Default |
|---|---|---|
keep_start |
Number of characters to keep at the beginning | 2 |
keep_end |
Number of characters to keep at the end | 2 |
mask |
String used to replace the hidden part | *** |
If the value is shorter than or equal to
keep_start + keep_end, it is replaced entirely by the mask.
Mapping
Nested fields
Field names can use dot notation to target nested array keys.
Given the following extra structure:
'user' => [ 'id' => 42, 'name' => [ 'first' => 'John', 'last' => 'Doe', ], 'ip' => '1.2.3.4', ]
You can map nested fields like this:
shadow_logger: mapping: extra: user.ip: ['ip'] user.name.first: ['hash'] user.name.last: ['remove']
Note: Dot notation uses the Symfony PropertyAccessor internally, which is slower than direct key access. Prefer flat field names when possible.
Custom transformer
Implement TransformerInterface:
// src/Transformer/CustomTransformer.php namespace App\Transformer; use Aubes\ShadowLoggerBundle\Transformer\TransformerInterface; class CustomTransformer implements TransformerInterface { public function transform(mixed $data): mixed { // transform and return the value return $data; } }
Register it as a service with the shadow_logger.transformer tag and an alias:
# config/services.yaml services: App\Transformer\CustomTransformer: tags: - { name: 'shadow_logger.transformer', alias: 'custom' }
The alias is the name used in the mapping configuration:
shadow_logger: mapping: context: some_field: ['custom']
aubes/shadow-logger-bundle 适用场景与选型建议
aubes/shadow-logger-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 30 次下载、GitHub Stars 达 0, 最近一次更新时间为 2023 年 04 月 11 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「log」 「symfony」 「monolog」 「bundle」 「gdpr」 「anonymise」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 aubes/shadow-logger-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 aubes/shadow-logger-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 aubes/shadow-logger-bundle 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A GeoIP decorator/processor for monolog
The bundle for easy using json-rpc api on your project
A Zend Framework module that sets up Monolog for logging in applications.
Laravel 5.6 Monolog custom telegram channel
A Monolog processor to add X-Request-Id or UNIQUE_ID env to monolog stack if present, provide a default one otherwise. Optionally, add a forwarded request-id list.
PSR-3 compatible logger with dynamic file naming and hourly rotation, powered by Monolog
统计信息
- 总下载量: 30
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 17
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2023-04-11