Install the Bundle
composer require chaseisabelle/phprom-bundle
For Symfony 4+ (Flex), this auto-enables the bundle. For older versions, manually add it to AppKernel.php.
Configure the Bundle
Create config/packages/phprom.yaml:
phprom:
namespace: "my_app" # Required
address: "127.0.0.1:3333" # Optional (defaults to 127.0.0.1:3333)
api: "grpc" # Optional (defaults to "grpc"; use "rest" for REST API)
First Use Case: Track a Route Add a metric to a controller:
use ChaseIsabelle\PHPromBundle\Metric\Counter;
class HomeController extends AbstractController
{
public function index(Counter $counter)
{
$counter->increment('homepage_views');
return $this->render('home/index.html.twig');
}
}
Verify Metrics
Check the phprom server UI (default port) to see your metrics under the configured namespace (e.g., my_app_homepage_views).
Metric Types Inject the appropriate metric class into controllers/services:
request_counts).
$counter->increment('api_requests');
active_users).
$gauge->set('active_users', $userCount);
response_times).
$histogram->observe('db_query_ms', $executionTime);
route_execution_time).
$timer->time('route_execution', function() {
// Code to measure
});
Route-Specific Metrics
Use the routes config to auto-track specific routes:
phprom:
namespace: "my_app"
routes:
enabled: true
patterns:
- ^/api/.*$
- ^/admin/.*
Metrics like route_counts and route_latencies are auto-generated.
Custom Metrics in Services Extend services with metrics:
class UserService
{
public function __construct(private Counter $counter) {}
public function createUser()
{
$this->counter->increment('users_created');
// ...
}
}
Middleware for Global Metrics Track metrics across all requests via middleware:
namespace App\Middleware;
use ChaseIsabelle\PHPromBundle\Metric\Counter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
class MetricsMiddleware
{
public function __invoke(RequestEvent $event, Counter $counter)
{
$counter->increment('all_requests');
}
}
Dependency Injection Prefer constructor injection for metrics to ensure they’re available where needed:
public function __construct(
private Counter $counter,
private Histogram $histogram
) {}
Labeling for Context Add labels to metrics for granularity:
$counter->increment('api_errors', ['endpoint' => 'users', 'status' => '404']);
Async Metric Flushing
Configure the bundle to flush metrics asynchronously (if supported by the underlying phprom-client):
phprom:
async_flush: true
Testing Mock metrics in tests to avoid hitting the real server:
$this->mock(Counter::class)->shouldReceive('increment');
Missing Namespace
Forgetting to set namespace in phprom.yaml will cause metrics to appear as empty strings in phprom.
gRPC Dependencies
grpc PHP extension is installed (pecl install grpc).grpc/php image or install the extension in your container.Failed to load gRPC extension → Verify extension=grpc.so is in php.ini.Metric Naming Collisions
Avoid duplicate metric names across services/controllers. Use unique prefixes (e.g., service_x_*).
REST API Fallback
If using api: "rest", ensure the phprom server’s REST endpoint is accessible. gRPC is faster but requires the extension.
Metric Cardinality Explosion
Over-labeling metrics (e.g., user_id in every metric) can bloat the phprom server. Use sparingly.
Check Connection Test connectivity to the phprom server:
curl http://127.0.0.1:3333/metrics # For REST API
Or use a gRPC client to verify the server is reachable.
Log Metric Sends
Enable debug logging in config/packages/dev/phprom.yaml:
phprom:
debug: true
Logs will appear in Symfony’s debug channel.
Verify Metric Names Use the phprom server’s UI to confirm metrics are being sent with the correct namespace and labels.
Custom Metric Types
Extend the bundle by creating your own metric classes (e.g., Summary for percentiles):
namespace App\Metric;
use ChaseIsabelle\PHPromBundle\Metric\AbstractMetric;
class Summary extends AbstractMetric
{
public function observe($value, array $labels = [])
{
// Custom logic to send to phprom
}
}
Register it as a service:
services:
App\Metric\Summary:
tags: ['phprom.metric']
Override Default Metrics
Replace default metrics (e.g., Counter) by binding your own service:
services:
ChaseIsabelle\PHPromBundle\Metric\Counter:
alias: App\Metric\CustomCounter
public: true
Event Listeners Hook into metric events (if the bundle supports them) to pre-process values:
namespace App\EventListener;
use ChaseIsabelle\PHPromBundle\Event\MetricEvent;
class MetricListener
{
public function onMetricSend(MetricEvent $event)
{
$event->setValue($event->getValue() * 1000); // Convert to ms
}
}
Register the listener in services.yaml:
services:
App\EventListener\MetricListener:
tags:
- { name: 'kernel.event_listener', event: 'phprom.metric.send', method: 'onMetricSend' }
Dynamic Namespace Use environment variables for the namespace:
phprom:
namespace: "%env(APP_NAME)%_metrics"
Set APP_NAME in .env.
Batch Metrics Group metric increments in a single call where possible to reduce network overhead:
$counter->increment('batch_1');
$counter->increment('batch_2');
// Flush happens automatically (or manually if async_flush is false)
Avoid Blocking Calls If using synchronous flushing, ensure metric calls don’t block critical paths (e.g., in middleware). Offload to async tasks if needed.
Monitor phprom Server
Keep the phprom server’s resource usage in check. High cardinality or rapid-fire metrics can overwhelm it. Use phprom --max-series to limit series.
How can I help you explore Laravel packages today?