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

sandermuller/stopwatch

A simple Laravel/PHP stopwatch package for measuring elapsed time, starting and stopping timers, and tracking laps or durations in your application.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Stopwatch is a Laravel-first instrumentation package: a service provider wires middleware, config publishing, Artisan commands (stopwatch:runs:list), a Debugbar timeline panel, and an MCP surface that exposes run data to agent/tooling consumers. That places it in the developer-observability layer of the stack, not the request-serving path — which is the right architectural slot for a TPM to defend. The MCP filter surface (threw) is the notable architectural wrinkle: profiling data is now consumable by automated tooling, so its correctness has downstream consumers beyond humans reading a CLI table.

Integration feasibility. Low-friction: composer install, publish config, opt-in via env. The v0.16.0 fixes are largely correctness fixes to behavior that was silently wrong (STOPWATCH_INJECT coercion, dropped deferred-job runs, missing TRANSIENT_EXCEPTION runs). Low integration cost, but the release also carries two semantic changes that touch contract-level behavior rather than internals.

Technical risk.

  • Pre-1.0 semver. v0.16.0 is a minor bump carrying behavior changes. Treat every 0.x minor as potentially breaking and pin exactly.
  • Timestamp semantics change. recorded_at now means start time; the CLI column is relabeled Started. Any downstream consumer — dashboards, saved queries, custom reports, MCP-driven analysis — that assumed end-time semantics is now silently misreading latency by the run's duration. The migration window is worse than a clean break: run files written pre-upgrade retain end-time semantics until pruning removes them, so a single runs directory will hold mixed-semantics records for one retention cycle.
  • started() contract change. Returning false after an auto-dropped no-checkpoint run changes control flow for any caller using started() as a guard. Not a signature change, so it won't fail loudly — it will fail quietly.
  • Silent default introduced. Published run_log configs lacking min_duration_ms now skip sub-50ms runs. This is a good default, but it retroactively changes volume and coverage on existing installs without a config edit — and anyone who was relying on capturing every run for a specific investigation will see gaps.
  • Env coercion fix has a blast radius in the other direction. Installations that "worked" only because a typo'd or false-valued STOPWATCH_INJECT still forced tracking will now genuinely stop tracking. Teams that believed they had data will find they don't.
  • Evidence gap. No prior assessment and no supplied dependency/compatibility data, so version support, PHP/Laravel constraints, and Debugbar version coupling are unverified here and must be confirmed before sign-off.

Key questions.

  1. Which Laravel/PHP versions and which Debugbar major does v0.16.0 support, and is Debugbar a hard or suggested dependency?
  2. What is the retention/pruning policy, and how long will mixed recorded_at semantics persist in our runs directory?
  3. Do we have any consumer (dashboard, notebook, MCP client, CI baseline) that parses recorded_at or the old column header Recorded?
  4. Does any code path use started() as a boolean guard where a new false changes behavior?
  5. Is min_duration_ms: 50 acceptable as our floor, or do we need full capture in any environment?
  6. Who else depends on stopwatch:runs:list --threw / MCP threw for failure reporting, and were their counts previously understated?
  7. Bus factor and release cadence for a single-maintainer 0.x package — is this a candidate for a fork-and-pin?

Integration Approach

Stack fit. Adopt as a dev/CI-only dependency. Keep it out of production runtime paths unless there is a specific, justified need to profile live traffic; the injection middleware and Debugbar toolbar are the two components most likely to cause production surprises, and this release exists partly because injection control was not being honored. Restrict installation to require-dev where the middleware is only registered in local/CI environments.

Migration path.

  1. Pin ^0.16.0 with a committed composer.lock.
  2. Read the published run_log config into version control before upgrading, and explicitly set min_duration_ms rather than relying on the new 50ms fallback — the fallback only applies to configs missing the key, so declaring it makes the behavior intentional and reviewable.
  3. Explicitly set STOPWATCH_INJECT to a real boolean in each environment's .env; do not rely on coercion. Audit for false, null, or misspelled values that were previously masked by the bug and will now change behavior.
  4. Grep for started() call sites and recorded_at consumers before merging.
  5. Clear or archive the existing runs directory at cutover so the mixed-semantics window is closed immediately rather than left to pruning. If historical run files must be retained, tag them by package version at ingest.

Compatibility. Two compatibility surfaces need explicit owners: (a) the runs-file format, which is version-dependent and mixed during transition, and (b) the CLI/MCP output schema, where a column was renamed. Anything that scrapes stopwatch:runs:list output by position or by header text is a break. The --threw and MCP threw fixes are compat-positive — filters now return runs they always should have — but they will change counts, so any alert threshold or baseline built on the old (understated) numbers needs recalibration.

Sequencing.

  1. Spike in a local branch: upgrade, publish config, verify command output and Debugbar panel.
  2. Update CI to the pinned version; capture a fresh baseline rather than comparing against pre-upgrade numbers.
  3. Land consumer-side fixes (dashboards, MCP clients, scripts) before the upgrade merges, not after.
  4. Roll to team dev environments; hold one retention cycle if any historical run file analysis matters.
  5. Re-evaluate at 1.0 for a production-adjacent posture.

Operational Impact

Maintenance. Pre-1.0 with a single maintainer and a fast minor cadence. Budget a recurring review of each minor's changelog — this release alone contains two behavior changes, one renamed output column, one changed default, and four substantive bug fixes. Pin exact versions, upgrade deliberately, and never float ^0.x without a lockfile. The addition of StructArmed architecture checks to CI is a positive maintainability signal: internal coupling is being governed, which lowers the odds of sprawling breakage in later minors.

Support. No vendor SLA. Internal ownership should sit with whoever owns developer tooling/CI, with a documented fallback: disable injection via env (now actually honored, per this release) or remove the package. The env-coercion fix is a support win — "tracking is on and I can't turn it off" stops being an unexplainable ticket — but expect a brief inverse wave of "why did my profiling data disappear" from environments that were only tracking due to the bug.

Scaling. Cost scales with run volume × retention, on disk. The new 50ms floor is a meaningful volume reducer for high-throughput local/CI suites and should be treated as the intended default. Watch the deferred-job fix: previously-lost runs now get recorded, so background/queue-heavy environments will see a step increase in run files immediately after upgrade. Confirm pruning runs on a schedule, not manually.

Failure modes to monitor post-upgrade.

  • Mixed-timestamp run files producing skewed duration reports (medium likelihood, high confusion).
  • started() returning false in a guard path, silently skipping profiling blocks (medium/high likelihood, silent).
  • Environments that stop tracking because a previously-ignored env value is now honored (high likelihood, low harm, high confusion).
  • Investigations missing sub-50ms runs due to the new default floor (medium likelihood, low harm, silent).
  • MCP/CLI threw consumers seeing a count jump and mistaking it for a regression rather than a fix (high likelihood, low harm if pre-announced).
  • Debugbar sub-1ms rendering change is cosmetic and carries no operational risk.

Ramp-up. Low. A developer can be productive in under an hour: install, publish config, wrap a code path in checkpoints, read stopwatch:runs:list. The MCP surface is the only piece requiring conceptual ramp-up, and it should be documented with the same care as the CLI since it is now a first-class consumer contract. Recommended enablement: a short internal note covering the recorded_at semantics change, the Started column rename, the 50ms default, and the fact that threw counts will rise — because that last one will otherwise be read as a regression by the first person who sees it.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums