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

Traceflow Laravel Laravel Package

smartness/traceflow-laravel

TraceFlow for Laravel adds lightweight request tracing to your app, capturing the flow of HTTP requests, queries, jobs, and events so you can see where time goes. Simple setup, configurable sampling, and clear timelines help debug slow endpoints and understand production behavior.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register. composer require smartness/traceflow-laravel, then publish the config: php artisan vendor:publish --tag=traceflow-config (confirm the tag from the provider's publishes() call — there's no README to lean on). Laravel's auto-discovery handles the service provider; check bootstrap/providers.php / config/app.php only if discovery is disabled.

Read the config file before anything else. It is the whole control surface: storage driver, sampling rate, redaction lists, and which instrumentations (queries, events, jobs, outbound HTTP) are enabled. This is also where you'll first see the real API names, since the published stub is often the only accurate documentation.

Set three env vars for the first run: enablement, sampling, and storage. Start with TRACEFLOW_ENABLED=true, TRACEFLOW_SAMPLE_RATE=1.0, and the log driver — not an external collector. Get a trace on disk before you get one on a wire.

Pick one concrete target. Don't instrument the whole app on day one. Choose your slowest endpoint or a nightly scheduled command, hit it in staging, and open the in-browser timeline viewer for that single trace. The goal of the first session is to confirm spans actually appear and are correlated — middleware, queries, and any dispatched job under one ID.

Verify it's running, not just installed. Hit a route and check for a trace ID in a response header or log context, then confirm the configured store received a record. A silent no-op (wrong driver, sampling disabled, middleware not registered) is the most common first-day outcome.

Where to look first in the source. The service provider (what gets bound and registered), the HTTP middleware (ordering and exception behavior), and the span/context class (how the trace ID is propagated into jobs). Those three files tell you more than any generated docs.

Implementation Patterns

Default is one trace per request; the value is in the attached children. The day-to-day workflow is: reproduce a slow user action, grab the trace ID, read the timeline top-to-bottom to see whether the time is in the DB, an outbound call, or queue wait. Sort queries by count first — an N+1 loop is visually obvious in a timeline in a way it isn't in a log file.

Propagate the trace ID across async boundaries explicitly. The advertised "shared trace ID across nested jobs and events" only holds if the ID is serialized onto the job payload when dispatched from a request. Verify that a job dispatched from a traced request lands under the same trace in the viewer. If it doesn't, you need to attach the context yourself — pass the trace ID through the job's constructor or a job middleware. Don't let a job start a fresh trace; attach to the existing one.

Wrap non-instrumented code in manual spans. The package covers middleware, queries, events, jobs, and HTTP by default; your domain logic and third-party SDK calls won't be. Use the facade/manual span API (TraceFlow::span('pricing.calculate', fn () => ...) — verify the exact name) around the two or three functions you actually care about timing. Resist wrapping everything; span sprawl makes the timeline unreadable.

Use it as a before/after measurement tool. Capture a trace of the slow path, make the optimization (eager-load, cache, index), capture again, and compare the same span names. This is the single highest-value day-to-day use: it converts "the page feels faster" into a per-span number you can put in a PR description.

Redact at the config layer, not the call site. Configure redaction for headers (Authorization, Cookie), query bindings, and request bodies up front. Default to redacting more than you think you need, then whitelist. Doing this per-span is unmaintainable and easy to forget on a new integration.

Sample by environment. 100% in staging and local so traces are always available for debugging; a low rate in production (start 1–5%, raise only if storage is cheap). If the package supports tail sampling or always-on-for-errors, enable that — you want the failed request even at a 1% head rate.

Put the trace ID where humans will find it. Add it to the response header and to your exception handler's log context. When support gets a ticket, the trace ID is the first thing you ask for, and it turns "we can't reproduce it" into a filter in the viewer.

Abstract behind your own Tracer interface. Bind a thin internal interface (startSpan, currentTraceId, addAttribute) that delegates to the package. When you outgrow it — or need to swap to the OTel PHP SDK — the cost is one adapter, not a rewrite. This is the cheapest insurance you can buy on a zero-adoption package.

Treat the viewer as a single-trace debugger, not a dashboard. It's for inspecting one trace's timeline. Aggregate questions (p95 per route, error rate) belong in your logs, metrics, or an APM — don't try to bend the viewer into that.

Gotchas and Tips

Synchronous export will stall your request path. If the storage driver posts to a collector and the collector is down, every request pays the timeout. Confirm export is batched/async and set a short timeout before this touches production. Keep an env-driven kill switch so you can disable tracing without a deploy.

Test under php artisan config:cache and route:cache. Packages that read config in a service provider commonly break when the cache is warm. Run both locally before rollout — this is a five-minute check that prevents a deploy-day surprise.

Middleware ordering matters and isn't obvious. Tracing should be outermost enough to capture the full lifecycle, but after trusted-proxy and CORS handling so preflights don't pollute your traces. Verify it captures your auth/session middleware's time and that an exception thrown downstream still closes the span rather than leaking it.

Long-lived workers are the classic failure mode. Queue workers and Octane/Swoole keep the process alive across requests and jobs, so tracer state must reset per unit of work. Symptoms: spans from job A appearing in job B's trace, and memory growth over hours. Test explicitly on Horizon and Octane — not just php artisan serve.

PII capture is on by default more often than you expect. Query bindings, request bodies, and headers frequently contain emails, tokens, and card-adjacent data. Audit exactly what the viewer stores and how long it retains it before enabling in any environment with real user data. This is the one gotcha with regulatory rather than operational consequences.

Understand how timings are measured before you cite them. Confirm whether a job span is wall-clock (includes queue wait) or execution time. Attributing queue latency to job execution will send you optimizing the wrong thing.

Low sample rates make your p95 a lie. Never compute a latency SLO or compare optimization results from a 5% sample without checking the confidence interval. Do the before/after at 100% in staging.

The version matrix is unverified. Read composer.json for PHP and Laravel bounds against your app before committing, and pin the version. There's no changelog to tell you when a framework major breaks the middleware, so add a CI job that runs your suite against each Laravel upgrade with tracing enabled.

Assume you may own this code. At zero stars and zero dependents you're the first production user of a package on the request hot path. Read the middleware's try/catch behavior so you know whether a tracer bug can throw into a live request, keep the fork posture in your back pocket, and name an internal owner for the sampling policy and version pinning. The extension points worth knowing are the storage driver contract, redaction callbacks, and custom span attributes — those are where you adapt it, and where a fork would live if you need one.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log