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

Laravel Spectra Laravel Package

spectra-php/laravel-spectra

Laravel Spectra is the Laravel integration for the Spectra PHP package. It provides config publishing, service-provider registration, and framework-friendly helpers so you can add Spectra to Laravel apps with minimal setup and familiar conventions.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Spectra is a cross-cutting cost-observability layer that instruments Laravel's HTTP client and the major AI SDK stacks (Prism, Laravel AI SDK, openai-php, Guzzle), persists a row per AI call plus daily aggregates, and exposes budgets, alerts, OpenTelemetry spans and a dashboard. For a TPM this is a governance dependency, not a feature dependency: it is the system of record for "what did AI cost us, per user, per tenant, per feature, per request." It fits best in a Laravel monolith or modular monolith where AI spend is a material line item and where finance/product need attribution and budget guardrails. It fits poorly where AI calls happen outside Laravel (edge workers, Python services), since those calls will be invisible and your cost picture will silently under-report.

Integration feasibility. Standard Laravel package shape: composer install, publish config and migrations, migrate, optionally schedule spectra:prune. v2 adds roughly a dozen columns to the tracked-request table and matching daily-stat totals, plus two new config keys (tracking.trace_per_request, tracking.use_traceparent) and spectra.costs.exchange_rates. The trace model is the notable architectural addition: one trace per HTTP request/job/command, propagation into dispatched jobs, and adoption of an inbound W3C traceparent as the parent span. That is a genuine interoperability win if you already run OpenTelemetry, and it turns Spectra from a cost ledger into a per-request cost timeline.

v2.0.1 is a narrow corrective patch to the v2.0.0 migration set: both migrations now skip tables and columns that already exist, fixing "relation already exists" failures when Spectra uses a dedicated spectra.storage.connection. The root cause is worth registering as an environmental fact rather than a footnote — migrate:fresh only drops tables on the default connection, so with a dedicated storage connection the Spectra tables survive a fresh reset while the migration rows are cleared and the migrations show as pending. That surfaces in CI, ephemeral review environments, and local dev resets, i.e. exactly the places where nobody is watching a cost dashboard. The patch makes the migrations idempotent; it does not change the storage topology or add a drop path for the secondary connection.

Technical risk. The risks are concentrated in data continuity and alerting semantics, not in install mechanics:

  • Cost discontinuity (highest impact). Several fixes materially raise reported cost: Anthropic cache reads/writes were underbilled (writes never billed at all), Gemini thinking/tool-use and xAI reasoning tokens were free, and provider-reported tiers now override request tiers. Reported spend will step up at the upgrade boundary. If historical rows are not repriced, trend lines, unit economics and any budget baselines built on 1.x are not comparable to post-upgrade data.
  • Backfill gap. Streaming calls in 1.x produced empty bodies and zero-token rows. Any pre-upgrade streaming traffic is understated, possibly to near-zero.
  • Alert behavior inversion. Budget alerts previously fired on every PHP-FPM request after threshold and never in long-running workers; they now fire once per period using the cache. This depends entirely on a shared, persistent cache store — an array or per-node file cache would produce either duplicate alerts or none. It also changes the response to a breach from "noisy" to "one signal," which may leave on-call without escalation unless something downstream consumes it.
  • Silent failure reporting. Save failures (e.g. duplicate daily-stat rows under load) now report instead of throwing into the app. Correct for availability, but it means tracking data can be dropped without anyone noticing unless the reporting channel is wired to alerting.
  • Scoped service binding. Spectra is now a scoped service. This fixes real cross-request leakage (global tags, trackable, tier, metadata bleeding across queued jobs and Octane), but any in-house code that resolved Spectra and held state across requests will change behavior — usually for the better, occasionally confusingly.
  • Migration idempotency (new in 2.0.1). The skip-if-exists behavior removes a hard failure but converts it into a softer one: a partially applied migration, or a column that exists with a different definition than the package expects, will now be silently accepted rather than corrected. Idempotent is not the same as convergent. On the default connection this is low risk (you will have reviewed the migrations); on a dedicated connection that has drifted, it is a real "the schema is not what the package thinks it is" exposure.
  • Framework floor. Laravel 11 is dropped, so this upgrade may force a framework upgrade first, with its own blast radius.

