sturents / sentry-light
PHP官方Sentry客户端的轻量级替代方案。从kodus/sentry分支而来
Requires
- php: >=8.0
- ext-json: *
- psr/http-message: ^1 | ^2
- psr/log: ^1 | ^2 | ^3
Requires (Dev)
- codeception/codeception: ^5.0
- codeception/module-asserts: *
- nyholm/psr7: ^1.0
- vimeo/psalm: ^5
This package is auto-updated.
Last update: 2024-09-20 12:17:32 UTC
README
轻量级无依赖的Sentry客户端。由于原包不再维护且在较新版本的PHP中导致中断,因此从kodus/sentry
分支而来。
关于
本包是Sentry官方PHP客户端的替代方案。
库包括一个客户端类、一个与Sentry API形状匹配的事件模型,以及一个用于扩展的接口。
API与统一API建议不同 - 我们的目标是记录详细的异常,并捕获导致这些异常的日志条目,尽可能减少与客户端的耦合和依赖。
大多数成员声明为protected
,您可以通过简单修改(完全类型提示的)模型来进一步扩展和覆盖/增强异常/错误/请求处理的各个方面。
功能
此客户端具有官方客户端的大部分功能,还有一些额外功能。
所有功能都是可选的,该包附带以下扩展
EnvironmentReporter
:报告PHP和操作系统版本、服务器名称、站点名称等。RequestReporter
:报告关于(PSR-7)HTTP请求的详细信息。ExceptionReporter
:提供具有源代码上下文、路径/文件名、行号等详细堆栈跟踪。ClientSniffer
:解析客户端(浏览器或机器人)名称/版本/操作系统并添加有用的标记。ClientIPDetector
:解析代理后面的用户IP的X-Forwarded-For
和Forwarded
头。BreadcrumbLogger
:将PSR-3日志事件报告为面包屑。
非功能
- 没有内置的错误处理程序:您的框架/堆栈/应用程序可能已经有了,并且此客户端几乎可以轻松地集成到任何地方。
- 没有记录后数据:清除/消毒不可靠。(如果您愿意承担风险,模型中提供了字段,您可以实现自己的扩展。)
使用方法
现在,大多数现代框架都有某种类型的DI容器和错误处理程序。
为了避免陷入各种框架的具体细节,在本节中,我们将展示如何独立于任何特定框架启动和集成客户端。
要启动客户端本身,您需要一个Sentry DSN、一个EventCapture
实现以及您选择的扩展 - 此示例使用DirectEventCapture
和大多数内置扩展
$client = new SentryClient( new DirectEventCapture( new DSN("https://0123456789abcdef0123456789abcdef@sentry.io/1234567"), "tcp://proxy.example.com:5100" // optional: required if you're behind a proxy ), [ new EnvironmentReporter(), new RequestReporter(), new ExceptionReporter(), new ClientSniffer(), new ClientIPDetector(), ] ); $client->sample_rate = 50; // optional: percentage of calls to `captureException()` to actually capture
一些扩展支持额外的选项,这些选项将在配置部分中描述。
要捕获PHP错误,我们需要添加一个将错误映射到内置的ErrorException
类实例的错误处理程序。
请注意,大多数框架和错误处理器已经内置了类似的功能 - 现有的错误处理器可能设计为唯一的全局错误处理器,并且可能提供对 set_error_handler()
的抽象和一些类型的API。
以下简化的错误处理器会抛出所有错误级别(除了 E_NOTICE
和 E_WARNING
),后者它静默地捕获到我们上面创建的 $client
实例。
set_error_handler( function ($severity, $message, $file, $line) use ($client) { $error = new ErrorException($message, 0, $severity, $file, $line); if ($severity & (E_ALL & ~E_NOTICE & ~E_WARNING)) { throw $error; } else { $client->captureException($error); } }, );
现在我们已经将 ErrorException
抛出作为 PHP 错误,我们可以通过在顶层脚本中的任何语句周围使用 try
/catch
-语句一致地处理任何错误/异常。
try { // ... dispatch your router or middleware-stack, etc. ... } catch (Throwable $error) { $client->captureException($error); // ... render an apology page for disappointed users ... }
现在我们有了基本的错误处理,以及静默捕获警告和通知。
在 PSR-15 中间件上下文中,我们可以捕获有关引发错误的 ServerRequestInterface
实例的更多有用信息 - 通常,我们将在中间件栈的顶部使用中间件来完成此操作,该中间件将从 try
/catch
-块委托给下一个中间件。
以下是将匿名中间件添加到中间件数组的基本示例。
$middlewares = [ new class ($client) implements MiddlewareInterface { /** * @var SentryClient */ private $client; public function __construct(SentryClient $client) { $this->client = $client; } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { try { return $handler->handle($request); } catch (Throwable $error) { $this->client->captureException($error, $request); // ... return an apology response for disappointed users ... } } }, // ... the rest of your middleware stack ... ];
此中间件捕获到的任何错误 不会 泡泡到顶层脚本中的第一个 try
/catch
-语句 - 相反,中间件中 captureException()
的调用包含了 $error
和 $request
(在顶层脚本中尚不存在)从其中客户端可以捕获更多详细信息。
此外,您的应用程序可能在正常操作期间记录一些有用的信息(例如数据库查询) - 在失败的情况下,这些信息可以帮助您诊断导致错误的事件。
这些日志条目可以使用提供的 BreadcrumbLogger
捕获,作为所谓的“面包屑”,它既是 PSR-3 LoggerInterface
实现,也是 SentryClientExtension
。
您可能希望将其作为主日志记录器启动 - 也许您只关心导致错误条件的日志条目。然而,更有可能您想要另一个日志记录器将日志事件发送到持久日志,并记录为面包屑。(例如,您可能尝试 monolog/monolog
包,该包允许您将日志记录到任何组合的 PSR-3 和 monolog 处理器,过滤日志条目等 - 或者如果您喜欢简单的东西,尝试 mouf/utils.log.psr.multi-logger
。)
请注意,日志条目将在捕获异常之前在日志记录器中缓冲 - 如果您的应用程序是处理多个请求的 CLI 脚本,您需要在成功的请求结束时手动调用日志记录器实例的 clear()
,否则日志条目将累积在请求之间。
注意:PHP 7.4 引入了一个新的 ini 设置(zend.exception_ignore_args
),用于从堆栈跟踪中排除参数。如果您希望将参数传递给 Sentry,则需要关闭此设置。
配置
一些扩展支持可选的构造函数参数来配置一些可选功能。
ExceptionReporter
构造函数接受两个可选参数
$root_path
- 如果指定,项目根路径将不会出现在堆栈跟踪中可见的文件名中。$max_string_length
- 指定报告的 PHP 值将被截断的最大长度。$filters
- 指定要从堆栈跟踪中过滤的一个或多个文件名模式。
此外,公共 $error_levels
属性允许您自定义 PHP 错误级别映射到 Sentry 严重级别的方式。默认配置与官方 2.0 客户端相同。
ClientSniffer
如果您的客户群使用稀有或异国客户端,您可以将自己的正则表达式模式添加到公共的$browser_patterns
和$os_patterns
属性中,以增强浏览器分类。默认配置将识别大多数常见的浏览器和版本、操作系统和爬虫。
ClientIPDetector
替换或添加到$user_ip_headers
,以在特殊环境中检测客户端IP地址。内置模式支持大多数常规缓存/代理服务器。
BreadcrumbLogger
默认的$log_levels
与官方(2.0)客户端匹配 - 如果需要,您可以自定义PSR-5日志级别到Sentry严重级别的映射。
BufferedEventCapture
有可用的缓冲EventCapture
实现。
如果您只捕获异常/错误,可能不需要这个 - 但如果您将警告和通知映射到具有错误处理程序的ErrorException
,可能希望避免在向Sentry发送时阻塞响应。
您可以使用BufferedEventCapture
装饰器来实现这一点,它允许您在向用户发送响应后延迟实际的HTTP请求。
在这种情况下,您需要分别启动捕获和客户端实例。
$buffer = new BufferedEventCapture( new DirectEventCapture( new DSN("https://0123456789abcdef0123456789abcdef@sentry.io/1234567") ), ); $client = new SentryClient($buffer);
由于事件现在将缓冲而不是直接发送到Sentry,您需要在请求结束时手动刷新事件。
在一个典型的PHP FCGI SAPI环境中,您可以通过在将事件刷新到Sentry之前明确关闭HTTP响应来实现这一点 - 例如,从index.php
文件。
register_shutdown_function(function () use ($buffer) { fastcgi_finish_request(); $buffer->flush(); });
定制
客户端类和扩展旨在考虑项目特定的扩展,并包含许多用于您扩展和覆盖其行为的protected
方法。
使用protected
重写,您可以自定义事件创建和捕获的方式、异常和请求的处理方式、客户端IP检测和过滤、PHP值在堆栈跟踪中的格式化,以及其他许多细节。
请参考源代码以获取可用的protected
方法 - 并请注意,我们致力于以语义版本化此包:对protected
方法的任何重大更改都将作为主要版本发布。
为什么?
公开表达的看法
官方Sentry PHP客户端的1.x版本已经过时,并不适合现代(PSR-7/15)应用程序堆栈。
2.0版本(目前正在开发中)是建筑杰作 - 这并不是我们从本质上收集一些数据和执行简单的JSON POST请求的所需/想要的东西。
特别是
- 我们不需要错误处理程序 - 每个现代应用程序堆栈都已经有一个。
- 我们不想有一个复杂的架构和自定义中间件 - 简单的函数就可以。
- 我们不想记录POST数据 - 存在太多的风险。
- 更少的代码 ~> 更少的错误(希望如此;您不希望错误记录器本身崩溃。)
- 无依赖项:无冲突,无麻烦。
我们想要简单、快速和透明的东西。
我们还坚持良好的IDE支持代码,这为阅读/修改代码的人提供了更好的洞察力,并减少了静默错误的可能性 - 官方客户端处理array
值,而我们的模型以实现JsonSerializable
的简单PHP类层次结构正式描述JSON体形状。
请注意,我们只模拟在PHP环境中有意义的JSON体形状部分 - 如果您发现某些内容缺失或不正确,欢迎提交pull-requests。