zlodes / prometheus-client
The Prometheus Metrics client for PHP
Installs: 13 309
Dependents: 1
Suggesters: 0
Security: 0
Stars: 13
Watchers: 2
Forks: 1
Open Issues: 0
Requires
- php: ^8.1
- psr/log: ^1.0 || ^2.0 || ^3.0
- webmozart/assert: ^1.11
Requires (Dev)
- ergebnis/composer-normalize: dev-main
- infection/infection: ^0.27.0
- mockery/mockery: ^1.5
- phpcompatibility/php-compatibility: ^9.3
- phpmd/phpmd: ^2.13
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- phpstan/phpstan-webmozart-assert: ^1.2
- phpunit/phpunit: ^10.0
- roave/security-advisories: dev-latest
- slevomat/coding-standard: ^8.11
- squizlabs/php_codesniffer: ^3.7
- vimeo/psalm: ^5.0
README
This package provides you an ability to collect and export Prometheus metrics from any modern PHP application.
Why?
- Until now, there was no working Prometheus client for modern PHP
- Framework-agnostic
- Almost zero dependencies
- Won't break your business logic even if something is wrong with Metrics Storage
- Ready to use with static analysis tools (PHPStan, Psalm)
Adapters
- For Laravel: zlodes/prometheus-client-laravel
Installation
composer require zlodes/prometheus-client
Flow
TL;DR: Read Simple example.
1. Preparation
- Set up a storage to store metrics. There are four interfaces can be implemented:
- Set up a Registry to register your metrics. ArrayRegistry is a default implementation.
- Register your metrics using the Registry from step 2.
2. Collecting
- Get a collector for your metric from a CollectorFactory
- Call metric update method (e.g.
increment
on CounterCollector)
3. Exporting
- Create a controller to export metrics. Your controller should use Exporter. FetcherExporter is a default implementation.
- Set up a Prometheus to scrape metrics from your application using the controller from step 1.
Simple example
<?php use Psr\Log\NullLogger; use Zlodes\PrometheusClient\Collector\CollectorFactory; use Zlodes\PrometheusClient\Exporter\FetcherExporter; use Zlodes\PrometheusClient\Metric\Counter; use Zlodes\PrometheusClient\Metric\Gauge; use Zlodes\PrometheusClient\Metric\Histogram; use Zlodes\PrometheusClient\Registry\ArrayRegistry; use Zlodes\PrometheusClient\Storage\InMemoryStorage; $registry = new ArrayRegistry(); $counterStorage = new InMemoryCounterStorage(); $gaugeStorage = new InMemoryGaugeStorage(); $histogramStorage = new InMemoryHistogramStorage(); $summaryStorage = new InMemorySummaryStorage(); // Register your metrics $registry ->registerMetric( new Gauge('body_temperature', 'Body temperature in Celsius') ) ->registerMetric( new Counter('steps', 'Steps count') ) ->registerMetric( (new Histogram('http_request_duration_seconds', 'HTTP Request duration')) ->withBuckets([0.1, 0.5, 1]), ) ->registerMetric( (new Summary('memory_used', 'Used memory in bytes')) ->withQuantiles([0.5, 0.9, 0.99]) ); // Create a Collector factory $collectorFactory = new CollectorFactory( $registry, $counterStorage, $gaugeStorage, $histogramStorage, $summaryStorage, new NullLogger(), ); // Collect metrics $bodyTemperatureGauge = $collectorFactory->gauge('body_temperature'); $bodyTemperatureGauge ->withLabels(['source' => 'armpit']) ->update(36.6); $bodyTemperatureGauge ->withLabels(['source' => 'ass']) ->update(37.2); $collectorFactory ->counter('steps') ->increment(); $requestTimer = $collectorFactory ->histogram('http_request_duration_seconds') ->startTimer(); usleep(50_000); $requestTimer->stop(); $collectorFactory ->summary('memory_used') ->update(100); $collectorFactory ->summary('memory_used') ->update(200); // Export metrics $fetcher = new StoredMetricsFetcher( $registry, $counterStorage, $gaugeStorage, $histogramStorage, $summaryStorage, ); $exporter = new FetcherExporter($fetcher); foreach ($exporter->export() as $metricOutput) { echo $metricOutput . "\n\n"; }
Output example:
# HELP steps Steps count
# TYPE steps counter
steps 1
# HELP body_temperature Body temperature in Celsius
# TYPE body_temperature gauge
body_temperature{source="armpit"} 36.6
body_temperature{source="ass"} 37.2
# HELP http_request_duration_seconds HTTP Request duration
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds{le="0.1"} 1
http_request_duration_seconds{le="0.5"} 1
http_request_duration_seconds{le="1"} 1
http_request_duration_seconds{le="+Inf"} 1
http_request_duration_seconds_sum 0.050071506
http_request_duration_seconds_count 1
# HELP memory_used Used memory in bytes
# TYPE memory_used summary
memory_used{quantile="0.5"} 150
memory_used{quantile="0.9"} 190
memory_used{quantile="0.99"} 199
memory_used_sum 300
memory_used_count 2
Testing
Run tests
php ./vendor/bin/phpunit
Creating your own Storage
Keys serialization
There is a Serializer interface (with JSON-based implementation) to simplify work with a key-value storage.
Example can be found in InMemoryStorage.
Storage Testing
There are four useful traits to simplify your storage testing:
They provide you a set of tests to check your storage implementation to be compatible with the library.
Example:
<?php use PHPUnit\Framework\TestCase; use Zlodes\PrometheusClient\Storage\Contracts\CounterStorage; use Zlodes\PrometheusClient\Storage\InMemory\InMemoryCounterStorage; use Zlodes\PrometheusClient\Storage\Testing\CounterStorageTesting; class InMemoryCounterStorageTest extends TestCase { use CounterStorageTesting; private function createStorage(): CounterStorage { return new InMemoryCounterStorage(); } }