Key questions.

  1. Is there a supported reprice/backfill for historical rows, or must we annotate the discontinuity ourselves?
  2. What is the migration size and locking profile on our tracked-request table at current row counts and growth rate?
  3. Which cache store will back budget-alert dedupe in each environment, and what consumes an alert once it fires?
  4. Where do "reported failures" go — a log channel, an event, a health endpoint? Can we alert on them?
  5. Does provider-reported cost reconcile to catalog price, and which one wins in the dashboard and in budgets?
  6. How is the pricing catalog versioned — can we reproduce the cost of a March request after an October catalog update?
  7. Do we have custom code reading Spectra tables directly, or resolving the service outside request scope?
  8. Do we actually use a dedicated spectra.storage.connection, and if so what drops those tables today — our reset scripts, or nothing?
  9. After the 2.0.1 skip-if-exists behavior, how do we verify in staging that the Spectra schema matches what the package expects, rather than merely "migrations ran without erroring"?

Integration Approach

Stack fit. Requires Laravel 12 or 13 and PHP 8.2–8.5; tests run on Pest 3, 4 or 5. That is a modern, supported baseline and a reasonable place for a package that touches framework internals. Provider coverage is broad and current (Claude 5.x, GPT-6/GPT-5.6, Gemini 3.8/4, Grok 4.5–4.7, Replicate), and retired models are retained and marked — important for historical reporting. Per-catalog currency with exchange rates and regional surcharges make this viable for multi-region billing, which is usually the point at which a homegrown cost table stops being maintainable. Pin to ^2.0.1 rather than 2.0.0; the fix is small but the failure it prevents is a blocked migration on a non-default connection, which is a bad thing to discover during a scheduled change window.

Migration path. Treat this as a schema-and-semantics migration, not a version bump:

  1. Land the Laravel 12/13 upgrade as its own PR with the package still on 1.x, so framework and package regressions are separable.
  2. Upgrade the package on a branch at 2.0.1 or later, publish and review the migrations (new columns plus daily-stat totals) before running them anywhere shared; rehearse against a production-sized snapshot.
  3. Establish the connection topology up front: default connection or dedicated spectra.storage.connection. If dedicated, fix the reset path in CI and staging explicitly (drop the Spectra tables in teardown, or accept idempotent re-application), and add a one-time schema assertion so "skipped because it existed" is distinguishable from "skipped because it was already correct."
  4. Run in staging against mirrored traffic or replayed fixtures, then diff cost reports 1.x vs 2.x per provider and per model. Every delta should be explainable by a named fix in the release notes.
  5. Decide and document the historical-data stance: backfill, reprice, or annotate the boundary in the dashboard.
  6. Re-baseline budgets and thresholds after the cost step-change is quantified, not before.

Compatibility. Check for: custom code resolving Spectra and holding it across requests or jobs; dashboards/queries touching the tracked-request table that assume the old column set; morph-map configurations (trackables now resolve by morph alias, which fixes budgets and per-user usage in apps using a morph map — but changes what existing rows resolve to); scheduled prune jobs that need the new --stats-days flag and chunked media deletion; any CI pinned to Pest 2 or Laravel 11; and any pipeline that runs migrate:fresh against a database carrying a dedicated Spectra connection, which prior to 2.0.1 would have left orphaned tables and a failing migration.

Sequencing. Framework upgrade → package upgrade (2.0.1+) + migrations on staging → cost reconciliation → historical-data decision → budget re-baseline and alert routing → trace propagation enablement (trace_per_request, use_traceparent) → dashboard rollout to stakeholders → prune schedule tightened. Trace propagation should come after cost validation, because correlating spans is only useful once the numbers under them are trustworthy.

Operational Impact

