northrook/error-handler
Composer 安装命令:
composer require northrook/error-handler
包简介
Capture and handle errors, build structured reports, and render consistent output
README 文档
README
Capture, buffer, aggregate, and render errors. Every event is recorded; emit channels (PSR log, render, terminate) apply filters and priority separately.
Requires PHP 8.4+.
Install
composer require northrook/error-handler
Quick start
use Northrook\ErrorHandler;
use Northrook\ErrorHandler\ErrorHandlerConfig;
use Northrook\ErrorHandler\ErrorLevelMask;
use Psr\Log\LoggerInterface;
$handler = ErrorHandler::register(
logger: $psrLogger, // optional; defaults to NullLogger
throwAt: ErrorLevelMask::Standard, // optional; see Throw mask
config: new ErrorHandlerConfig(debug: true),
);
// Uncaught exceptions and fatals are handled automatically once installed.
register() builds the singleton and, by default, installs global error / exception / shutdown handlers. Pass install: false to construct without wiring globals, then call $handler->install() when ready.
Design
| Principle | Meaning |
|---|---|
| Buffer ≠ log | The buffer is the full forensic record (including @-silenced). Logging is filtered. |
| Report ≠ handle | report() builds diagnostics without dying; handle() renders and exits. |
| Global ≠ scoped | Global handlers enforce throwAt; box() probes without throwing. |
| Priority ≠ PHP severity | EventPriority is consequence-based (Noise / Action / Critical), not E_*. |
Pipeline (current):
PHP error / throwable / box probe
↓
ErrorBuffer (always)
↓
Fingerprint → Aggregator (count + highest priority)
↓
Route: Critical → log now; else queue until shutdown flush
↓
handle() also renders + exit(1)
Registration & lifecycle
ErrorHandler::register()
ErrorHandler::register(
null|LoggerInterface $logger = null,
null|ErrorRendererInterface $renderer = null,
null|int|ErrorLevelMask $throwAt = null,
bool $install = true,
null|ErrorHandlerConfig $config = null,
): ErrorHandler
| Argument | Default | Role |
|---|---|---|
$logger | NullLogger | PSR-3 sink for aggregate emit |
$renderer | ErrorRenderer (CLI/HTML/JSON) | Fatal / handle() output |
$throwAt | ErrorLevelMask::Standard | Which PHP E_* types become exceptions |
$install | true | Wire global handlers immediately |
$config | new ErrorHandlerConfig() | Debug flag, render strategy, palette |
Install / uninstall / reset
$handler->install(); // set_error_handler, set_exception_handler, register_shutdown_function
$handler->uninstall(); // restore previous handlers
$handler->reset(); // uninstall (if installed), clear buffer + aggregator, drop singleton
Shutdown always flushes pending aggregates to the logger first, then handles fatal last-errors.
Configuration
use Northrook\Contracts\RenderStrategy;
use Northrook\ErrorHandler\ErrorHandlerConfig;
new ErrorHandlerConfig(
debug: true, // default: AppEnv::isDebug()
renderStrategy: RenderStrategy::AUTO, // honored by ReportFactory / dumps
colorPalette: null, // optional ColorPalette override
);
debug— whentrue,context['dumps']are turned into VarDump bags for CLI/HTML. Whenfalse, dumps are ignored.renderStrategy— passed into dump rendering (AUTOpicks CLI vs HTML by SAPI).
Throw mask (ErrorLevelMask)
Controls which PHP error types the global handler promotes to ErrorException. Independent of priority / logging.
use Northrook\ErrorHandler\ErrorLevelMask;
ErrorHandler::register(throwAt: ErrorLevelMask::Standard);
ErrorHandler::register(throwAt: E_USER_WARNING | E_USER_ERROR); // raw int also fine
| Case | Mask |
|---|---|
None | 0 — never throw from PHP errors |
Fatal | Fatals + recoverable |
Standard | E_ALL minus deprecations (default) |
WarningsAndAbove | Excludes notices and deprecations |
Strict | E_ALL including deprecations |
Silenced errors (error_reporting masks the type, or @) are always buffered and aggregated as Noise; they never throw.
Scoped probes — box()
Failsafe: catch PHP errors inside a callback, keep going. Never throws from the scoped handler.
$result = $handler->box(
fn () => $cache->warm($key),
// optional: EventPriority::Action,
);
if ($handler->lastBoxError() !== null) {
// inspect RuntimeError; process continues
}
| Behaviour | Detail |
|---|---|
| Default priority | Noise |
| Optional 2nd arg | EventPriority — elevates the aggregate for that scope |
| Buffer | Errors recorded on the shared ErrorBuffer |
| Aggregate | Each distinct fingerprint is hit; repeats bump count |
| Return | Callback return value (or null if the callback returns nothing useful) |
lastBoxError() is the last RuntimeError from the most recent box(); lastError() is the last entry in the global buffer.
Reports — report() vs handle()
report(Throwable $e, array $context = []): ErrorReport
Builds a structured ErrorReport (reference, snapshot, stack, previous chain, context, dumps, PHP errors). Does not exit.
Default priority: Action. Override with reserved context key:
$report = $handler->report($e, [
'priority' => EventPriority::Critical, // or 'Critical' / 'critical'
'orderId' => $orderId,
'dumps' => [
'cart' => $cart,
'user' => $user,
],
]);
echo $handler->renderer->json->render($report); // or cli / html
Reserved keys (stripped from stored context):
| Key | Effect |
|---|---|
priority | EventPriority (or case name string) — emit routing |
dumps | Labeled values → debug dump bags when config.debug is on |
handle(Throwable $e): never
Forces Critical, aggregates, logs immediately, sets HTTP 500 (when not CLI and headers not sent), renders via the composite renderer, then exit(1).
Uncaught exceptions go through handle() (except under PHPUnit, where they are rethrown).
Priority & aggregation
EventPriority
| Band | Meaning | Emit |
|---|---|---|
Noise | Forensic / hygiene | Batched at shutdown |
Action | Should be noticed | Batched; appears in actionables() |
Critical | Cannot usefully continue | Immediate log |
Defaults by path:
| Path | Priority |
|---|---|
Untagged box() | Noise |
Untagged report() | Action |
handle() / fatal shutdown | Critical |
| Global non-throwing / silenced | Noise |
Repeats of the same fingerprint elevate to the highest priority seen and bump count.
Fingerprint
Stable xxh32 of class|phpType + file + line + message — used for aggregation. Separate from the per-instance report reference (error-{xxh32}).
Standing list & flush
$handler->actionables(); // Action+ entries this request
$handler->aggregator()->all(); // every fingerprint
$handler->flushPendingAggregates(); // emit queued Noise/Action now (also called on shutdown)
Each emit is one PSR log line per fingerprint:
| Log level | Priority |
|---|---|
notice | Noise |
error | Action |
critical | Critical |
Context includes fingerprint, priority, count, class, reference (when a report exists), firstSeen, lastSeen.
Buffer inspection
$buffer = $handler->errors(); // ErrorBufferInterface (shared)
$buffer->all();
$buffer->last();
$mark = $buffer->mark();
$since = $buffer->since($mark);
Everything that hits the global or scoped handlers is recorded here, including silenced notices.
Renderers
ErrorRenderer picks CLI vs HTML by SAPI. JSON is available explicitly.
| Backend | Output |
|---|---|
CliRenderer | ANSI summary, stack, previous chain, dump CLI blobs |
HtmlRenderer | Error page with SourceView panes + HTML dump sections |
JsonRenderer | $report->jsonString() |
Source highlighting and var dumps come from northrook/php-debug — this package wires them in; it does not reimplement them.
Composite construction (optional overrides):
use Northrook\ErrorHandler\ErrorRenderer;
use Northrook\ErrorHandler\Renderer\CliRenderer;
use Northrook\ErrorHandler\Renderer\HtmlRenderer;
use Northrook\ErrorHandler\Renderer\JsonRenderer;
$renderer = new ErrorRenderer(
cli: new CliRenderer(),
html: new HtmlRenderer(new ErrorHandlerConfig(debug: true)),
json: new JsonRenderer(),
);
If a backend renderer itself throws, a dependency-light disaster fallback is printed and the failure is logged at critical.
Typed exception meta
ReportFactory attaches snapshot meta for known contract exceptions (e.g. filesystem path, curl URL). Extend buildMeta() as more types land in contracts.
Demos
From the package root:
php index.php # list demos
php index.php exception # uncaught → handle() view
php index.php box # failsafe probe
php index.php dumps # context dumps in CLI/HTML
php index.php aggregate # Noise counts + Action standing list + flush
# Browser
php -S localhost:8080 index.php
# open /?demo=exception
| Key | Scenario |
|---|---|
exception | Uncaught exception → full error view |
nested | Previous-exception chain |
warning | PHP warning promoted by throwAt |
box | Boxed probe; process continues |
silenced | Silenced notice buffered, then a real failure |
json | report() + JSON only (no exit) |
meta | Typed exception meta on the snapshot |
dumps | dumps => […] in report context |
aggregate | Repeated box Noise + Action report; standing list + batched flush |
Tests & static analysis
composer test
composer phpstan
Not yet implemented
Deferred (see PLAN.md): SilencePolicy / screamAt, ReportVerbosity Safe redaction, RuntimeMode presets, signature rules, SQLite/file persistence, WTHH disaster file, notification delivery.
northrook/error-handler 适用场景与选型建议
northrook/error-handler 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 07 月 15 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 northrook/error-handler 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 northrook/error-handler 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: BSD-3-Clause
- 更新时间: 2026-07-15