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

Prometheus Client Php Laravel Package

promphp/prometheus_client_php

PHP Prometheus client library that uses Redis, Predis, APCu, or in-memory adapters for client-side aggregation. Register counters, gauges, histograms, and summaries, then expose metrics in Prometheus text format.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a framework-agnostic Prometheus client, not a Laravel package. It provides CollectorRegistry, four collector types (counter, gauge, histogram, summary), pluggable storage adapters (Redis, Predis, APC, APCng, InMemory, PDO), and a RenderTextFormat exposition renderer. There is no service provider, no config file, no middleware, no facades — all Laravel wiring is ours to write. That is roughly 150–250 lines of glue (provider + config + middleware + controller), which is acceptable but must be planned as first-party code we own, not "install and go."

The critical architectural fact is that PHP is share-nothing. Client-side aggregation means the registry state must live outside the request lifecycle. That forces a choice with real operational consequences:

  • Redis — correct default for a load-balanced, multi-instance Laravel deployment. One scrape endpoint can see aggregate state for the whole fleet, and it is the only adapter that behaves sanely under Octane and across FPM pools.
  • APCu / APCng — per-node, per-process-pool state. Prometheus must scrape every instance directly, and behind a round-robin load balancer a scrape may hit a worker that never served traffic, producing incoherent counters. Viable only on single-instance or per-node-scrape architectures.
  • InMemory — useless for web requests (state dies with the request); only valid for long-running scripts.
  • PDO — reuses our existing MySQL/Postgres, but adds a write amplification path on every instrumented request against the OLTP database. High risk for the primary DB.

Integration feasibility. Straightforward technically: composer require promphp/prometheus_client_php, register the registry as a singleton, expose a route that renders $registry->getMetricFamilySamples(). The friction points are specific and worth flagging up front:

  1. The package opens its own Redis connection. It does not accept Laravel's Redis manager connection. With phpredis we duplicate host/port/auth config and lose Laravel's connection pooling and failover semantics; the only clean injection path is Predis::fromExistingConnection() if we standardize on predis (non-default in Laravel). Plan for config duplication or an explicit switch to predis for the metrics client only.
  2. Prefix sharing. Redis::setPrefix() and Predis::setPrefix() share one namespace; two adapters with different prefixes in one app is explicitly unsupported. Multi-app Redis sharing requires disciplined, per-app prefixes.
  3. Push Gateway is removed as of v2.0.0 and lives in a separate package (promphp/prometheus_push_gateway_php). This matters: queue workers and cron jobs cannot be scraped, so job/batch metrics need either push-gateway support (second dependency) or a decision to not instrument workers at all.
  4. Text format only — no native OpenMetrics, no exemplars, no native tracing correlation.

Technical risk. Moderate. Ranked:

  • Metrics can break production requests. Collector calls throw on Redis errors. Every instrumentation point needs wrapping or a fail-open decorator, otherwise a Redis blip becomes a 500. This is the single most important non-obvious risk and must be an explicit acceptance decision.
  • Cardinality explosion. Histograms and summaries store label combinations as keys in Redis; per-tenant, per-URL, or per-user-ID labels will grow the keyspace unbounded and slow both writes and scrapes. Needs a naming/label standard and a review gate before any new metric ships.
  • Scrape cost. Each /metrics hit reads the entire metric family set from Redis. Scrape interval × metric count × instance count is real read load on the same instance we use for cache/session unless isolated.
  • Eviction and key loss. If the metrics Redis shares a cache instance with allkeys-lru, metric keys get evicted silently — counters reset, histograms skew, no error surfaces.
  • Maintainer concentration. Small maintainer set, 554 stars, Dependents: 0 in the supplied metadata (likely a registry artifact, but not verified). Bus-factor is a genuine consideration for a library sitting on the hot path of every request.

Key questions for the team.

  1. Is there an existing Prometheus/Grafana stack and scrape infrastructure, or does this package imply standing one up? If the latter, the client is the smallest part of the project.
  2. Do we run Octane, multiple app instances behind an LB, or a single FPM node? This decides Redis vs APCu and is non-negotiable.
  3. Will metrics share the cache/session Redis instance, or do we get a dedicated one? Answer must include maxmemory-policy explicitly.
  4. Which framework/domain metrics are actually required in phase 1 — HTTP RED metrics only, or queue/cron/business metrics too? If workers are in scope, budget the second package.
  5. Who owns the metric naming/label standard, and is there a review checkpoint for cardinality?
  6. Are we willing to accept metrics being best-effort (fail-open) rather than guaranteed?

Integration Approach

