Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Stopwatch Laravel Package

symfony/stopwatch

Symfony Stopwatch profiles PHP code: start and stop named events, group them into sections, and record lap times to measure where execution time goes. Install via Composer.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

Build vs. buy — and the real decision is what to build. The timer itself is a commodity: MIT-licensed, zero dependencies, ~a dozen classes, no config, no I/O. Buying it costs nothing. What no one sells is the instrumentation contract around it — event naming taxonomy, section conventions, threshold policy, output format. Stopwatch has no reporter, no sink, no serialization contract, so every team that adopts it writes the same thin wrapper. This package lets us make one deliberate decision — standardize a Profiler wrapper and facade — instead of letting ten squads improvise four dialects of db.query that can never be joined. That wrapper is the product; Stopwatch is a dependency of it.

Roadmap: a bounded performance-reliability track, not an observability program. The package supports a 2–3 sprint initiative with a clear end state: phase timing on the paths that carry the SLO (checkout, search ranking, auth), a pre-merge performance gate on the two most latency-sensitive paths, and JSON-lines output into an existing log channel. No new infrastructure, no data migration, no schema change, no backfill.

Prioritization of where to instrument first — queue jobs and Artisan commands, then HTTP middleware. This is the decision the package most directly informs. APM coverage is weakest on background jobs and console commands and the ROI is highest there; middleware timing is largely already covered by whatever APM we run. Instrumenting everything at once is the classic failure mode.

Feature-level decisions it accelerates: which code paths get phase boundaries (fetch → transform → persist), whether a given job class gets a duration budget, and whether staging requests are sampled for endpoint profiling. It also forces an explicit non-goal list — this is not an APM replacement, not a micro-benchmarking tool (durations are integer milliseconds; sub-millisecond work floors to zero), and not a flame-graph profiler. Debugbar and Telescope cover the dev-time introspection job better; we should not rebuild them.

Scope discipline worth naming up front: the package does nothing until someone writes start()/stop(). If we are not prepared to make manual instrumentation a team norm with a named owner, this initiative should not start — the tool is not at fault, the adoption model is.

When to Consider This Package

Adopt when:

  • We are on Laravel/Symfony and the Symfony component is likely already in vendor/ transitively (verify with composer why symfony/stopwatch before adding a direct constraint) — the cost is a version pin, not an install.
  • The team accepts manual instrumentation and we have a named owner for event naming and thresholds.
  • The goal is phase-level timing on a handful of known hot paths, in dev/staging/pre-deploy, with a narrow sampled production carve-out behind a flag.
  • License, security, and data-egress review needs to be a non-event: MIT, Symfony governance, no network surface, no data leaves the process.
  • We want a cheap exit ramp — a wrapper now means we can emit OpenTelemetry spans later without touching call sites.

Look elsewhere when:

  • We need sub-millisecond resolution (integer ms only), call-graphs, or flame charts — use a real profiler or Debugbar/Telescope.
  • We need distributed tracing across services; that is OpenTelemetry's job, and Stopwatch is at best a temporary local placeholder.
  • The workload runs on Octane, Swoole, RoadRunner, or long-lived queue daemons and we are not prepared to bind it scoped rather than singleton and reset per unit of work.
  • Continuous production profiling across the whole fleet is the ask — that is a vendor product, not this.
  • There is no owner for the taxonomy or the gate policy. Instrumentation untied to a threshold or a CI gate is theater, and theater is worse than nothing because it manufactures confidence.
  • The team will not add start/stop calls. Adoption will stall regardless of package quality.

Two operational caveats to resolve before committing to a constraint: the listed last release date is future-dated relative to a normal review cadence — treat it as a pipeline artifact and verify against Packagist and the GitHub tag list. And floor at Symfony 7.2+ (for Stopwatch::ROOT and getLastPeriod(), both real ergonomics wins), matching the Symfony major the framework already resolves; v8 is gated on a PHP 8.4 upgrade. Do not cite the dependents: 0 figure as adoption evidence — it is a metadata artifact of the Symfony monorepo split.

How to Pitch It (Stakeholders)

To executives: This is a one-week, one-line-rollback investment that buys us accountability on the handful of code paths that carry revenue. It adds no infrastructure, no vendor contract, no data-egress surface, and no compliance finding — MIT-licensed, zero runtime dependencies, maintained under Symfony governance. The deliverable is not "a profiler"; it is a shared standard for how we measure and a gate that stops latency regressions before they ship. Total ask is roughly 5–8 engineering days across two phases plus one named owner. The dominant risk is not breakage — it is false confidence from instrumentation nobody acts on, which we mitigate by tying every measurement to a threshold and capping ourselves at two blocking gates.

To engineering: It is ~a dozen classes, no I/O, no container coupling, droppable at any layer. Highest-value hooks in ROI order: queue job middleware (no base-class tax), an Artisan --profile flag, then sampled HTTP middleware, then three to five targeted service methods. Bind it as a scoped container singleton and put a thin Profiler facade in front of it — application code should never touch Stopwatch directly, and that single decision is what keeps the OpenTelemetry exit ramp open. Two API footguns to design around now: getDuration() returns integer milliseconds, and calling start() on an already-started event throws a LogicException that surfaces as a 500 the first time re-entrant code hits it. The wrapper absorbs both.

The ask, stated plainly: approve Phase 1 (provider, facade, job middleware, --profile flag, log channel) and Phase 2 (threshold config, test helper, two blocking CI gates), assign an owner for the naming taxonomy and gate-failure policy, and agree that the Stopwatch binding is scoped, not singleton. Everything else — how many paths we instrument, how strict the budgets are — is a reversible config change we can tune without a second approval.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings