wickedbyte / tombstone
PHP 的 Tombstone 模式的基本实现,用于揭示僵尸代码
Requires
- php: 8.2.* || 8.3.*
- psr/cache: ^1.0 || ^2.0 || ^3.0
- psr/event-dispatcher: ^1.0
- psr/log: ^1.0 || ^2.0 || ^3.0
- psr/simple-cache: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- phpstan/extension-installer: ^1.3.1
- phpstan/phpstan: ^1.10.65
- phpstan/phpstan-phpunit: ^1.3.16
- phpunit/phpunit: ^11.0.8
- psy/psysh: ^0.12.2
- rector/rector: ^1.0.3
- slevomat/coding-standard: ^8.15
- squizlabs/php_codesniffer: ^3.9
README
此库包含多种处理代码库中 Tombstone 击中的方式,包括触发 PHP 错误(例如 E_USER_DEPRECATED
)的处理程序,使用本地文件系统跟踪 Tombstone 击中,以及用于您项目现有 PSR-3 Logger、PSR-14 Event Dispatcher、PSR-6/PSR-16 Cache 实现的快速集成。
安装和配置
使用 Composer 以非开发依赖项安装
composer require wickedbyte/tombstone
在您的项目启动过程或服务容器中(例如通过服务提供者),配置一个新的 GraveyardConfiguration
实例,并将其传递给 Graveyard::config()
方法。例如
use WickedByte\Tombstone\Graveyard; use WickedByte\Tombstone\GraveyardConfiguration; Graveyard::config(new GraveyardConfiguration(handlers: [ new \WickedByte\Tombstone\Handlers\InMemoryRateLimitHandler(), new \WickedByte\Tombstone\Handlers\PhpErrorHandler(), // Add additional handlers for your project here... ]));
如果出于某种原因,在设置配置之前击中了 tombstone,则库将默认使用回退配置,将 tombstone 击中记录为 PHP E_USER_DEPRECATED
错误。
GraveyardConfiguration
类接受以下命名参数
-
rethrow_exceptions
:一个布尔值,表示在处理TombstoneActivated
事件时是否应该重新抛出或抑制异常。这可能在调试时很有用,但在生产中应该禁用。默认值为false
。 -
trace_depth
:包含在 tombstone 追踪中的堆栈帧数。这可以用于减小 tombstone 日志输出的大小。默认值为10
。将值设置为0
将使用完整的回溯堆栈跟踪。 -
logger
:一个可选的 PSR-3 日志记录器实例,用于将处理TombstoneActivated
事件时发生的异常记录为错误。注意:此日志记录器与用于 PSR-3 Tombstone 处理程序的日志记录器是分开的,尽管您当然可以将相同的LoggerInterface
实例传递给两者。 -
handlers
:一个TombstoneHandlerInterface
实例数组,当 tombstone 被击中时将调用。处理程序将按数组中定义的顺序调用。如果处理程序将TombstoneActivated
实例的$propagate
属性设置为false
,则不会调用其他处理程序。这可以用于防止日志或其他副作用。默认值是InMemoryRateLimitHandler
和PhpErrorHandler
。
使用方法
要标记您的代码中的一个位置为 tombstone,请使用 tombstone
函数
\tombstone('2021-01-01 This code is *probably* dead');
或者,您可以直接使用 Graveyard::tombstone()
静态方法
\WickedByte\Tombstone\Graveyard::tombstone('2021-01-01 This code is *probably* dead');
这两种方法都接受一个任意的字符串消息参数。消息应该是简短的,并可能包含有关何时或为什么添加了代码 tombstone 的日期或其他信息。当 tombstone 被击中时,将记录消息,并将其用作 tombstone 的唯一标识符的一部分。这意味着如果您可以通过使消息字符串动态来增加更多粒度。
第二个参数 $extra
是一个可选的数组,其中包含可以由您的自定义辅助实现使用的额外上下文信息。例如,如果您添加了一个发送电子邮件通知的处理程序,则可以使用 $extra
数组来包括添加 tombstone 的人的电子邮件地址和收件人地址。
Tombstone 处理程序
包含的 Tombstone 处理程序
InMemoryRateLimitHandler
虽然假定已经死亡代码不太可能经常被击中,但为了安全起见总是好的,尤其是在为生产日志存储付费时。
为了减少在循环或高频情况下触碰到墓碑时的垃圾邮件日志和其他副作用,此处理程序将限制记录的墓碑触发的次数,每次请求只记录一次。更准确地说——对于非HTTP环境,如队列工作者和cron作业来说很重要——是针对配置的处理类实例的每一次实例化。底层数组是墓碑的8字节标识符与值true
的键/值对,以最小化内存使用。
PhpErrorHandler
当触碰到墓碑时,此处理程序将触发PHP错误,允许您的项目的错误处理系统将墓碑触发记录为任何其他PHP错误。默认错误级别为E_USER_DEPRECATED
,但也支持其他三个运行时用户错误级别(E_USER_ERROR
、E_USER_WARNING
和E_USER_NOTICE
)。
FilesystemGraveyardHandler
此处理程序使用本地文件系统跟踪墓碑触发。提供目录路径(如果不存在,则可以创建目录),墓碑激活将被记录在该目录下的文件中,每个墓碑ID一个文件。如果您想重置墓碑,则需要手动清理目录。我们只有在文件不存在的情况下才会修改文件。
PsrLoggerHandler
此处理程序将墓碑触发记录到PSR-3日志实例,例如Monolog。默认日志级别为warning
,但可以使用PSR-3的任何日志级别进行配置。处理程序将记录有关墓碑触发的额外上下文信息,包括墓碑的消息、堆栈跟踪以及当前请求的上下文信息。
PsrEventDispatcherHandler
此处理程序与您现有的PSR-14事件调度器集成,并调度TombstoneActivated
事件。这允许您向事件添加额外的监听器,这些监听器不需要实现TombstoneHandlerInterface
接口,并且与项目中的其他事件监听器一起定义。
PsrCacheHandler
/ PsrSimpleCacheHandler
这些处理程序将使用PSR-6或PSR-16缓存实例来缓存墓碑触发。如果缓存实现使用某种远程驱动程序,如Redis或Memcached,则这有助于在多个服务器或进程之间跟踪墓碑触发。缓存键是墓碑的唯一标识符,值是TombstoneActivated
实例或1
。后者在内存和带宽方面效率更高,但不包括墓碑的消息或堆栈跟踪,这对于调试可能很有用,因为它显示了墓碑是如何被触发的,以及由谁触发的。
默认缓存TTL为86400
秒(24小时),但可以配置为任何非负整数值。如果TTL设置为0
,则缓存永远不会过期——尽管技术上允许,但您可能不希望这样做。
创建自定义墓碑处理程序
要创建自定义处理程序,实现TombstoneHandlerInterface
接口
use WickedByte\Tombstone\TombstoneActivated; interface TombstoneHandlerInterface { public function handle(TombstoneActivated $tombstone): void; }
然后将您的自定义处理程序实例添加到GraveyardConfiguration
实例。处理程序可以通过调用Graveyard::config()->pushHandlers()
或Graveyard::config()->setHandlers()
方法在运行时动态添加或重置。
如果您想停止将墓碑事件传播到其他处理程序,请将传入的TombstoneActivated
实例的$propagate
属性设置为false
。
贡献
运行make
以构建项目Docker镜像,创建"./build"缓存目录,并使用Composer安装依赖项。
要升级项目依赖项到当前主版本,运行make upgrade
,或仅在其当前定义的约束范围内更新它们,运行make update
使用Makefile目标执行常见操作
make bash
make phpunit
make psysh
make phpcs
make phpstan
make rector
make rector-dry-run
make ci
要获得一个全新的开始,运行make clean
以删除vendor和构建目录,这将触发在下次运行make
时重新构建Docker镜像。
对于Makefile中未定义的其他任何内容,请使用
docker compose run --rm -it app {your-command-here}