php artisan boost:add-skill talaria/laravel
Save this content to: .cursor/rules/transport.mdc
# Transport & queue
## Wire contract
Events:
- `POST {url}/v1/events`
- Header: `Authorization: Bearer <tal_sk_ key>`
- Body (plain JSON, no `input` wrapper):
```json
{ "events": [ { "message": "..." } ] }
```
Spans (when tracing is enabled):
- `POST {url}/v1/spans`
- Same Bearer header
- Body: `{ "spans": [ { ... } ] }`
- `SpanTransport` constructs its **own** Guzzle client. Do not install `GuzzleMiddleware` on ingest transports.
Analytics (server-side; no autocapture, no cookie jar):
- `POST {url}/v1/analytics`
- Body: `{ "events": [ { ... } ] }`
- `AnalyticsTransport` constructs its **own** Guzzle client.
- `track` requires `userId` and/or `anonymousId` (browser ids forwarded by the caller)
- Core `enableAnalytics` defaults true; when false the facade no-ops. Silverstripe YAML / `TALARIA_ENABLE_ANALYTICS` defaults off.
- Even a single leftover event, span, or analytics item is a batch of one
- `extra` → `extraJson` (JSON **string**); `tags` are string→string
- Flat `userId` / `url` — not nested `user` / `request`
- First-class `exception` (`ExceptionDataDto` / frames with `functionName`) — never put `exception_class` / `file` / `line` / `code` in `extra`
- `platform: "php"` on all PHP captures (exceptions and messages); keep raw `stackTrace` string alongside structured frames
## EventQueue drain triggers
| Trigger | Config | When |
| ------- | ------ | ---- |
| Size | `maxBatchSize` (default 50) | Buffer reaches N |
| Age | `flushIntervalMs` (default 2000) | Checked on each enqueue |
| Explicit | `flush()` / `close()` | Always drain |
| Shutdown | `register_shutdown_function` | Drain remainder |
PHP FPM has no background timer — age is checked on enqueue, not via a wall-clock thread.
## Reliability
- Short HTTP timeout (2–3s)
- No unbounded retries; on 429 log warning and drop/backoff once
- Transport failures must not crash the host app. Queues catch every `\Throwable` from a transport; `checkIn`, `reportClient`, `flush` and flag loads swallow and log. Transport log lines go through `FailSafe::logRateLimited` (one per signal per minute)
- Call `fastcgi_finish_request()` when available before shutdown network I/O
- On ingest `retry: false` (or known permanent class names when `retry` is absent): drop the batch, log once, and disable events **and** spans **and** analytics for the rest of this PHP process. Message contains `lacks required scope` disables **that signal only**. Quota / rate-limit (`retry: true`) and 5xx must **not** disable. FPM workers reuse the singleton — a new worker after deploy picks up a rotated key.
Events:
POST {url}/v1/eventsAuthorization: Bearer <tal_sk_ key>input wrapper):{ "events": [ { "message": "..." } ] }
Spans (when tracing is enabled):
POST {url}/v1/spans{ "spans": [ { ... } ] }SpanTransport constructs its own Guzzle client. Do not install GuzzleMiddleware on ingest transports.Analytics (server-side; no autocapture, no cookie jar):
POST {url}/v1/analytics
Body: { "events": [ { ... } ] }
AnalyticsTransport constructs its own Guzzle client.
track requires userId and/or anonymousId (browser ids forwarded by the caller)
Core enableAnalytics defaults true; when false the facade no-ops. Silverstripe YAML / TALARIA_ENABLE_ANALYTICS defaults off.
Even a single leftover event, span, or analytics item is a batch of one
extra → extraJson (JSON string); tags are string→string
Flat userId / url — not nested user / request
First-class exception (ExceptionDataDto / frames with functionName) — never put exception_class / file / line / code in extra
platform: "php" on all PHP captures (exceptions and messages); keep raw stackTrace string alongside structured frames
| Trigger | Config | When |
|---|---|---|
| Size | maxBatchSize (default 50) |
Buffer reaches N |
| Age | flushIntervalMs (default 2000) |
Checked on each enqueue |
| Explicit | flush() / close() |
Always drain |
| Shutdown | register_shutdown_function |
Drain remainder |
PHP FPM has no background timer — age is checked on enqueue, not via a wall-clock thread.
\Throwable from a transport; checkIn, reportClient, flush and flag loads swallow and log. Transport log lines go through FailSafe::logRateLimited (one per signal per minute)fastcgi_finish_request() when available before shutdown network I/Oretry: false (or known permanent class names when retry is absent): drop the batch, log once, and disable events and spans and analytics for the rest of this PHP process. Message contains lacks required scope disables that signal only. Quota / rate-limit (retry: true) and 5xx must not disable. FPM workers reuse the singleton — a new worker after deploy picks up a rotated key.How can I help you explore Laravel packages today?