metricpanel/php
MetricPanel PHP is a lightweight client for sending application metrics to MetricPanel from Laravel and PHP projects. Track custom events and key business data, then monitor trends, build dashboards, and configure alerts with simple setup.
MetricPanel arrives as a v0.1.0 initial release — a pre-1.0 package, so treat everything below as "verify against the README before you build on it." The release note is deliberately narrow: it says the export is tested and allowlisted from the canonical source, and it defers installation and delivery semantics to the README. That tells you two things worth acting on immediately: the package is distributed through a controlled channel (so mirroring/forking it may not be supported), and the README — specifically whatever section covers delivery guarantees — is the primary spec, not the code.
Minimal path to a first signal:
"vendor/metricpanel": "0.1.0"), not a caret. On a 0.x release a caret lets a breaking minor in silently.php artisan vendor:publish --provider="...\MetricPanelServiceProvider" (confirm the FQCN from the README), then read the published config top to bottom before changing anything. The defaults encode the author's assumptions about storage, sampling, and enablement.php artisan migrate and inspect the created tables — column shape tells you what dimensions are first-class.register/boot for bindings and route registration, and at routes/ for the panel endpoints. This is where you'll find auth middleware, prefixes, and whether the panel is registered unconditionally.First use case: instrument a single thing you already understand — one controller action or one queued job — and confirm the value lands in the panel end to end. Don't start with a broad sweep across the app; you won't be able to tell a collection bug from a configuration bug.
Read the delivery guarantees section with a skeptical eye. "Tested export" is a statement about the artifact, not about runtime durability. The questions that matter are: are writes synchronous or buffered, what happens when the store is unreachable, and is data loss on shutdown acceptable to you. If the README is silent, assume best-effort and design accordingly.
Wrap ingestion in your own boundary. The single highest-value pattern with a 0.x metrics package is to never call it directly from application code. Define a thin interface in your domain (MetricsRecorder, Telemetry) with the two or three methods you actually need, and let the package be one implementation behind it. When v0.2.0 renames a method or changes an argument order, you edit one adapter class instead of grepping the codebase.
Record at boundaries, not in the middle of logic.
JobProcessed/JobFailed. This catches the jobs your HTTP middleware never sees.Schedule::call that emits aggregate counts after the fact, rather than instrumenting every iteration of a loop.Decouple the write path. If the package writes synchronously, wrap the recorder in a queued job or dispatch after the response (dispatchAfterResponse, or terminate middleware) so a slow or unavailable metrics store cannot add latency to user requests. This is the difference between a metrics package being invisible and being an incident.
Gate the panel properly. Panel routes registered by a package frequently land outside the web group or with a different middleware stack than you expect. Put an explicit auth + can:viewMetricPanel middleware in front of the prefix, and define that ability as a Gate in a service provider rather than relying on the package's default authorization. Verify with an unauthenticated request from a private window — this is the check people forget.
Separate collection from display. In production you usually want collection on and the UI off, or the UI restricted to staff. If the package exposes a single enable/disable switch, split it: drive collection from one env var and route registration from another, wrapping route registration in a config check in your own provider if necessary.
Neutralize it in tests. Set the package's enabled flag to false in phpunit.xml, or bind a no-op implementation of your Telemetry interface in the test container. Otherwise tests inherit production-shaped config and you get either flaky assertions on counts or writes escaping to a real store.
For multi-tenant apps, check early whether the package supports a tenant/label dimension natively. If not, inject it at your adapter layer so every call site doesn't have to remember.
Semver on 0.x is doing real work. v0.1.0 to v0.2.0 may break config keys, method signatures, or storage schema with no deprecation cycle. Pin exactly, upgrade deliberately, and read the diff rather than the changelog — for a first release there's no changelog history to trust yet.
"Allowlisted export" implies a distribution constraint. If the package is delivered from a canonical source rather than Packagist, confirm how your CI and your colleagues' machines authenticate to that source. A private/vendored channel that works locally and fails in CI is a common and annoying first-week surprise. Also check your license posture before depending on it.
Cardinality is the failure mode for every metrics system. One label containing a user ID, a raw URL with a path parameter, or an exception message will blow up storage and dashboard query time. Constrain dimensions at your adapter: normalize routes to names, bucket durations, whitelist error types. This is far cheaper to do on day one than to clean up.
Unpublished config means silent defaults. A package can run fine with no published config file while using defaults you'd never have chosen — usually "enabled everywhere." Publish it explicitly so the settings are visible in review, and so config caching behaves predictably. After any config change in a cached environment, php artisan config:clear.
Retention and growth. Ask where samples go and who prunes them. If the package ships a prune command, schedule it; if it doesn't, the table is yours to manage and it will only become obvious in month three.
Debugging order when nothing appears in the panel: (1) is collection enabled for this env; (2) is the config cached with stale values; (3) is a queue worker actually running if writes are queued; (4) is there an authorization failure on the read side making an empty chart look like missing data. That last one burns people — check the network tab before the database.
Extension points to inspect before you need them: the container bindings in the service provider (a driver or repository interface you can rebind), any published views you can override, and whether panel widgets are registered through a registry you can add to. A 0.1.0 package's most stable API is often its bindings, because the author needs them for their own tests.
Overall recommendation: adopt it behind an abstraction, pinned, in a non-critical path first. The release note is too thin to justify deeper commitment until you've confirmed the delivery guarantees yourself.
How can I help you explore Laravel packages today?