ruudk/campfire-exception-bundle
A Symfony bundle that posts application exceptions to a Campfire chat room, so your team sees errors as they happen. It hooks into Symfony's exception handling to push formatted notifications with the message, file, and trace straight into the room you configure.
This bundle is a historical Symfony2 artifact: archived, one star, zero dependents, last release April 2014. The Campfire service it targets was already winding down (37signals stopped new signups in 2013 and eventually shut the product down), so treat it as a reference implementation for "post exceptions to a chat room" rather than something you deploy.
Minimal onboarding path if you're studying it:
DependencyInjection/RuudkCampfireExceptionExtension.php and the corresponding Resources/config/*.xml (or .yml). That tells you the config keys (typically account, token, room, and an enabled/debug toggle) and which service wires the listener.EventListener/ExceptionListener.php (or similar). It hooks kernel.exception and delegates to a Campfire API client. That class is the whole product.new Ruudk\CampfireExceptionBundle\RuudkCampfireExceptionBundle() to AppKernel::registerBundles().app/config/config.yml under ruudk_campfire_exception (account subdomain, API token, room ID).prod environment posts the exception class, message, and optionally trace to a Campfire room so the on-call dev sees it before users report it.Because there's no maintained API surface, expect to read the source over documentation. The README is thin and older than most of the bundle's own dependency tree.
Environment scoping (the intended pattern). Configure the bundle only in config_prod.yml — you do not want exception spam from dev or test. In Symfony2 terms:
# app/config/config_prod.yml
ruudk_campfire_exception:
account: "%campfire_account%"
token: "%campfire_token%"
room: 123456
Keep account/token in parameters.yml (or an environment variable) — never inline.
Pair with Monolog, don't replace it. Let Monolog handle durable logging and the bundle handle "loud" notification. A common pattern:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
The bundle then acts as the pager — noisy but immediate.
Filter before you notify. If the bundle's config does not already expose an ignore list, wrap or override the listener via a compiler pass rather than editing vendor code. Typical filters: Symfony\Component\HttpKernel\Exception\NotFoundHttpException, AccessDeniedHttpException, and 404s in general — these are noise, not incidents.
Custom formatting via service override. The listener typically builds a text payload; alias your own formatter service in services.yml to include Request::getUri(), the authenticated user, and the first trace line. This is the most useful extension point.
Rate/dedupe. In Symfony2 you would do this by decorating the Campfire transport with a small service that keeps a cache key on exception class + file:line and suppresses duplicates within N minutes.
Migration path (what you'd actually do today): replace the bundle with a Monolog handler that POSTs to a Slack/MS Teams/Matrix webhook — monolog/monolog SlackHandler plus a FingersCrossedHandler covers the same use case with maintained code.
composer.json requires symfony/symfony ~2.x. On Symfony 3+ you'll hit constraint errors; --ignore-platform-reqs gets you a broken runtime, not a working bundle. Don't try to bolt it into a modern app.kernel.exception listeners are fire-on-everything. Without filtering you will notify on 404s, CSRF failures, and validation-driven HttpExceptions. If you port this idea, filter first.kernel.exception listeners (e.g., security's) can mutate or replace the exception. Register the notifier with a low priority so it runs after Symfony has normalized the exception, and guard against null.app/console container:debug ruudk_campfire and check the bundle is in AppKernel. A silent no-op usually means the listener is tagged but enabled: false, or the config node isn't under the expected root key.HttpClient, JSON body) and you have a working "notify chat on exception" bundle without touching the Symfony wiring at all.How can I help you explore Laravel packages today?