Bundle Symfony pour exporter des statistiques au format Prometheus



Tout en travaillant sur divers services micro (et pas si) écrits à l'aide de Symfony, chaque fois que je rencontrais le besoin d'exporter des métriques pour Prometheus. Au début, nous avons simplement copié le même code entre les projets, mais quand il y en avait plus de trois, je pensais que je ne pourrais pas continuer comme ça (je ne me soucierai pas d'expliquer pourquoi cela est gênant; je pense que tout le monde le comprend lui-même).

Il a été décidé de séparer l'ensemble de cette économie en un bundle distinct: ArtprimaPrometheusMetricsBundle .

En choisissant des métriques communes pour toutes les applications, j'ai décidé d'écrire un bundle. Le client a été sélectionné comme client Jimdo / prometheus_client_php , ce qui vous permet d'utiliser comme magasin de statistiques: Redis (via ext-redis), APCu (via ext-apcu) et InMemory (en mémoire PHP, uniquement pour la durée de vie du processus). Je ferai une réservation tout de suite que seul APCu est testé dans la pratique (j'avais besoin d'avoir des statistiques par instance, alors que dans Redis il y en aura partagées, sauf si Redis est déployé sur chaque instance). Et InMemory en général, à mon humble avis, ne peut être utilisé que pour des tests.

Il y a eu un problème immédiatement avec Jimdo / prometheus_client_php - il n'y a pas eu de version depuis longtemps et les fonctionnalités requises (APCu) ne sont pas disponibles en tant que version. À cet égard, j'ai fait ma fourchette du client , qui ne diffère que par le fait qu'il a la bonne balise pour générer la version.

Le deuxième problème que j'ai rencontré concerne les recettes de Symfony. Vous n'avez même pas à vous mêler du dépôt officiel, et les demandes de pull-request de la communauté prendront très longtemps (pour le moment, le bundle a presque un mois et la recette PR est toujours à l'étude). À cet égard, lors de l'installation, vous devez effectuer manuellement les réglages nécessaires. Heureusement, il n'y en a pas beaucoup.

En fait, vous devez configurer la configuration principale:

#config/packages/prometheus-metrics.yaml artprima_prometheus_metrics: # namespace     prometheus namespace: myapp #    type: in_memory #  : in_memory, apcu, redis #   ,         ignored_routes: [some_route_name, another_route_name] #     "redis" (   ) redis: host: 127.0.0.1 port: 6379 timeout: 0.1 read_timeout: 10 persistent_connections: false password: ~ 

Ensuite, vous devez exporter l'itinéraire:

 #    /metrics/prometheus app_metrics: resource: '@ArtprimaPrometheusMetricsBundle/Resources/config/routing.xml' 

Ou vous pouvez configurer l'itinéraire manuellement:

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

C'est fait. Par conséquent, vos métriques seront disponibles sur http [s]: // your_host / metrics / prometheus (si vous n'avez pas modifié le chemin d'accès). Et après un certain temps, vous obtenez quelque chose comme ceci:

exemple de métrique
# HELP myapp_http_2xx_responses_total total 2xx response count
# TYPE myapp_http_2xx_responses_total counter
myapp_http_2xx_responses_total{action="GET-app_ep1"} 3911
myapp_http_2xx_responses_total{action="GET-app_ep2"} 29974
myapp_http_2xx_responses_total{action="GET-app_ep3"} 323
myapp_http_2xx_responses_total{action="GET-app_ep4"} 18
myapp_http_2xx_responses_total{action="GET-app_ep5"} 3627
myapp_http_2xx_responses_total{action="GET-app_search"} 5962
myapp_http_2xx_responses_total{action="GET-app_ep8"} 42967
myapp_http_2xx_responses_total{action="GET-app_variants"} 641
myapp_http_2xx_responses_total{action="all"} 87423
# HELP myapp_http_4xx_responses_total total 4xx response count
# TYPE myapp_http_4xx_responses_total counter
myapp_http_4xx_responses_total{action="GET-app_ep2"} 71
myapp_http_4xx_responses_total{action="GET-app_ep8"} 2584
myapp_http_4xx_responses_total{action="all"} 2660
# HELP myapp_http_requests_total total request count
# TYPE myapp_http_requests_total counter
myapp_http_requests_total{action="GET-app_ep1"} 3922
myapp_http_requests_total{action="GET-app_ep2"} 30098
myapp_http_requests_total{action="GET-app_ep3"} 468
myapp_http_requests_total{action="GET-app_ep4"} 18
myapp_http_requests_total{action="GET-app_ep5"} 3631
myapp_http_requests_total{action="GET-app_search"} 5964
myapp_http_requests_total{action="GET-app_ep8"} 45556
myapp_http_requests_total{action="GET-app_variants"} 644
myapp_http_requests_total{action="all"} 90301
# HELP myapp_instance_name app instance name
# TYPE myapp_instance_name gauge
myapp_instance_name{instance="myapp-77c4d96744-cf9nz"} 1
# HELP myapp_request_durations_histogram_seconds request durations in seconds
# TYPE myapp_request_durations_histogram_seconds histogram
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.025"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.05"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.075"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.1"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.25"} 59
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.5"} 1915
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="0.75"} 3115
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="1"} 3553
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="2.5"} 3879
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="5"} 3911
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="7.5"} 3911
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="10"} 3911
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep1",le="+Inf"} 3911
myapp_request_durations_histogram_seconds_count{action="GET-app_ep1"} 3911
myapp_request_durations_histogram_seconds_sum{action="GET-app_ep1"} 2413.185
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.025"} 50
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.05"} 62
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.075"} 63
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.1"} 72
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.25"} 914
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.5"} 2761
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="0.75"} 14326
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="1"} 23571
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="2.5"} 29569
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="5"} 30045
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="7.5"} 30045
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="10"} 30045
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep2",le="+Inf"} 30045
myapp_request_durations_histogram_seconds_count{action="GET-app_ep2"} 30045
myapp_request_durations_histogram_seconds_sum{action="GET-app_ep2"} 26552.86
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.005"} 141
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.01"} 144
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.025"} 144
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.05"} 144
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.075"} 145
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.1"} 145
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.25"} 145
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.5"} 199
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="0.75"} 408
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="1"} 442
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="2.5"} 468
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="5"} 468
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="7.5"} 468
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="10"} 468
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep3",le="+Inf"} 468
myapp_request_durations_histogram_seconds_count{action="GET-app_ep3"} 468
myapp_request_durations_histogram_seconds_sum{action="GET-app_ep3"} 216.495
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.025"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.05"} 4
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.075"} 10
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.1"} 13
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.25"} 16
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.5"} 17
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="0.75"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="1"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="2.5"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="5"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="7.5"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="10"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep4",le="+Inf"} 18
myapp_request_durations_histogram_seconds_count{action="GET-app_ep4"} 18
myapp_request_durations_histogram_seconds_sum{action="GET-app_ep4"} 2.291
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.025"} 1
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.05"} 16
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.075"} 97
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.1"} 269
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.25"} 2308
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.5"} 3351
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="0.75"} 3566
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="1"} 3612
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="2.5"} 3627
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="5"} 3627
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="7.5"} 3627
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="10"} 3627
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep5",le="+Inf"} 3627
myapp_request_durations_histogram_seconds_count{action="GET-app_ep5"} 3627
myapp_request_durations_histogram_seconds_sum{action="GET-app_ep5"} 959.773
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.025"} 18
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.05"} 547
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.075"} 968
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.1"} 1387
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.25"} 3784
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.5"} 5377
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="0.75"} 5811
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="1"} 5913
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="2.5"} 5959
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="5"} 5960
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="7.5"} 5960
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="10"} 5960
myapp_request_durations_histogram_seconds_bucket{action="GET-app_search",le="+Inf"} 5962
myapp_request_durations_histogram_seconds_count{action="GET-app_search"} 5962
myapp_request_durations_histogram_seconds_sum{action="GET-app_search"} 1516.982
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.025"} 2724
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.05"} 8348
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.075"} 18828
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.1"} 28811
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.25"} 39709
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.5"} 43958
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="0.75"} 45161
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="1"} 45436
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="2.5"} 45541
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="5"} 45549
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="7.5"} 45549
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="10"} 45549
myapp_request_durations_histogram_seconds_bucket{action="GET-app_ep8",le="+Inf"} 45551
myapp_request_durations_histogram_seconds_count{action="GET-app_ep8"} 45551
myapp_request_durations_histogram_seconds_sum{action="GET-app_ep8"} 6125.712
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.005"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.01"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.025"} 0
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.05"} 252
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.075"} 451
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.1"} 511
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.25"} 583
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.5"} 631
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="0.75"} 640
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="1"} 641
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="2.5"} 641
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="5"} 641
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="7.5"} 641
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="10"} 641
myapp_request_durations_histogram_seconds_bucket{action="GET-app_variants",le="+Inf"} 641
myapp_request_durations_histogram_seconds_count{action="GET-app_variants"} 641
myapp_request_durations_histogram_seconds_sum{action="GET-app_variants"} 62.744
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.005"} 145
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.01"} 148
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.025"} 2942
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.05"} 9378
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.075"} 20567
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.1"} 31213
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.25"} 47523
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.5"} 58214
myapp_request_durations_histogram_seconds_bucket{action="all",le="0.75"} 73050
myapp_request_durations_histogram_seconds_bucket{action="all",le="1"} 83191
myapp_request_durations_histogram_seconds_bucket{action="all",le="2.5"} 89707
myapp_request_durations_histogram_seconds_bucket{action="all",le="5"} 90224
myapp_request_durations_histogram_seconds_bucket{action="all",le="7.5"} 90224
myapp_request_durations_histogram_seconds_bucket{action="all",le="10"} 90224
myapp_request_durations_histogram_seconds_bucket{action="all",le="+Inf"} 90228
myapp_request_durations_histogram_seconds_count{action="all"} 90228
myapp_request_durations_histogram_seconds_sum{action="all"} 37850.074


