PHP
Collect PHP HTTP request metrics — rate, errors by status class, and latency — and get curated dashboards and alerts for them with a single import.
PHP uses the Prometheus path, not the OpenTelemetry SDK. OpenTelemetry PHP’s
auto-instrumentation emits traces only; there are no automatic OpenTelemetry metrics. The
mature way to get PHP request metrics is Prometheus: instrument the app with a
Prometheus client (this demand targets Symfony’s
artprima/prometheus-metrics-bundle)
to expose a /metrics endpoint, and have an OpenTelemetry Collector scrape it
with the Prometheus receiver and forward OTLP to your LeanSignal agent gateway
(one per cluster or environment). The gateway keeps full fidelity locally and
forwards only the demanded subset to your central dataplane — no traces involved.
The demands below are built against the bundle’s default symfony_* metric names
(symfony_http_requests_total, symfony_http_{2xx,4xx,5xx}_responses_total,
symfony_http_requests_duration_seconds). If you instrument with a Laravel
exporter or a custom promphp setup instead, adjust the imported demand’s
queries to match your metric names.
Prerequisites
Section titled “Prerequisites”- A LeanSignal agent gateway deployed and connected — one per cluster or
environment. If you haven’t deployed it yet, follow
Install the agent (source:
LeanSignal/leansignal-agent). It should show as Connected under Agents in the LeanSignal app. - Network reachability to the gateway’s OTLP port —
4317(gRPC) or4318(HTTP). See Agent configuration. - Your PHP app exposing Prometheus metrics, plus an OpenTelemetry Collector that scrapes them and forwards OTLP to the gateway — both configured in Setup.
- Editor or admin role in the LeanSignal app (importing a demand creates dashboards and alert rules).
1. Instrument your app with Prometheus. For Symfony, install the bundle:
composer require artprima/prometheus-metrics-bundleRegister it and expose a metrics endpoint (see the bundle’s README for the route and storage adapter — Redis or APCu is recommended for PHP-FPM, since each worker is a separate process):
app_metrics: path: /metrics controller: Artprima\PrometheusMetricsBundle\Controller\MetricsController::prometheusThis publishes symfony_http_requests_total,
symfony_http_{2xx,4xx,5xx}_responses_total, and
symfony_http_requests_duration_seconds at /metrics.
2. Scrape it with an OpenTelemetry Collector and forward OTLP to your gateway (not a SaaS endpoint):
receivers: prometheus: config: scrape_configs: - job_name: php-app # becomes the service_name / job label scrape_interval: 15s static_configs: - targets: [my-php-app:80] # host:port exposing /metrics metrics_path: /metrics
processors: batch: {}
exporters: otlp: endpoint: leansignal-agent:4317 # per-cluster gateway (use :4318 for HTTP) tls: insecure: true # in-cluster plaintext; provide ca_file for TLS
service: pipelines: metrics: receivers: [prometheus] processors: [batch] exporters: [otlp]In Kubernetes, use the Prometheus receiver’s kubernetes_sd_configs (or a
PodMonitor) instead of static targets.
Logs and traces
Section titled “Logs and traces”Tracing is where OpenTelemetry PHP shines — install the opentelemetry PECL
extension and the auto-instrumentation packages for your framework, point
OTEL_EXPORTER_OTLP_ENDPOINT at the gateway, and spans flow with no code
changes. (This is independent of the Prometheus metrics path above.) For logs,
add the OpenTelemetry Monolog handler — or keep writing files and ship them
with a collector or shipper. See the
PHP OpenTelemetry docs.
Demands
Section titled “Demands”PHP ships as a ready-made demand in three variants. You don’t copy any JSON — in the LeanSignal app go to Demands, press the ˅ arrow on the Add Demand button (the arrow opens the import menu), choose Import from catalog…, and pick the variant. Each variant below lists the slug that identifies its published bundle. See Integrations for the full import flow.
The variants are nested — Standard is a superset of Essential, Extended a superset of Standard. Pick whichever is closest to what you need and treat it as a starting point: after import everything is a normal, editable copy, so retune thresholds, add or drop panels, and adjust queries for your environment — your edits reshape the demand automatically. Start small and re-import a larger variant later if you outgrow it.
The golden signals. 1 dashboard · 4 panels · 3 alerts — traffic, success and error rates, and latency at a glance.
Import this variant from the catalog. Its demand slug:
php-otel-demand-essentialDashboard — Request rate, Successful (2xx) rate, 5xx error rate, and Request latency p95.
Alerts (3)
| Alert | Severity | Fires when |
|---|---|---|
| High HTTP 5xx error rate | critical | 5xx ratio > 5% for 5m |
| High request latency (p95) | warning | p95 latency > 1s for 5m |
| No inbound traffic | warning | no requests for 15m |
Well-rounded coverage. 1 dashboard · 8 panels · 5 alerts — adds per-action traffic and latency percentiles. The recommended default.
Import this variant from the catalog. Its demand slug:
php-otel-demand-standardDashboard — everything in Essential, plus Request rate by action, 4xx error rate, Request latency p50, and Request latency (average).
Alerts (5)
| Alert | Severity | Fires when |
|---|---|---|
| High HTTP 5xx error rate | critical | 5xx ratio > 5% for 5m |
| High request latency (p95) | warning | p95 latency > 1s for 5m |
| No inbound traffic | warning | no requests for 15m |
| Critical HTTP 5xx error rate | critical | 5xx ratio > 20% for 5m |
| High request latency (p99) | warning | p99 latency > 2.5s for 10m |
Deep request visibility. 1 dashboard · 12 panels · 7 alerts — status-class breakdowns and per-action latency for apps you need to diagnose, not just watch.
Import this variant from the catalog. Its demand slug:
php-otel-demand-extendedDashboard — everything in Standard, plus Responses by status class, 5xx by action, Request latency p99, and Latency p95 by action.
Alerts (7)
| Alert | Severity | Fires when |
|---|---|---|
| High HTTP 5xx error rate | critical | 5xx ratio > 5% for 5m |
| High request latency (p95) | warning | p95 latency > 1s for 5m |
| No inbound traffic | warning | no requests for 15m |
| Critical HTTP 5xx error rate | critical | 5xx ratio > 20% for 5m |
| High request latency (p99) | warning | p99 latency > 2.5s for 10m |
| Elevated 4xx client error rate | warning | 4xx ratio > 30% for 10m |
| Slow action (p95) | warning | an action p95 > 2s for 10m |
Dashboards
Section titled “Dashboards”Each variant imports one PHP dashboard, its panels grouped into
collapsible sections. Every dashboard carries an Instance filter (on the
instance label), so one import covers the whole fleet — view every instance
at once, or focus on one. Legends are sortable tables showing last/mean/max per
series, so the outlier instance stands out. Dashboards are demand-driven:
importing one tells your agents to forward exactly the timeseries its panels
query, and nothing else. Panels are ordinary Perses panels — edit queries, add
panels, or retune them after import, and your changes reshape the demand
automatically.
Alerts
Section titled “Alerts”Thresholds are conservative starting points — tune them to your workload.
Next steps
Section titled “Next steps”- Demand-driven observability — why importing a demand also shapes what your agents collect.
- Agent configuration — the full agent config surface.
Thanks for your feedback!
Report sent — thank you!