Releases: adelinferaru/nestedflowtracker
3.2.0
Adds the #[Trace] attribute — annotate a route action (or a whole controller), a route closure, or a queued job and it's wrapped in a span. No other code; the attribute is the opt-in.
use AdelinFeraru\NestedFlowTracker\Core\Attributes\Trace;
class CheckoutController
{
#[Trace('checkout')]
public function store(Request $request) { /* … */ }
}
#[Trace]
class SendInvoice implements ShouldQueue { /* … */ }- Route actions via a new
TraceActionmiddleware on the web/api groups — nests under the request root whenFLOW_AUTO_HTTPis on; 5xx responses mark the span failed. Controller methods, class-level attributes, invokable controllers, and attributed route closures all work. - Queued jobs carrying
#[Trace]are traced even withFLOW_AUTO_QUEUEoff — per-job opt-in instead of all-jobs; failed jobs record the exception. FLOW_ATTRIBUTES=falseis the kill switch (default on; detection is one cached reflection lookup per request/job).- PHP attributes are metadata, not decorators — there's no engine-level interception, so this works at the call sites the package owns; for arbitrary service methods keep using
Flow::span().
Full details in changelog.md. This closes the last deferred roadmap item.
3.1.3
Packaging and docs release — no code changes.
- Lean dist archive:
.gitattributesnowexport-ignores tests, docs, demo assets, and tooling config, socomposer requiredownloads only the package itself (~1.5 MB smaller). examples/plain-php.php: a runnable round trip without Laravel — trace a checkout (including a failed span) with the framework-agnostic Core, store it viaBufferedPdoDriverin SQLite, read the tree back with plain SQL.SECURITY.md(private disclosure path, supported versions) and CI/PHP/license badges in the README.
3.1.2
Metadata-only release: composer.json homepage now points to the landing page — https://adelinferaru.github.io/nestedflowtracker/ — and support links (issues, source, docs) are set so they show on Packagist. No code changes.
3.1.1
Patch release: nine correctness fixes from a full-codebase soundness review, each covered by a regression test. No API or schema changes — drop-in upgrade from 3.1.0.
Fixed
- Buffered drivers no longer drop continuation flows.
EloquentBufferedDriver,BufferedPdoDriver, andOtelDrivernow detect flow completion by the open-span count returning to zero instead of "the closed span has no parent". A flow continued viaoptions['parent_span_id']— whose outermost span has a non-null parent — was previously buffered and then silently discarded. Buffers are also detached before writing/exporting, so a failed insert/POST can no longer replay stale spans into the next flow. flow.auto.queueno longer wipes the caller's flow for sync-dispatched jobs. The sync queue driver fires the sameJobProcessing/JobProcessedevents as a worker, and the listener used toflush()unconditionally — orphaning the surrounding request/job root span. Jobs dispatched inside an open flow now nest under the current span; the closing listeners close the job's own span (cleaning up spans the job leaked open) instead of blindly popping the innermost.- Viewer no longer recurses infinitely on pre-2.1 rows with a NULL
span_id. Flow::end(['status' => …])with an invalid value no longer half-closes the span — the status override is validated before the stack is touched.Span::toRow()can no longer emitfalsefor unencodablecontext/result— invalid UTF-8 is substituted instead of failing the whole row.TraceContext::parse()reads only the sampled bit of the flags byte;TraceContext::spanId()passes 16-hex ids through and hashes non-numeric keys instead of(int)-casting them into the W3C-invalid all-zero id.- The JSON API clamps
per_pageto 1–100 — a negative value previously dropped the LIMIT clause entirely. - The OTel export listener registers only for the
databasedriver and re-checksflow.otel.enabledat fire time;flow:benchmarkno longer queues export jobs for its rolled-back flows. - Container-bound PSR-17
RequestFactoryInterface/StreamFactoryInterfaceare honored, as documented.
Full details in changelog.md.
2.5.1
Patch release.
Fixed
license.mddeclared the EU Public License v1.1 whilecomposer.jsonand the README declared MIT. The license file is now the standard MIT License, so all three agree. No code changes.
2.5.0
Adds a JSON read API over recorded flows, alongside the HTML viewer.\n\n## Endpoints\n\nGET {path}/api/flows # recent flows; ?component= ?status= ?per_page= ?page=\nGET {path}/api/flows/{trace} # one flow as a nested span tree\n\n\nServed from the viewer route group (shares flow.viewer.enabled, the viewFlow gate, and the viewer middleware). For stateless/token API clients, set flow.viewer.middleware to [\"api\"].\n\nNo migration. See the changelog.
2.4.0
Adds buffered (batched) database writes.\n\n## Added\n- flow.buffer / FLOW_BUFFER=true — the database driver buffers a whole flow in memory and writes it in a single bulk insert when the root span closes, instead of two writes per span. About 8× faster in the benchmark (in-memory SQLite). Off by default; spans persist only once the flow completes.\n\n## Changed\n- The viewer, flow:show, and the OTel export now reconstruct the tree from parent_span_id (ordered by started_at), so they work for both the immediate and buffered drivers. No migration required.\n\ndotenv\nFLOW_BUFFER=true\n\n\nSee the changelog.
2.3.0
A measure-first performance release.\n\n## Added\n- php artisan flow:benchmark — measures tracking overhead per driver (disabled / null / database) and reports microseconds per span. The database run is wrapped in a transaction and rolled back, so it leaves no data behind.\n- Index on flow_spans.created_at — speeds the viewer's recent-flows listing and flow:prune.\n\nIndicative overhead (in-memory SQLite; your DB/hardware will differ): disabled ~1µs/span, null driver ~60µs/span, database driver ~1.1ms/span — the database cost is dominated by per-span writes, motivating the buffered-write mode on the roadmap.\n\n## Upgrade\nRun the new migration: php artisan vendor:publish --tag=\"flow-migrations\" && php artisan migrate.\n\nSee the changelog.
2.2.0
Adds pluggable storage drivers — choose where finished spans go via flow.driver.\n\n## Drivers\n- database (default) — the nested-set store that powers the viewer and the artisan commands. Unchanged behavior.\n- log — write each span as a structured log line (flow.log.channel).\n- null — discard (the API stays on, nothing stored).\n- otel — send spans straight to an OTLP/HTTP collector with no database.\n\ndotenv\nFLOW_DRIVER=database # database | log | null | otel\n\n\nThe viewer, flow:show/flow:prune, and the flow.otel export remain database-only features.\n\n## Internals\n- FlowTracker now delegates persistence to a SpanDriver.\n- New parent_span_id column so parent linkage works without database row ids (powers the non-DB drivers and simplifies OTLP export).\n\n## Upgrade\nRun the new migration: php artisan vendor:publish --tag=\"flow-migrations\" && php artisan migrate. The default driver preserves existing behavior.\n\nSee the changelog.
2.1.0
Adds a lightweight, opt-in OpenTelemetry export — no OTel SDK dependency.\n\n## Added\n- Export completed flows to an OTLP/HTTP collector (OpenTelemetry Collector / Jaeger / Grafana Tempo). When a flow's root span closes, the whole trace is sent as OTLP-JSON to {endpoint}/v1/traces, on a queue.\n- span_id (16-hex) and microsecond started_at on flow_spans for correct OTLP span ids and timing; the outbound traceparent now uses the real span_id.\n\ndotenv\nFLOW_OTEL_ENABLED=true\nFLOW_OTEL_ENDPOINT=http://localhost:4318\n\n\n## Upgrade from 2.0\nRun the new migration: php artisan vendor:publish --tag=\"flow-migrations\" && php artisan migrate. Run a queue worker so exports happen off the request.\n\nSee the changelog.