ripcord / laravel
Ship Laravel errors and deploy events to Ripcord — no application code, one config block.
Requires
- php: ^8.0
- illuminate/http: ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-03 15:59:09 UTC
README
Ship Laravel errors and deploy events to Ripcord (AI Change Intelligence
Platform) — no application code, one config block. Ripcord can't read your
storage/logs from outside; this package pushes what matters out to it.
Install
composer require ripcord/laravel
php artisan vendor:publish --tag=ripcord-config # optional
.env:
RIPCORD_URL=https://ripcord.internal RIPCORD_PROJECT_ID=4 RIPCORD_INGEST_TOKEN=<same as RIPCORD_INGEST_TOKEN on the Ripcord server> # optional RIPCORD_ENABLED=true RIPCORD_LOG_LEVEL=error # min PSR-3 level that becomes an event RIPCORD_ENVIRONMENTS=production,staging RIPCORD_DEDUPE_SECONDS=60 RIPCORD_ALLOW_INSECURE=false # allow a plain-http RIPCORD_URL (loopback is always allowed)
That's it. Every Log::error() / unhandled exception (via Laravel's exception
handler → MessageLogged) is sent to Ripcord as a runtime event, attached to
the most recent analyzed change for the project, and appears on that change's
Timeline tab.
Deploy event
Add to the end of your deploy pipeline (any CI):
php artisan ripcord:deployed --title="v3.1.0 → production" --sha="$CI_COMMIT_SHORT_SHA" # --change-id=77 to attach to a specific change instead of the latest
How it works
| Capture | listens on Illuminate\Log\Events\MessageLogged — fires for every channel, so no logging.php edit |
| Filter | level ≥ RIPCORD_LOG_LEVEL, environment in RIPCORD_ENVIRONMENTS, de-duped per worker |
| Send | fire-and-forget POST {url}/v1/projects/{id}/events with X-Ripcord-Token; 1s connect / 2s timeout; on HTTP requests it flushes in terminating() so it never blocks the response |
| Safety | every failure is swallowed — a down or misconfigured Ripcord never breaks a request; a re-entrancy guard stops a failed POST from logging itself into a loop |
Severity mapping: error/critical/alert/emergency → critical,
warning/notice → warning, else info.
Security & limits
- Transport. Log messages are sent verbatim, so a non-
https://RIPCORD_URLis refused (config returns "not configured") unless the host is loopback orRIPCORD_ALLOW_INSECURE=true. Keep itfalsein production. - What leaves the app. The event
titleis the raw log message (truncated to 250 chars).metadatacarries onlylevel, exception class +file:line, and the scalar context keysmethod,user_id,request_id, plusurlwith its query string stripped. Nothing else from the log context is sent. UseRIPCORD_LOG_LEVELto keep low-value / chatty messages out entirely. - Flood control. One request or job queues at most 25 events; a worker sends at most 60 per rolling 60 s. Excess is dropped silently — the package can never turn a logging storm into a storm of blocking HTTP calls.
- Memory. The per-worker dedupe table is capped at 500 keys and pruned by age; a wedged in-flight flag self-heals after 5 s (matters only under Octane).
- No inbound surface. The package only makes outbound POSTs. It never
registers a route, command input is cast (
--change-idto int), and theproject_idis cast to int when building the URL.
Not this package's job
Active health probing / synthetic checks. This only ships events the app already produces.