openconext/monitor-bundle
OpenConext Monitor Bundle adds health and status monitoring endpoints to Symfony services, exposing service metadata, availability checks, and diagnostic details for operations dashboards and uptime monitoring.
Reality check first: openconext/monitor-bundle (now at 4.3.1) is a Symfony bundle, not a Laravel package. If you're on Laravel, there is no service provider to register — you either (a) run it in a Symfony service and scrape its HTTP endpoint, or (b) port the ~200 lines of check-aggregation logic into a Laravel controller/health route. Budget an hour for (b) rather than fighting Composer autoloading.
On Symfony:
composer require openconext/monitor-bundle
OpenConext\MonitorBundle\MonitorBundle in config/bundles.php./monitor) — confirm the resulting paths with bin/console debug:router | grep -i monitor rather than trusting docs, since paths have shifted across versions.First real use case: expose the health route to your load balancer / uptime monitor so a failing database or IdP connection pulls the node out of rotation, rather than serving 500s to users.
Where to look first if something's off:
bin/console debug:container --tag=monitor.check — is your check actually registered?bin/console debug:router — is the route where you think it is?DependencyInjection/ config to see the default tag name and any env-driven toggles.Custom checks as tagged services. Implement the bundle's check interface (name + health status) on a small service and tag it monitor.check. Keep each check to a single dependency — one for the DB, one for Redis, one for each critical third-party API. Per-check granularity is the whole point; a monolithic "is everything fine?" check gives you a red light with no diagnosis.
Split liveness from readiness. Point Kubernetes livenessProbe at a trivial always-200 route and readinessProbe at the full monitor endpoint. Otherwise a slow downstream dependency causes the kubelet to restart a perfectly healthy PHP process — the classic outage-amplification failure.
Non-critical metadata goes in the info/status payload, not into failing checks. Build commit SHA, deploy timestamp, feature-flag state, and dependency versions into a check that always reports healthy. Ops gets diagnostic context without ever flapping the endpoint.
Wrap checks in a thin decorator with a timeout and a short cache. Probes fire every few seconds; without a 5–10s result cache you'll hammer the same downstream API from every pod simultaneously. Cache the boolean, not the exception.
CI / post-deploy verification:
curl -fsS https://app.example.com/monitor/health | jq -e '.checks | to_entries[] | select(.value.healthy == false) | .key'
Gate the deploy on this in your release pipeline — it catches "app boots but can't reach the queue" far earlier than a synthetic user monitor.
Environment-scoped checks. Register external-dependency checks only in staging/production via the service definition's %kernel.environment% condition, so local dev doesn't require a VPN to get a green light.
Alert routing by check name. Since results are keyed per check, map check name → on-call rotation in your monitoring tool. db pages instantly; cache opens a ticket.
4.3.1 changed failure semantics — read your dashboards accordingly. Instantiation errors on a check (missing constructor argument, un-autowirable dependency, container misconfiguration) are now caught and surfaced as a failing check instead of exploding the endpoint. Two consequences: a misconfigured check now looks like a dependency outage in your alerting, and because the exception is swallowed you may no longer see a loud stack trace in your error log. When the endpoint goes red after a deploy, read the response body and check whether the failure is an outage or a wiring bug before paging anyone. If you have log-based alerts keyed on the previous fatal, they'll go quiet — replace them.
This fix is a strict improvement over 4.3.0 and safe to take: previously one bad check definition could 500 the entire health endpoint, which is precisely when you least want your monitoring blind. Pin ^4.3.1.
Don't let a check do work. Checks must be fast, read-only, idempotent, and side-effect free. No cache warmups, no migrations, no queue dispatch, no writes to prove the DB is up — a health endpoint that writes is a DoS vector pointed at yourself.
Set explicit timeouts on every outbound call inside a check. PHP's default cURL/socket timeout is effectively unbounded; one hung dependency turns your readiness probe into a 30-second hang and the orchestrator kills the pod mid-request.
Version and build info is reconnaissance. The info payload typically exposes framework versions, commit SHAs, and sometimes service hostnames. Restrict the route at the ingress or firewall to your monitoring network — never leave it open to the internet.
Watch for HTTP caching layers. Reverse proxies and CDNs will happily cache a 200 and keep serving it after the app dies. Send Cache-Control: no-store on health responses, or exempt the path from the proxy cache.
Check autoconfigure is on for the directory holding your checks (services.yaml → _defaults: autoconfigure: true). A missing tag produces a silently empty check list and a permanently green endpoint — the worst possible monitoring outcome. Assert at least one check is registered in a smoke test.
Extension points: the check interface itself, the tag name, and the routing import are the stable seams. Subclassing the controller is fragile across minor versions — if you need custom output shape, register your own route and compose the bundle's check aggregation instead of overriding its controller.
How can I help you explore Laravel packages today?