Stack fit. Composer-native, PSR-friendly, no framework coupling. PHP ^8.2 aligns with Laravel 11/12; if any service is still on Laravel 10 with PHP 8.1, this package pins the platform floor and forces an upgrade first — verify before committing.

Wiring. Four artifacts, all ours:

  • config/prometheus.php — namespace, adapter selection, Redis host/port/auth/timeout, storage prefix, enabled flag.
  • PrometheusServiceProvider — binds CollectorRegistry as a singleton with the chosen adapter; reads from the config, not hardcoded defaults.
  • MetricsController — single /metrics action, RenderTextFormat::MIME_TYPE, cached getMetricFamilySamples() per scrape. Must be excluded from web middleware (no session, no CSRF) and explicitly excluded from its own instrumentation to prevent recursion.
  • InstrumentHttpRequests middleware — histogram on request duration and counter on status, labelled by route (route name, never raw URI) and method. Terminate-based recording to avoid capturing post-response work.

Migration path. Deliverable in one sprint, non-breaking:

  1. Add the dependency and the service provider with a PROMETHEUS_ENABLED=false kill switch. Ship it inert.
  2. Provision/allocate the metrics Redis (database index or dedicated instance), set prefix, verify auth/ACL (v2.13 added two-argument ACL AUTH).
  3. Enable the HTTP middleware + scrape route in a single staging environment; confirm Prometheus scrapes and series are stable for a week.
  4. Only then add domain counters, then dashboards, then alerts.

Compatibility. Framework-agnostic, so no Laravel major-version coupling. Watch: PHP 8.2 floor; phpredis vs predis choice determines connection injection; APC/APCng require PECL extensions in the build image (an image change, not a Composer change); PDO adapter supports MySQL, PostgreSQL, SQLite if that path is ever chosen.

Sequencing. Dependency + kill switch → metrics backend provisioned → scrape endpoint live and scraped → HTTP metrics → domain metrics → alerting. Do not interleave with an Octane migration or a PHP version upgrade; both change the state model underneath the adapter choice.

Operational Impact

Maintenance. Low code churn required from us; the library evolves slowly (2.7 → 2.13 over multiple minor releases, mostly adapter internals and correctness fixes, no breaking changes since the 2.0 Push Gateway extraction). The ongoing cost is not the library — it's the metrics estate: dashboards, alerts, cardinality hygiene, and the Prometheus/Grafana infrastructure itself. Budget owner time for that, not for the dependency.

Support. Apache-2.0, public issue tracker, Slack channel, CI across the four adapters with black-box and performance test suites. Vendor support does not exist — this is community-maintained. For a hot-path dependency, plan an internal fork policy: we should be able to patch and pin if needed, and should pin to an exact minor version rather than a caret range on the request path.

Scaling. Cost model is per-request Redis commands: each observation is one or more round-trips (histogram observations more than counters). At high RPS this is a measurable p99 contribution — set the connection timeout low (default 0.1s, deliberately aggressive) and measure before enabling broadly. Scrape load scales with metric family count × instances × scrape frequency, all reads. Two scaling hedges: keep the metrics Redis separate so eviction and load isolation are decoupled from cache, and enforce a hard cap on distinct label combinations per metric. Note the 2.7 fixes for Redis write-locks on histogram/gauge updates and the APCng collection-lag removal — both were genuine concurrency defects, which is a reminder to stay current rather than pin old minors indefinitely.

Failure modes. Enumerate these in the runbook:

  • Redis unreachable or timing out → instrumentation throws → user-facing 500s unless fail-open wrapping is in place. Highest severity.
  • Metrics keys evicted by cache pressure → silent counter resets and skewed histograms; no signal in application logs, only in Grafana discontinuities.
  • Prefix collision between apps on a shared Redis → cross-contaminated series, extremely confusing to diagnose.
  • Label cardinality blowup → slow scrapes, scrape timeouts, memory pressure in the metrics backend. Degrades observability exactly when it's needed.
  • APCu adapter under multi-instance LB → inconsistent, per-worker series that look like flapping.
  • Queue workers and cron → invisible by default; team assumes they're covered when they aren't. Needs an explicit decision, not an omission.
  • Package abandonment → no security patches; mitigated by pinning plus an internal fork capability.

Ramp-up. One engineer, roughly 1–2 days for the provider/config/middleware/route with a working scrape, plus ~1 week to define a metric taxonomy, wire meaningful domain metrics, and validate dashboards. The PHP side is the easy half; the Prometheus/Grafana/alerting half is where timelines actually slip. If the observability stack doesn't already exist, treat this package as a 10% line item in a larger project and sequence it behind stack provisioning — otherwise the team builds a scrape endpoint nothing scrapes.

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