adhocrat-io/arkhe-watcher
Composer 安装命令:
composer require adhocrat-io/arkhe-watcher
包简介
In-app monitoring (requests, exceptions, queries, jobs, logs, mail, scheduled tasks) for Laravel, branched onto Arkhè Main with a Flux UI dashboard. A laraowl-style watcher with no separate application to run.
README 文档
README
In-app monitoring for Laravel — requests, exceptions, queries, jobs, commands, scheduled tasks, logs and mail — branched directly onto Arkhè Main with a Flux UI dashboard and a Watcher menu.
It reproduces the core of laraowl's
application telemetry, but without a separate application to deploy. There
is no server to host, no laraowl/client to point at it, no Reverb WebSocket
server and no second queue: everything runs inside the host app and stores to a
single table. Think Telescope/Pulse, wearing Arkhè's admin chrome.
Requirements
- PHP 8.3+
adhocrat-io/arkhe-main^3.2 (this package requires it and mounts onto it — the navigation registry it branches onto landed in 3.2.0)- Livewire 4 + Flux 2 (already present in an Arkhè Main app)
Installation
composer require adhocrat-io/arkhe-watcher php artisan arkhe:watcher:install
The installer:
- publishes the config (
config/watcher.php) and the migrations, - runs the migrations (creates
watcher_entriesandwatcher_settings), - adds an
@sourceline toresources/css/app.cssso Tailwind scans the package's Blade views, - creates the
view-watcherpermission and grants it to therootandadministratorroles.
That's it — open /administration/watcher.
The Watcher menu needs no sidebar patching: the package registers its own
collapsible group into Arkhè Main's shared navigation registry (see below), and
Arkhè Main's sidebar partial renders it. As long as your layout includes
@include('arkhe::partials.sidebar-items') (Arkhè Main's installer wires that
in), the menu appears automatically.
How it branches onto Arkhè Main
-
Routes mount under Arkhè's admin prefix:
{arkhe.admin.prefix}/watcher(e.g./administration/watcher), namedarkhe.watcher.*. -
Access uses Arkhè's
web,authandarkhe.backendmiddleware, plus this package'sarkhe.watchergate: an Arkhè root always passes, otherwise the user needs theview-watcherpermission. -
Layout is resolved from
config('arkhe.admin.layout'), so dashboard pages render inside your existing Arkhè shell. -
Menu — the package registers a
watchersection on Arkhè Main'sArkheNavregistry from its service provider (requires Arkhè Main ≥ 3.2):ArkheNav::section('watcher', heading: fn () => __('arkhe-watcher::watcher.menu'), priority: 90, can: /* root or view-watcher */) ->item('overview', fn () => __('…'), 'chart-bar', route: 'arkhe.watcher.index') // …one item per dashboard page
This is the same mechanism any satellite package uses to branch onto Arkhè's backend — settings entries go into the shared
settings("Réglages") section, richer tools declare their own section like the Watcher does.
What it monitors
| Watcher | Captures | Toggle env |
|---|---|---|
| Requests | method, URI, route, status, duration, memory, user, slow flag | WATCHER_REQUESTS |
| Exceptions | class, message, file/line, trimmed stack trace, grouped by fingerprint | WATCHER_EXCEPTIONS |
| Queries | SQL, normalised fingerprint, bindings, time, connection, slow flag | WATCHER_QUERIES |
| Jobs | name, queue, connection, status, attempts, duration, error | WATCHER_JOBS |
| Commands | command, arguments, exit code, duration | WATCHER_COMMANDS |
| Schedule | scheduled task runs — finished / failed / skipped, output, cron | WATCHER_SCHEDULE |
| Logs | level, message, sanitised context | WATCHER_LOGS |
| subject, from/to/cc/bcc, mailer, HTML body | WATCHER_MAIL |
|
| Cache | hit / miss / write / forget by key (off by default — noisy) | WATCHER_CACHE |
| Outgoing HTTP | method, URL, status, duration for Http:: client calls |
WATCHER_HTTP |
Dashboard pages
Overview (headline counts + recent exceptions + slowest requests),
Requests, Exceptions (grouped, with occurrence counts), Queries
(slow-only filter), Issues (query health — see below), Jobs
(failed-only filter), Commands, Scheduled tasks, Logs (level filter) and
Mail. Every page has a time-range filter (1h / 24h / 7d / 30d / all),
free-text search, a detail flyout and live polling.
Query health — N+1, missing indexes & AI fixes
Reproducing the heart of wilfridterry/cardinal,
the Issues page surfaces database problems the analyzer derives from each
request's queries:
- N+1 detection — every query is normalised to a literal-free fingerprint
(
where id = ?); a fingerprint that fires more thanWATCHER_NPLUSONE_THRESHOLDtimes in one lifecycle is flagged as an N+1, with the offending queries marked. - Missing-index detection — a slow query filtering on an unindexed column is
flagged (best-effort, via schema introspection), naming the
table.column. - AI fix suggestions (opt-in) — on the Issues detail flyout (and via
php artisan arkhe:watcher:analyze <uuid>), the watcher asks Claude for a root-cause diagnosis and a concrete fix: a ready-to-run Laravel migration for a missing index, or the eager-loading change for an N+1. Enable withWATCHER_AI_ENABLED=trueand an API key; it calls the Anthropic Messages API through Laravel's HTTP client (no extra package dependency), defaulting toclaude-opus-4-8.
php artisan arkhe:watcher:issues prints the same report on the CLI.
Settings page
A root-only Settings page (arkhe.watcher.settings) lets you toggle the
master switch and each collector, and adjust retention, HTTP sampling and the
live-refresh interval — all from the UI. It is branched into Arkhè Main's shared
Réglages section (not the Watcher group), so it sits next to every other
package's settings. Values are stored in watcher_settings and layered over the
config-file defaults at boot (collector toggles take effect on the next request).
How recording works
Each watcher subscribes to framework events and pushes an IncomingEntry into a
buffered Recorder. The buffer is written in one bulk insert at the end of
each lifecycle — HTTP terminate, job processed, command finished, scheduled task
done — so monitoring stays off the request's critical path. Everything recorded
during one lifecycle shares a batch_id.
Recording is fail-safe (storage errors are swallowed), governed by a master
switch (WATCHER_ENABLED) and optional HTTP sampling (WATCHER_SAMPLING),
and never records its own dashboard reads.
Configuration highlights
// config/watcher.php 'enabled' => env('WATCHER_ENABLED', true), 'sampling' => env('WATCHER_SAMPLING', 1.0), // record this fraction of HTTP traffic 'retention_days' => env('WATCHER_RETENTION_DAYS', 7), 'slow' => ['request' => 1000, 'query' => 100, 'job' => 5000], // ms 'poll_interval' => env('WATCHER_POLL_INTERVAL', '10s'), 'connection' => env('WATCHER_DB_CONNECTION'), // keep monitoring off your primary DB 'detectors' => ['n_plus_one' => ['enabled' => true, 'threshold' => 5], 'missing_index' => ['enabled' => true]], 'ai' => ['enabled' => false, 'model' => 'claude-opus-4-8', 'api_key' => env('WATCHER_AI_API_KEY', env('ANTHROPIC_API_KEY'))],
Point connection at a separate database to isolate monitoring writes. Lower
sampling on busy production apps. Disable the cache watcher (default) unless
you are actively tuning cache behaviour.
Commands
php artisan arkhe:watcher:install # publish, migrate, wire the menu, grant access php artisan arkhe:watcher:prune # delete entries past retention (scheduled daily) php artisan arkhe:watcher:prune --hours=6 php artisan arkhe:watcher:clear # truncate everything (--force to skip the prompt) php artisan arkhe:watcher:issues # report N+1 / missing-index issues (--kind=, --hours=) php artisan arkhe:watcher:analyze <uuid> # AI diagnosis + fix for an issue (needs watcher.ai)
The daily prune is scheduled automatically (watcher.prune.schedule, default
0 2 * * *); it only runs if your app runs schedule:run.
Programmatic control
use Arkhe\Watcher\Watch; Watch::pause(); // stop recording Watch::resume(); Watch::withoutRecording(fn () => /* noisy bulk op */);
Differences from laraowl
laraowl is a standalone monitoring server with a client agent. Arkhè Watcher is the single-app model, so a few laraowl features that fundamentally need external infrastructure are intentionally out of scope: uptime/heartbeat checks from an outside vantage point, the WAF/firewall threat engine, multi-tenant teams/projects, and real-time WebSocket streaming (replaced by lightweight polling). Everything that observes the app itself is covered.
Testing
composer install
composer test
The suite covers the recording engine, every watcher, pruning, the access gate
and a full Flux render of all nine dashboard pages. tests/bootstrap.php falls
back to the sibling arkhe-main package's vendor/ when this package has not
been installed standalone, so the suite runs inside the monorepo without a
second composer install.
License
MIT. See LICENSE.
统计信息
- 总下载量: 2
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-29