Naturellement, il se peut qu'il n'y ait pas assez de métriques de base bientôt, vous avez donc toujours la possibilité d'écrire votre propre générateur de métriques (en plus de celui existant) et de l'exporter comme ceci:

 # config/services.yaml App\Metrics\MyMetricsGenerator: tags: - { name: prometheus_metrics_bundle.metrics_generator } 

Dans le même temps, votre générateur doit implémenter l' Artprima\PrometheusMetricsBundle\Metrics\MetricsGeneratorInterface . Vous pouvez voir à quoi pourrait ressembler le générateur dans Artprima\PrometheusMetricsBundle\Metrics\AppMetrics . La principale chose que vous devez savoir ici est que la méthode collectRequest appelée sur l'événement kernel.request et la méthode collectResponse est collectResponse sur l'événement kernel.terminate .

J'accepte essentiellement la critique. Tant sous forme de conseils que de relations publiques :-)

PS Attention aux commentaires que nous avons inventé la moto: oui, je sais qu'il existe des alternatives. Et, très probablement, ils sont certainement meilleurs. En particulier, l'un d'eux est le TweedeGolfPrometheusBundle . Malheureusement, je ne me souviens pas pourquoi nous n'avons pas choisi cette solution, mais il y a un peu plus de six mois, nous l'avons essayée et refusée. D'une manière ou d'une autre, je pense qu'avoir le choix est toujours bon, c'est pourquoi notre bundle a été publié dans OpenSource.

Source: https://habr.com/ru/post/fr429800/


All Articles