Maintenance. Shipping twelve maintained pricing catalogs is the package's core ongoing value and its core ongoing dependency: model pricing changes monthly, and a lagging catalog silently misprices spend. Assign explicit ownership of "pricing freshness" — a monthly check that current models resolve and cost correctly — rather than assuming it is free. New pricing dimensions (date-effective since prices, long-context thresholds, audio/image token rates, megapixel/page/request units, aliases, exchange rates) add configurability that someone must own when rates or surcharges change. Add one durable item to the runbook: the reset/teardown procedure for the Spectra storage connection, now that it is a known sharp edge rather than an incident-in-waiting.

Support. Expect two support surfaces. Engineering owns schema, cache, and instrumentation. Finance/ops owns the definition of "cost" — catalog price versus provider-reported cost, currency conversion, and which tier applies. Write that definition down before the dashboard is widely shared; the new request detail page (input uncached/cache-read/cache-write split, output answer/reasoning split, error details) will invite line-item questions from budget holders, and the Trace card will invite questions about why one user action cost what it did. That is a feature, but only if someone can answer them. A third, thinner surface now exists around migration/reset behavior; keep it inside engineering and out of the finance conversation.

Scaling. Row-per-AI-call plus daily aggregates grows with traffic; chunked prune with media deletion and --stats-days is the right control, but the prune schedule must be set deliberately rather than inherited. Trace ids, parent_span_id, conversation_id and laravel_request_id add index surface — validate query plans on the dashboard's aggregate queries at realistic row counts. Budget-alert dedupe adds a cache dependency on the hot path; verify behavior with the production cache driver, not the test driver. A dedicated storage connection isolates Spectra's write volume from the app's primary — useful at scale, but it also means Spectra's tables are outside the blast radius of our standard reset and maintenance tooling, which is a deliberate trade to document rather than a detail to rediscover.

Failure modes.

  • Quiet data loss: tracking save failures no longer throw. Without alerting on the reported failures, you get a dashboard that looks healthy while under-reporting spend.
  • Alert silence: cache outage or a non-shared cache store means budget alerts fire never or everywhere. Neither is acceptable for a financial guardrail; add an independent check that alerts fired when expected.
  • Misattribution: a broken or absent morph map, or code bypassing the scoped service, produces spend attributed to the wrong user or tenant — worse than no attribution, because it drives wrong decisions.
  • Stream accounting gaps: streaming is now tracked as the app reads, including early termination and in-stream error events. Partial reads and provider-specific stream shapes (SSE, NDJSON, streamed JSON arrays) are the residual edge; spot-check a sample per provider after rollout.
  • Cost surprise: budgets tuned under 1.x underbilling will trip immediately post-upgrade, and thresholds set to compensate will then be too loose once pricing is correct.
  • Silent schema drift: with idempotent migrations, a Spectra table or column that exists but is wrong — stale definition, partially applied prior run, manual hotfix — is skipped rather than reconciled. The symptom is not a failed deploy but a query or aggregate that quietly misreports. This is the tradeoff 2.0.1 buys, and it needs a compensating check (schema assertion in staging, or a periodic comparison against a fresh install) rather than trust.

Ramp-up. Engineering: roughly one sprint for upgrade, migration rehearsal, reconciliation and alert wiring, more if the Laravel 11 → 12/13 jump is bundled. Add a small, bounded increment for the storage-connection path — verifying reset behavior and wiring a schema check — which is cheap now and expensive to retrofit after an incident. Finance/ops: a short briefing plus a written cost-definition note; the step-change in reported spend must be communicated before the first post-upgrade report circulates, or it will read as a regression caused by the upgrade rather than a correction of prior underbilling. Net position: 2.0.1 does not change the shape of the v2 decision — it removes a concrete install-blocker for teams using a dedicated storage connection and, in doing so, shifts a hard failure into a soft one that requires a verification step. The release line remains a substantial correctness upgrade that makes Spectra defensible as a financial system of record, but it is a breaking release on three axes at once (framework floor, schema, billing semantics), so it should be scheduled and communicated as a data-migration event, not a routine dependency bump.

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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel