artprima/prometheus-metrics-bundle

Symfony 4 Prometheus Metrics Bundle

Installs: 19 329

Dependents: 0

Suggesters: 0

Stars: 16

Watchers: 2

Forks: 3

Open Issues: 0

Type:symfony-bundle

1.1.1 2019-02-07 10:34 UTC

README

Master
Build Status
Coverage Status
Quality Status

Symfony 4 Prometheus Metrics Bundle

Installation

Applications that use Symfony Flex

Open a command console, enter your project directory and execute:

$ composer require artprima/prometheus-metrics-bundle

Applications that don't use Symfony Flex

Step 1: Download the Bundle

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

$ composer require artprima/prometheus-metrics-bundle

This command requires you to have Composer installed globally, as explained in the installation chapter of the Composer documentation.

Step 2: Enable the Bundle

Then, enable the bundle by adding it to the list of registered bundles in the app/AppKernel.php file of your project:

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...
            new Artprima\PrometheusMetricsBundle\ArtprimaPrometheusMetricsBundle(),
        );

        // ...
    }

    // ...
}

Configuration

config.yaml

artprima_prometheus_metrics:
    # namespace is used to prefix the prometheus metrics
    namespace: myapp

    # metrics backend type
    type: in_memory # possible values: in_memory, apcu, redis

    # ignoring some routes in metrics
    ignored_routes: [some_route_name, another_route_name]

    # used in case of type = "redis"
    redis:
        host: 127.0.0.1
        port: 6379
        timeout: 0.1
        read_timeout: 10
        persistent_connections: false
        password: ~

routes.yaml

# expose /metrics/prometheus in your application
app_metrics:
    resource: '@ArtprimaPrometheusMetricsBundle/Resources/config/routing.xml'

You can alternatively define your own path and rules:

app_metrics:
    path: /mypath/mymetrics
    controller: Artprima\PrometheusMetricsBundle\Controller\MetricsController::prometheus

Now your metrics are available to Prometheus using http://<yourapp_url>/metrics/prometheus.

Custom Metrics Generator

If you want to collect your own metrics, you should create a class that will implement Artprima\PrometheusMetricsBundle\Metrics\MetricsGeneratorInterface. Something like this:

<?php

declare(strict_types=1);

namespace App\Metrics;

use Artprima\PrometheusMetricsBundle\Metrics\MetricsGeneratorInterface;
use Prometheus\CollectorRegistry;
use Prometheus\Exception\MetricNotFoundException;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;

/**
 * Class MyMetricsGenerator.
 */
class MyMetricsGenerator implements MetricsGeneratorInterface
{
    /**
     * @var string
     */
    private $namespace;

    /**
     * @var CollectorRegistry
     */
    private $collectionRegistry;

    public function init(string $namespace, CollectorRegistry $collectionRegistry): void
    {
        $this->namespace = $namespace;
        $this->collectionRegistry = $collectionRegistry;
    }

    private function incRequestsTotal(?string $method = null, ?string $route = null): void
    {
        $counter = $this->collectionRegistry->getOrRegisterCounter(
            $this->namespace,
            'http_requests_total',
            'total request count',
            ['action']
        );

        $counter->inc(['all']);

        if (null !== $method && null !== $route) {
            $counter->inc([sprintf('%s-%s', $method, $route)]);
        }
    }

    private function incResponsesTotal(?string $method = null, ?string $route = null): void
    {
        $counter = $this->collectionRegistry->getOrRegisterCounter(
            $this->namespace,
            'http_responses_total',
            'total response count',
            ['action']
        );
        $counter->inc(['all']);

        if (null !== $method && null !== $route) {
            $counter->inc([sprintf('%s-%s', $method, $route)]);
        }
    }

    // called on the `kernel.request` event
    public function collectRequest(GetResponseEvent $event): void
    {
        $request = $event->getRequest();
        $requestMethod = $request->getMethod();
        $requestRoute = $request->attributes->get('_route');

        // do not track "OPTIONS" requests
        if ('OPTIONS' === $requestMethod) {
            return;
        }

        $this->incRequestsTotal($requestMethod, $requestRoute);
    }

    // called on the `kernel.terminate` event
    public function collectResponse(PostResponseEvent $event): void
    {
        $response = $event->getResponse();
        $request = $event->getRequest();

        $requestMethod = $request->getMethod();
        $requestRoute = $request->attributes->get('_route');

        $this->incResponsesTotal($requestMethod, $requestRoute);
    }
}

Then declare it this way:

    App\Metrics\MyMetricsGenerator:
        # NB: do NOT add a call to `init()` as it will be done automatically by the relevant compiler pass.
        tags:
            - { name: prometheus_metrics_bundle.metrics_generator }

Code license

You are free to use the code in this repository under the terms of the MIT license. LICENSE contains a copy of this license.