From 287710459c0142c3c9128de914aa2f4365977e50 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:05:53 +0200 Subject: [PATCH 01/83] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b16da07..03d0716 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # morty-counts +Teaching Morty how to count and sending the results to Prometheus + ![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) From d8a14742eff562a23c54890a995792e2f80f435b Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:09:23 +0200 Subject: [PATCH 02/83] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 03d0716..4a743f3 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,9 @@ Teaching Morty how to count and sending the results to Prometheus ![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) + +## Requirements + +`Redis` to act as a buffer before and avoid latency in the code + +`comsave:prometheus:push` cronjob to push data periodically to Prometheus Pushgateway From 4b056c9a735da5d7231202cb01bbcb38bb645590 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:09:33 +0200 Subject: [PATCH 03/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a743f3..2156cc2 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,4 @@ Teaching Morty how to count and sending the results to Prometheus `Redis` to act as a buffer before and avoid latency in the code -`comsave:prometheus:push` cronjob to push data periodically to Prometheus Pushgateway +`bin/console comsave:prometheus:push` cronjob to push data periodically to Prometheus Pushgateway From f446df06b1ee28f97b0b50eebfdee887a9805ccf Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:09:45 +0200 Subject: [PATCH 04/83] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2156cc2..0a5de89 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,7 @@ Teaching Morty how to count and sending the results to Prometheus `Redis` to act as a buffer before and avoid latency in the code `bin/console comsave:prometheus:push` cronjob to push data periodically to Prometheus Pushgateway + +## License + +MIT From 1067fa8f99ba7ba1678024d815be1924c8f041a5 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:10:04 +0200 Subject: [PATCH 05/83] Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..550782c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Comsave + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 5d7546737a9bdae4ce1879c2d0b4f1d91d211c97 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:16:08 +0200 Subject: [PATCH 06/83] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0a5de89..485f55e 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ Teaching Morty how to count and sending the results to Prometheus ## Requirements -`Redis` to act as a buffer before and avoid latency in the code +1. `Redis` (the service & the PHP extension): to act as a buffer before and avoid latency in the code -`bin/console comsave:prometheus:push` cronjob to push data periodically to Prometheus Pushgateway +2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway ## License From baa0159ce7048a0a7ca870a86509030768ae4b0f Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:16:58 +0200 Subject: [PATCH 07/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 485f55e..a214599 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Teaching Morty how to count and sending the results to Prometheus ## Requirements -1. `Redis` (the service & the PHP extension): to act as a buffer before and avoid latency in the code +1. `Redis` (the service & the PHP extension): to act as a buffer before push and avoid latency in the code 2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway From c98c017205e57174eaea93d9b6137bda891a99e8 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:18:51 +0200 Subject: [PATCH 08/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a214599..daa0f99 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Teaching Morty how to count and sending the results to Prometheus -![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) +![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) ![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) ![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) ## Requirements From 8e23012f778a57ec8b44cf4756335be4fb68bf6e Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 13:19:19 +0200 Subject: [PATCH 09/83] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index daa0f99..95493b3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # morty-counts -Teaching Morty how to count and sending the results to Prometheus +Teaching Morty how to count and sending the results to Prometheus. -![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) ![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) ![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) +![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) +![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) ## Requirements @@ -13,3 +14,5 @@ Teaching Morty how to count and sending the results to Prometheus ## License MIT + +![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) From 828ee2c4916e09e2a9ea4b2603268f4208f2acf5 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 15:24:14 +0200 Subject: [PATCH 10/83] init --- .gitignore | 2 + composer.json | 7 + composer.lock | 574 +++++++++++++++++++++++++++++++++++++++++++++++ src/.gitignore | 0 tests/.gitignore | 0 5 files changed, 583 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 src/.gitignore create mode 100644 tests/.gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0caea8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +vendor/ \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..751dd0c --- /dev/null +++ b/composer.json @@ -0,0 +1,7 @@ +{ + "name": "comsave/morty-counts", + "license": "MIT", + "require": { + "endclothing/prometheus_client_php": "^1.0" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..c6f286f --- /dev/null +++ b/composer.lock @@ -0,0 +1,574 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b8dcdd16110c2c60b3b6b083792eae82", + "packages": [ + { + "name": "endclothing/prometheus_client_php", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/endclothing/prometheus_client_php.git", + "reference": "ae61369d8667343cfff70fec648b3448a2076778" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/endclothing/prometheus_client_php/zipball/ae61369d8667343cfff70fec648b3448a2076778", + "reference": "ae61369d8667343cfff70fec648b3448a2076778", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.2", + "php": "^7.1", + "symfony/polyfill-apcu": "^1.6" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-apc": "Required if using APCu.", + "ext-redis": "Required if using Redis." + }, + "type": "library", + "autoload": { + "psr-4": { + "Prometheus\\": "src/Prometheus/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Daniel Noel-Davies", + "email": "Daniel.Noel-Davies@endclothing.com" + } + ], + "time": "2019-10-04T10:46:29+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.5.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e", + "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.6.1", + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.11" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.1" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2020-04-18T10:38:46+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "suggest": { + "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2019-07-01T23:21:34+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "symfony/polyfill-apcu", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-apcu.git", + "reference": "d6b5c4ac62cd4ed622e583d027ae684de2d3c4bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/d6b5c4ac62cd4ed622e583d027ae684de2d3c4bd", + "reference": "d6b5c4ac62cd4ed622e583d027ae684de2d3c4bd", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Apcu\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "apcu", + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2020-02-27T09:26:54+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2020-03-09T19:04:49+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2020-03-09T19:04:49+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "37b0976c78b94856543260ce09b460a7bc852747" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", + "reference": "37b0976c78b94856543260ce09b460a7bc852747", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2020-02-27T09:26:54+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..e69de29 From f17717dcdf12ad946d0ea2ebab4d0c849a84f9d1 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 15:25:15 +0200 Subject: [PATCH 11/83] require ext-redis --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 751dd0c..baa4354 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,7 @@ "name": "comsave/morty-counts", "license": "MIT", "require": { + "ext-redis": "*", "endclothing/prometheus_client_php": "^1.0" } } From 271ecb72ae66d74c0d588478661dbad32f5f66d9 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 15:51:54 +0200 Subject: [PATCH 12/83] init bundle --- .dockerignore | 2 + .gitignore | 3 +- README.md | 4 + composer.json | 9 +- composer.lock | 574 ------------------ docker-compose.yml | 14 + docker/php-fpm/Dockerfile | 14 + src/.gitignore | 0 .../Command/ComsavePrometheusPushCommand.php | 9 + .../MortyCountsBundle/MortyCountsBundle.php | 9 + 10 files changed, 62 insertions(+), 576 deletions(-) create mode 100644 .dockerignore delete mode 100644 composer.lock create mode 100644 docker-compose.yml create mode 100644 docker/php-fpm/Dockerfile delete mode 100644 src/.gitignore create mode 100644 src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php create mode 100644 src/Comsave/MortyCountsBundle/MortyCountsBundle.php diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..32edd2f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.git +docker \ No newline at end of file diff --git a/.gitignore b/.gitignore index e0caea8..cdb3d20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ -vendor/ \ No newline at end of file +vendor/ +composer.lock \ No newline at end of file diff --git a/README.md b/README.md index 95493b3..7a20487 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Teaching Morty how to count and sending the results to Prometheus. 2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway +## Development + +`docker-compose up --remove-orphans -d --build` + ## License MIT diff --git a/composer.json b/composer.json index baa4354..6f3d60f 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,13 @@ "license": "MIT", "require": { "ext-redis": "*", - "endclothing/prometheus_client_php": "^1.0" + "endclothing/prometheus_client_php": "^1.0", + "symfony/http-kernel": "^3.4|^4.4", + "symfony/console": "^3.4|^4.4" + }, + "autoload": { + "psr-4": { + "Comsave\\": "src/Comsave" + } } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index c6f286f..0000000 --- a/composer.lock +++ /dev/null @@ -1,574 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "b8dcdd16110c2c60b3b6b083792eae82", - "packages": [ - { - "name": "endclothing/prometheus_client_php", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/endclothing/prometheus_client_php.git", - "reference": "ae61369d8667343cfff70fec648b3448a2076778" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/endclothing/prometheus_client_php/zipball/ae61369d8667343cfff70fec648b3448a2076778", - "reference": "ae61369d8667343cfff70fec648b3448a2076778", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/guzzle": "^6.2", - "php": "^7.1", - "symfony/polyfill-apcu": "^1.6" - }, - "require-dev": { - "phpunit/phpunit": "^7.5" - }, - "suggest": { - "ext-apc": "Required if using APCu.", - "ext-redis": "Required if using Redis." - }, - "type": "library", - "autoload": { - "psr-4": { - "Prometheus\\": "src/Prometheus/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Daniel Noel-Davies", - "email": "Daniel.Noel-Davies@endclothing.com" - } - ], - "time": "2019-10-04T10:46:29+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.5.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e", - "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.6.1", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.11" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.1" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.5-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2020-04-18T10:38:46+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "239400de7a173fe9901b9ac7c06497751f00727a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", - "reference": "239400de7a173fe9901b9ac7c06497751f00727a", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" - }, - "suggest": { - "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2019-07-01T23:21:34+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "time": "2019-03-08T08:55:37+00:00" - }, - { - "name": "symfony/polyfill-apcu", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "d6b5c4ac62cd4ed622e583d027ae684de2d3c4bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/d6b5c4ac62cd4ed622e583d027ae684de2d3c4bd", - "reference": "d6b5c4ac62cd4ed622e583d027ae684de2d3c4bd", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.15-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "apcu", - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2020-02-27T09:26:54+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", - "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.15-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "time": "2020-03-09T19:04:49+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", - "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.15-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2020-03-09T19:04:49+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "37b0976c78b94856543260ce09b460a7bc852747" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", - "reference": "37b0976c78b94856543260ce09b460a7bc852747", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.15-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2020-02-27T09:26:54+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [] -} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ed188bc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3" + +services: + php: + build: + dockerfile: ./docker/php-fpm/Dockerfile + context: . + depends_on: + - redis + volumes: + - ./:/app + + redis: + image: redis:alpine \ No newline at end of file diff --git a/docker/php-fpm/Dockerfile b/docker/php-fpm/Dockerfile new file mode 100644 index 0000000..64702e2 --- /dev/null +++ b/docker/php-fpm/Dockerfile @@ -0,0 +1,14 @@ +FROM php:7.3-fpm + +RUN apt-get update && apt-get install git -y +RUN pecl install redis && docker-php-ext-enable redis + +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ + php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \ + php composer-setup.php && \ + php -r "unlink('composer-setup.php');" && \ + mv composer.phar /usr/local/bin/composer && \ + chmod +x /usr/local/bin/composer + +WORKDIR /app +#COPY ./* /app/ \ No newline at end of file diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php new file mode 100644 index 0000000..9b2409e --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php @@ -0,0 +1,9 @@ + Date: Tue, 21 Apr 2020 15:59:53 +0200 Subject: [PATCH 13/83] init config --- .../MortyCountsBundle/Resources/config/services.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/Comsave/MortyCountsBundle/Resources/config/services.yml diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml new file mode 100644 index 0000000..8e3d885 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -0,0 +1,9 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Comsave\: + resource: '../src/*' + exclude: '../src/**/{Enum,Kernel.php}' \ No newline at end of file From 328532a23cad2af6ccd79bc42ad5ec373444513b Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 21 Apr 2020 16:15:36 +0200 Subject: [PATCH 14/83] init prometheus publisher --- .../Services/PrometheusMetricPublisher.php | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php b/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php new file mode 100644 index 0000000..e79eac3 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php @@ -0,0 +1,60 @@ +registry = $registry; + $this->registryStorageAdapter = $registryStorageAdapter; + $this->pushGatewayUrl = $pushGatewayUrl; + } + + /** + * @return bool + * @throws \Prometheus\Exception\MetricsRegistrationException + */ + public function buffer(): bool + { + $counter = $this->registry->registerCounter('test', 'some_counter', 'it increases', ['type']); + $counter->incBy(6, ['blue']); + } + + /** + * @param string $jobName + * @param string $instanceName + * @return bool + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\StorageException + */ + public function publish(string $jobName, string $instanceName): bool + { + $pushGateway = new PushGateway($this->pushGatewayUrl); + + $pushGateway->push($this->registry, $jobName, [ + 'instance' => $instanceName, + ]); + + $this->registryStorageAdapter->flushRedis(); + } +} \ No newline at end of file From 94dcdea97b61194925cb8bc5c5546c4d352ceb02 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 09:21:57 +0200 Subject: [PATCH 15/83] add pushgateway factory --- .../Factory/PushGatewayFactory.php | 13 +++++++++++++ .../Resources/config/services.yml | 9 ++++++++- .../Services/PrometheusMetricPublisher.php | 14 ++++++-------- 3 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php diff --git a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php new file mode 100644 index 0000000..3467f29 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php @@ -0,0 +1,13 @@ +registry = $registry; $this->registryStorageAdapter = $registryStorageAdapter; - $this->pushGatewayUrl = $pushGatewayUrl; + $this->pushGateway = $pushGateway; } /** @@ -49,9 +49,7 @@ public function buffer(): bool */ public function publish(string $jobName, string $instanceName): bool { - $pushGateway = new PushGateway($this->pushGatewayUrl); - - $pushGateway->push($this->registry, $jobName, [ + $this->pushGateway->push($this->registry, $jobName, [ 'instance' => $instanceName, ]); From 59991c3ebb1975ffe90fdfb7d32a08c259a1ff42 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 09:29:17 +0200 Subject: [PATCH 16/83] add redis storage adapter factory --- .../Factory/RedisStorageAdapterFactory.php | 16 ++++++++++++++++ .../Resources/config/services.yml | 15 ++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php diff --git a/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php b/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php new file mode 100644 index 0000000..ca09646 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php @@ -0,0 +1,16 @@ + $redisHost, + 'port' => $redisPort + ]); + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index 9ef0e47..705f05d 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -1,5 +1,7 @@ parameters: morty_counts_pushgateway_url: '' + morty_counts_redis_host: '' + morty_counts_redis_port: '' services: _defaults: @@ -13,4 +15,15 @@ services: Prometheus\PushGateway: factory: ['Comsave\MortyCountsBundle\PushGatewayFactory', 'build'] - arguments: ['%morty_counts_pushgateway_url%'] \ No newline at end of file + arguments: + $pushGatewayUrl: '%morty_counts_pushgateway_url%'] + + Prometheus\Storage\Redis: + factory: ['Comsave\MortyCountsBundle\RedisStorageAdapterFactory', 'build'] + arguments: + $redisHost: '%morty_counts_redis_host%'] + $redisPort: '%morty_counts_redis_port%'] + + Prometheus\CollectorRegistry: + arguments: + $adapter: Prometheus\Storage\Redis \ No newline at end of file From b0a5b6080883bb1e832e46429d2728f996d9bd68 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 11:40:42 +0200 Subject: [PATCH 17/83] add prometheus & grafana to compose --- docker-compose.yml | 33 ++++++++++++++- docker/grafana/datasources.yml | 8 ++++ docker/prometheus/prometheus.yml | 14 +++++++ .../Command/ComsavePrometheusPushCommand.php | 9 ---- .../Command/PrometheusPushCommand.php | 41 +++++++++++++++++++ .../Services/PrometheusMetricPublisher.php | 18 +++----- 6 files changed, 101 insertions(+), 22 deletions(-) create mode 100644 docker/grafana/datasources.yml create mode 100644 docker/prometheus/prometheus.yml delete mode 100644 src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php create mode 100644 src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php diff --git a/docker-compose.yml b/docker-compose.yml index ed188bc..badc817 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,4 +11,35 @@ services: - ./:/app redis: - image: redis:alpine \ No newline at end of file + image: redis:alpine + + prometheus: + image: prom/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.listen-address=:9090' + depends_on: + - pushgateway + ports: + - 9090:9090 + volumes: + - ./docker/prometheus/prometheus.yml/:/etc/prometheus/prometheus.yml + + pushgateway: + image: prom/pushgateway + command: + - '--web.listen-address=:9191' + ports: + - 9191:9191 + + grafana: + image: grafana/grafana + depends_on: + - prometheus + ports: + - 3000:3000 + volumes: + - ./docker/grafana/datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml + environment: + - GF_SECURITY_ADMIN_PASSWORD=admin + - GF_USERS_ALLOW_SIGN_UP=false \ No newline at end of file diff --git a/docker/grafana/datasources.yml b/docker/grafana/datasources.yml new file mode 100644 index 0000000..86fd346 --- /dev/null +++ b/docker/grafana/datasources.yml @@ -0,0 +1,8 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true diff --git a/docker/prometheus/prometheus.yml b/docker/prometheus/prometheus.yml new file mode 100644 index 0000000..58c87ba --- /dev/null +++ b/docker/prometheus/prometheus.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'prometheus' + scrape_interval: 5s + static_configs: + - targets: ['prometheus:9090'] + + - job_name: 'pushgateway' + honor_labels: true + scrape_interval: 2s + static_configs: + - targets: ['localhost:9191'] \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php deleted file mode 100644 index 9b2409e..0000000 --- a/src/Comsave/MortyCountsBundle/Command/ComsavePrometheusPushCommand.php +++ /dev/null @@ -1,9 +0,0 @@ -prometheusMetricPublisher = $prometheusMetricPublisher; + + parent::__construct(); + } + + public function configure(): void + { + $this + ->setName('comsave:prometheus:push') + ->setDescription(''); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->prometheusMetricPublisher->publish(); + + $output->writeln('Metrics sent.'); + + return 0; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php b/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php index 687f59e..a0af154 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php @@ -30,24 +30,13 @@ public function __construct(CollectorRegistry $registry, Redis $registryStorageA $this->pushGateway = $pushGateway; } - /** - * @return bool - * @throws \Prometheus\Exception\MetricsRegistrationException - */ - public function buffer(): bool - { - $counter = $this->registry->registerCounter('test', 'some_counter', 'it increases', ['type']); - $counter->incBy(6, ['blue']); - } - /** * @param string $jobName * @param string $instanceName - * @return bool * @throws \GuzzleHttp\Exception\GuzzleException * @throws \Prometheus\Exception\StorageException */ - public function publish(string $jobName, string $instanceName): bool + public function publish(string $jobName, string $instanceName): void { $this->pushGateway->push($this->registry, $jobName, [ 'instance' => $instanceName, @@ -55,4 +44,9 @@ public function publish(string $jobName, string $instanceName): bool $this->registryStorageAdapter->flushRedis(); } + + public function getRegistry(): CollectorRegistry + { + return $this->registry; + } } \ No newline at end of file From 382d1cba62d72fe876d61553ba32299db87d0928 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 11:41:18 +0200 Subject: [PATCH 18/83] update prometheus config --- docker/prometheus/prometheus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/prometheus/prometheus.yml b/docker/prometheus/prometheus.yml index 58c87ba..4f7f73a 100644 --- a/docker/prometheus/prometheus.yml +++ b/docker/prometheus/prometheus.yml @@ -11,4 +11,4 @@ scrape_configs: honor_labels: true scrape_interval: 2s static_configs: - - targets: ['localhost:9191'] \ No newline at end of file + - targets: ['pushgateway:9191'] \ No newline at end of file From ceeec7580d9a316263f02401ee0171e7fa653baa Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 12:38:07 +0200 Subject: [PATCH 19/83] init tests --- composer.json | 8 ++++++++ docker/php-fpm/Dockerfile | 8 ++++++-- tests/Integration/PushTest.php | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/Integration/PushTest.php diff --git a/composer.json b/composer.json index 6f3d60f..865ffbd 100644 --- a/composer.json +++ b/composer.json @@ -7,9 +7,17 @@ "symfony/http-kernel": "^3.4|^4.4", "symfony/console": "^3.4|^4.4" }, + "require-dev": { + "phpunit/phpunit": "^9.1" + }, "autoload": { "psr-4": { "Comsave\\": "src/Comsave" } + }, + "autoload-dev": { + "psr-4": { + "Comsave\\Tests\\": "tests" + } } } diff --git a/docker/php-fpm/Dockerfile b/docker/php-fpm/Dockerfile index 64702e2..2926578 100644 --- a/docker/php-fpm/Dockerfile +++ b/docker/php-fpm/Dockerfile @@ -1,7 +1,6 @@ FROM php:7.3-fpm RUN apt-get update && apt-get install git -y -RUN pecl install redis && docker-php-ext-enable redis RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \ @@ -10,5 +9,10 @@ RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && mv composer.phar /usr/local/bin/composer && \ chmod +x /usr/local/bin/composer +RUN pecl install redis && docker-php-ext-enable redis +RUN apt-get install zip unzip -y + WORKDIR /app -#COPY ./* /app/ \ No newline at end of file +COPY composer.* ./ +RUN composer install +COPY ./* ./ \ No newline at end of file diff --git a/tests/Integration/PushTest.php b/tests/Integration/PushTest.php new file mode 100644 index 0000000..2280841 --- /dev/null +++ b/tests/Integration/PushTest.php @@ -0,0 +1,17 @@ +assertTrue(true); + } +} \ No newline at end of file From a734deb521a38bfcfe6e3c50c8f229351e760703 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 13:34:12 +0200 Subject: [PATCH 20/83] add PrometheusPushTest --- .../Command/PrometheusPushCommand.php | 8 +- .../Factory/GuzzleHttpClientFactory.php | 13 ++++ .../Resources/config/services.yml | 11 ++- .../Services/PrometheusClient.php | 37 +++++++++ ...ricPublisher.php => PushGatewayClient.php} | 17 +++-- tests/Integration/PrometheusPushTest.php | 75 +++++++++++++++++++ tests/Integration/PushTest.php | 17 ----- 7 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php create mode 100644 src/Comsave/MortyCountsBundle/Services/PrometheusClient.php rename src/Comsave/MortyCountsBundle/Services/{PrometheusMetricPublisher.php => PushGatewayClient.php} (72%) create mode 100644 tests/Integration/PrometheusPushTest.php delete mode 100644 tests/Integration/PushTest.php diff --git a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php index 5914b06..d9b8500 100644 --- a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php +++ b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php @@ -2,21 +2,21 @@ namespace Comsave\MortyCountsBundle\Command; -use Comsave\MortyCountsBundle\Services\PrometheusMetricPublisher; +use Comsave\MortyCountsBundle\Services\PushGatewayClient; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class PrometheusPushCommand extends Command { - /** @var PrometheusMetricPublisher */ + /** @var PushGatewayClient */ private $prometheusMetricPublisher; /** - * @param PrometheusMetricPublisher $prometheusMetricPublisher + * @param PushGatewayClient $prometheusMetricPublisher * @codeCoverageIgnore */ - public function __construct(PrometheusMetricPublisher $prometheusMetricPublisher) + public function __construct(PushGatewayClient $prometheusMetricPublisher) { $this->prometheusMetricPublisher = $prometheusMetricPublisher; diff --git a/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php b/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php new file mode 100644 index 0000000..0802306 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php @@ -0,0 +1,13 @@ +prometheusUrl = $prometheusUrl; + $this->httpClient = $httpClient; + } + + public function query(array $arguments): array + { + $response = $this->httpClient->request('GET', vsprintf('%s/api/v1/query?%s', [ + $this->prometheusUrl, + http_build_query($arguments) + ])); + + $responseJson = json_decode((string)$response->getBody(), true); + + return $responseJson['data']['result']; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php similarity index 72% rename from src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php rename to src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index a0af154..1650417 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusMetricPublisher.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -6,7 +6,7 @@ use Prometheus\PushGateway; use Prometheus\Storage\Redis; -class PrometheusMetricPublisher +class PushGatewayClient { /** @var CollectorRegistry */ private $registry; @@ -36,11 +36,18 @@ public function __construct(CollectorRegistry $registry, Redis $registryStorageA * @throws \GuzzleHttp\Exception\GuzzleException * @throws \Prometheus\Exception\StorageException */ - public function publish(string $jobName, string $instanceName): void + public function push(string $jobName, string $instanceName): void { - $this->pushGateway->push($this->registry, $jobName, [ - 'instance' => $instanceName, - ]); + try { + $this->pushGateway->pushAdd($this->registry, $jobName, [ + 'instance' => $instanceName, + ]); + } + catch (\RuntimeException $ex) { + if(strpos($ex->getMessage(), 'Unexpected status code 200') === false) { + throw $ex; + } + } $this->registryStorageAdapter->flushRedis(); } diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php new file mode 100644 index 0000000..a1b4767 --- /dev/null +++ b/tests/Integration/PrometheusPushTest.php @@ -0,0 +1,75 @@ +prometheusClient = new PrometheusClient( + 'prometheus:9090', + GuzzleHttpClientFactory::build() + ); + + $registryStorageAdapter = RedisStorageAdapterFactory::build('redis', 6379); + $registry = new CollectorRegistry($registryStorageAdapter); + $pushGateway = PushGatewayFactory::build('pushgateway:9191'); + + $this->pushGatewayClient = new PushGatewayClient( + $registry, + $registryStorageAdapter, + $pushGateway + ); + } + + public function testPushesCounterMetric(): void + { + // todo: clear before + + $jobName = 'my_custom_service_job'; + $instanceName = '127.0.0.1:9000'; + $metricNamespace = 'test'; + $metricName = 'some_counter_' . substr(md5(mt_rand()), -10); + + $counter = $this->pushGatewayClient->getRegistry()->registerCounter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + + $this->pushGatewayClient->push($jobName, $instanceName); + + sleep(3); + + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + + $results = $this->prometheusClient->query([ + 'query' => $metricFullName, + ]); + + $this->assertCount(1, $results); + $this->assertEquals([ + '__name__' => $metricFullName, + 'instance' => $instanceName, + 'job' => $jobName, + 'type' => 'blue', + ], $results[0]['metric']); + $this->assertEquals(5, $results[0]['value'][1]); + } +} \ No newline at end of file diff --git a/tests/Integration/PushTest.php b/tests/Integration/PushTest.php deleted file mode 100644 index 2280841..0000000 --- a/tests/Integration/PushTest.php +++ /dev/null @@ -1,17 +0,0 @@ -assertTrue(true); - } -} \ No newline at end of file From f0d447c62c84e47bad2cf779f211170381c56bbd Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 14:42:15 +0200 Subject: [PATCH 21/83] update PrometheusPushTest --- README.md | 4 +- docker-compose.yml | 3 +- .../Resources/config/services.yml | 4 +- .../Services/PushGatewayClient.php | 49 ++++++++++++++----- tests/Integration/PrometheusPushTest.php | 48 ++++++++++++++++-- 5 files changed, 87 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7a20487..d53e37c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ Teaching Morty how to count and sending the results to Prometheus. ## Development -`docker-compose up --remove-orphans -d --build` +Start `docker-compose up --remove-orphans -d --build` + +Tests `docker exec $(docker ps | grep _php | awk '{print $1}') vendor/bin/phpunit tests` ## License diff --git a/docker-compose.yml b/docker-compose.yml index badc817..6eb4689 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,8 @@ services: prometheus: image: prom/prometheus command: - - '--config.file=/etc/prometheus/prometheus.yml' - '--web.listen-address=:9090' + - '--config.file=/etc/prometheus/prometheus.yml' depends_on: - pushgateway ports: @@ -29,6 +29,7 @@ services: image: prom/pushgateway command: - '--web.listen-address=:9191' + - '--push.disable-consistency-check' ports: - 9191:9191 diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index e99d8a9..1b3b2cd 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -1,5 +1,5 @@ parameters: - morty_cuonts_prometheus_url: '' + morty_counts_prometheus_url: '' morty_counts_pushgateway_url: '' morty_counts_redis_host: '' morty_counts_redis_port: '' @@ -35,4 +35,4 @@ services: Comsave\MortyCountsBundle\Services\PrometheusClient: autowire: true arguments: - $prometheusUrl: '%morty_cuonts_prometheus_url%' \ No newline at end of file + $prometheusUrl: '%morty_counts_prometheus_url%' \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index 1650417..f23e376 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -38,22 +38,47 @@ public function __construct(CollectorRegistry $registry, Redis $registryStorageA */ public function push(string $jobName, string $instanceName): void { - try { - $this->pushGateway->pushAdd($this->registry, $jobName, [ - 'instance' => $instanceName, - ]); - } - catch (\RuntimeException $ex) { - if(strpos($ex->getMessage(), 'Unexpected status code 200') === false) { - throw $ex; - } - } - - $this->registryStorageAdapter->flushRedis(); + $this->pushGateway->push($this->registry, $jobName, [ + 'instance' => $instanceName, + ]); + +// $this->registryStorageAdapter->flushRedis(); + } + + /** + * @param string $jobName + * @param string $instanceName + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\StorageException + */ + public function pushAdd(string $jobName, string $instanceName): void + { + $this->pushGateway->pushAdd($this->registry, $jobName, [ + 'instance' => $instanceName, + ]); + +// $this->registryStorageAdapter->flushRedis(); + } + + /** + * @param string $jobName + * @param string $instanceName + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function delete(string $jobName, string $instanceName): void + { + $this->pushGateway->delete($jobName, [ + 'instance' => $instanceName, + ]); } public function getRegistry(): CollectorRegistry { return $this->registry; } + + public function getRegistryStorageAdapter(): Redis + { + return $this->registryStorageAdapter; + } } \ No newline at end of file diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index a1b4767..1e7bbb6 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -27,23 +27,55 @@ public function setUp(): void $registryStorageAdapter = RedisStorageAdapterFactory::build('redis', 6379); $registry = new CollectorRegistry($registryStorageAdapter); - $pushGateway = PushGatewayFactory::build('pushgateway:9191'); $this->pushGatewayClient = new PushGatewayClient( $registry, $registryStorageAdapter, - $pushGateway + PushGatewayFactory::build('pushgateway:9191') ); + $this->pushGatewayClient->getRegistryStorageAdapter()->flushRedis(); } public function testPushesCounterMetric(): void { - // todo: clear before + $jobName = 'my_custom_service_job'; + $instanceName = '127.0.0.1:9000'; + $metricNamespace = 'test'; + $metricName = 'some_counter'; + + $counter = $this->pushGatewayClient->getRegistry()->registerCounter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + $this->pushGatewayClient->push($jobName, $instanceName); + + sleep(3); + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + + $results = $this->prometheusClient->query([ + 'query' => $metricFullName, + ]); + + $this->assertCount(1, $results); + $this->assertEquals([ + '__name__' => $metricFullName, + 'instance' => $instanceName, + 'job' => $jobName, + 'type' => 'blue', + ], $results[0]['metric']); + $this->assertEquals(5, $results[0]['value'][1]); + } + + public function testPushesCounterMetricAndIncreases(): void + { $jobName = 'my_custom_service_job'; $instanceName = '127.0.0.1:9000'; $metricNamespace = 'test'; - $metricName = 'some_counter_' . substr(md5(mt_rand()), -10); + $metricName = 'some_counter_2'; $counter = $this->pushGatewayClient->getRegistry()->registerCounter( $metricNamespace, @@ -52,7 +84,13 @@ public function testPushesCounterMetric(): void ['type'] ); $counter->incBy(5, ['blue']); + $this->pushGatewayClient->push($jobName, $instanceName); + $counter = $this->pushGatewayClient->getRegistry()->getCounter( + $metricNamespace, + $metricName + ); + $counter->inc(['blue']); $this->pushGatewayClient->push($jobName, $instanceName); sleep(3); @@ -70,6 +108,6 @@ public function testPushesCounterMetric(): void 'job' => $jobName, 'type' => 'blue', ], $results[0]['metric']); - $this->assertEquals(5, $results[0]['value'][1]); + $this->assertEquals(6, $results[0]['value'][1]); } } \ No newline at end of file From 425b7e038d215fe10149f3f33b370f7069a2ef80 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 14:43:51 +0200 Subject: [PATCH 22/83] update PushGatewayClient --- .../Services/PushGatewayClient.php | 52 +++++++++---------- tests/Integration/PrometheusPushTest.php | 11 ++++ 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index f23e376..921601e 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -41,36 +41,32 @@ public function push(string $jobName, string $instanceName): void $this->pushGateway->push($this->registry, $jobName, [ 'instance' => $instanceName, ]); - -// $this->registryStorageAdapter->flushRedis(); - } - - /** - * @param string $jobName - * @param string $instanceName - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\StorageException - */ - public function pushAdd(string $jobName, string $instanceName): void - { - $this->pushGateway->pushAdd($this->registry, $jobName, [ - 'instance' => $instanceName, - ]); - -// $this->registryStorageAdapter->flushRedis(); } - /** - * @param string $jobName - * @param string $instanceName - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function delete(string $jobName, string $instanceName): void - { - $this->pushGateway->delete($jobName, [ - 'instance' => $instanceName, - ]); - } +// /** +// * @param string $jobName +// * @param string $instanceName +// * @throws \GuzzleHttp\Exception\GuzzleException +// * @throws \Prometheus\Exception\StorageException +// */ +// public function pushAdd(string $jobName, string $instanceName): void +// { +// $this->pushGateway->pushAdd($this->registry, $jobName, [ +// 'instance' => $instanceName, +// ]); +// } +// +// /** +// * @param string $jobName +// * @param string $instanceName +// * @throws \GuzzleHttp\Exception\GuzzleException +// */ +// public function delete(string $jobName, string $instanceName): void +// { +// $this->pushGateway->delete($jobName, [ +// 'instance' => $instanceName, +// ]); +// } public function getRegistry(): CollectorRegistry { diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index 1e7bbb6..3a907ef 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -36,6 +36,11 @@ public function setUp(): void $this->pushGatewayClient->getRegistryStorageAdapter()->flushRedis(); } + /** + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws \Prometheus\Exception\StorageException + */ public function testPushesCounterMetric(): void { $jobName = 'my_custom_service_job'; @@ -70,6 +75,12 @@ public function testPushesCounterMetric(): void $this->assertEquals(5, $results[0]['value'][1]); } + /** + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\MetricNotFoundException + * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws \Prometheus\Exception\StorageException + */ public function testPushesCounterMetricAndIncreases(): void { $jobName = 'my_custom_service_job'; From 30f372f50c689924e565af820f4ed6a8a2ae564f Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 14:53:48 +0200 Subject: [PATCH 23/83] update PrometheusPushTest; populate PrometheusPushCommand --- .../Command/PrometheusPushCommand.php | 23 +++++++++++++------ .../Factory/GuzzleHttpClientFactory.php | 4 ++-- .../Resources/config/services.yml | 11 ++++++++- tests/Integration/PrometheusPushTest.php | 19 +++++++++------ 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php index d9b8500..efa0d47 100644 --- a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php +++ b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php @@ -10,15 +10,22 @@ class PrometheusPushCommand extends Command { /** @var PushGatewayClient */ - private $prometheusMetricPublisher; + private $pushGatewayClient; + + /** @var string */ + private $prometheusJobName; + + /** @var string */ + private $prometheusInstanceName; /** - * @param PushGatewayClient $prometheusMetricPublisher * @codeCoverageIgnore */ - public function __construct(PushGatewayClient $prometheusMetricPublisher) + public function __construct(PushGatewayClient $pushGatewayClient, string $prometheusJobName, string $prometheusInstanceName) { - $this->prometheusMetricPublisher = $prometheusMetricPublisher; + $this->pushGatewayClient = $pushGatewayClient; + $this->prometheusJobName = $prometheusJobName; + $this->prometheusInstanceName = $prometheusInstanceName; parent::__construct(); } @@ -27,14 +34,16 @@ public function configure(): void { $this ->setName('comsave:prometheus:push') - ->setDescription(''); + ->setDescription('Pushes scheduled metris from PushGateway to Prometheus.'); } protected function execute(InputInterface $input, OutputInterface $output) { - $this->prometheusMetricPublisher->publish(); + $output->writeln('Pushing metrics...'); + + $this->pushGatewayClient->push($this->prometheusJobName, $this->prometheusInstanceName); - $output->writeln('Metrics sent.'); + $output->writeln('Done.'); return 0; } diff --git a/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php b/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php index 0802306..4dcf291 100644 --- a/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php +++ b/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php @@ -6,8 +6,8 @@ class GuzzleHttpClientFactory { - public static function build(): Client + public static function build(array $options = []): Client { - return new Client(); + return new Client($options); } } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index 1b3b2cd..b7b5669 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -1,6 +1,8 @@ parameters: morty_counts_prometheus_url: '' morty_counts_pushgateway_url: '' + morty_counts_prometheus_instance: '' + morty_counts_prometheus_job: '' morty_counts_redis_host: '' morty_counts_redis_port: '' @@ -35,4 +37,11 @@ services: Comsave\MortyCountsBundle\Services\PrometheusClient: autowire: true arguments: - $prometheusUrl: '%morty_counts_prometheus_url%' \ No newline at end of file + $prometheusUrl: '%morty_counts_prometheus_url%' + + Comsave\MortyCountsBundle\Command\PrometheusPushCommand: + autowire: true + autoconfigure: true + arguments: + $prometheusJobName: '%morty_counts_prometheus_job%' + $prometheusInstanceName: '%morty_counts_prometheus_instance%' diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index 3a907ef..69b90f3 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -18,8 +18,17 @@ class PrometheusPushTest extends TestCase /** @var PushGatewayClient */ private $pushGatewayClient; + /** @var string */ + private $jobName; + + /** @var string */ + private $instanceName; + public function setUp(): void { + $jobName = 'my_custom_service_job'; + $instanceName = '127.0.0.1:9000'; + $this->prometheusClient = new PrometheusClient( 'prometheus:9090', GuzzleHttpClientFactory::build() @@ -43,8 +52,6 @@ public function setUp(): void */ public function testPushesCounterMetric(): void { - $jobName = 'my_custom_service_job'; - $instanceName = '127.0.0.1:9000'; $metricNamespace = 'test'; $metricName = 'some_counter'; @@ -55,7 +62,7 @@ public function testPushesCounterMetric(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push($jobName, $instanceName); + $this->pushGatewayClient->push($this->jobName, $this->instanceName); sleep(3); @@ -83,8 +90,6 @@ public function testPushesCounterMetric(): void */ public function testPushesCounterMetricAndIncreases(): void { - $jobName = 'my_custom_service_job'; - $instanceName = '127.0.0.1:9000'; $metricNamespace = 'test'; $metricName = 'some_counter_2'; @@ -95,14 +100,14 @@ public function testPushesCounterMetricAndIncreases(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push($jobName, $instanceName); + $this->pushGatewayClient->push($this->jobName, $this->instanceName); $counter = $this->pushGatewayClient->getRegistry()->getCounter( $metricNamespace, $metricName ); $counter->inc(['blue']); - $this->pushGatewayClient->push($jobName, $instanceName); + $this->pushGatewayClient->push($this->jobName, $this->instanceName); sleep(3); From ac5c7bec54396e4cb7a86696f17a21d2e677d33e Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 14:55:54 +0200 Subject: [PATCH 24/83] update PrometheusPushTest --- tests/Integration/PrometheusPushTest.php | 33 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index 69b90f3..a0b5296 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -19,16 +19,13 @@ class PrometheusPushTest extends TestCase private $pushGatewayClient; /** @var string */ - private $jobName; + private $jobName = 'my_custom_service_job'; /** @var string */ - private $instanceName; + private $instanceName = '127.0.0.1:9000'; public function setUp(): void { - $jobName = 'my_custom_service_job'; - $instanceName = '127.0.0.1:9000'; - $this->prometheusClient = new PrometheusClient( 'prometheus:9090', GuzzleHttpClientFactory::build() @@ -75,8 +72,8 @@ public function testPushesCounterMetric(): void $this->assertCount(1, $results); $this->assertEquals([ '__name__' => $metricFullName, - 'instance' => $instanceName, - 'job' => $jobName, + 'instance' => $this->instanceName, + 'job' => $this->jobName, 'type' => 'blue', ], $results[0]['metric']); $this->assertEquals(5, $results[0]['value'][1]); @@ -92,6 +89,7 @@ public function testPushesCounterMetricAndIncreases(): void { $metricNamespace = 'test'; $metricName = 'some_counter_2'; + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $counter = $this->pushGatewayClient->getRegistry()->registerCounter( $metricNamespace, @@ -102,6 +100,21 @@ public function testPushesCounterMetricAndIncreases(): void $counter->incBy(5, ['blue']); $this->pushGatewayClient->push($this->jobName, $this->instanceName); + sleep(3); + + $results = $this->prometheusClient->query([ + 'query' => $metricFullName, + ]); + + $this->assertCount(1, $results); + $this->assertEquals([ + '__name__' => $metricFullName, + 'instance' => $this->instanceName, + 'job' => $this->jobName, + 'type' => 'blue', + ], $results[0]['metric']); + $this->assertEquals(5, $results[0]['value'][1]); + $counter = $this->pushGatewayClient->getRegistry()->getCounter( $metricNamespace, $metricName @@ -111,8 +124,6 @@ public function testPushesCounterMetricAndIncreases(): void sleep(3); - $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $results = $this->prometheusClient->query([ 'query' => $metricFullName, ]); @@ -120,8 +131,8 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertCount(1, $results); $this->assertEquals([ '__name__' => $metricFullName, - 'instance' => $instanceName, - 'job' => $jobName, + 'instance' => $this->instanceName, + 'job' => $this->jobName, 'type' => 'blue', ], $results[0]['metric']); $this->assertEquals(6, $results[0]['value'][1]); From 35b04ebdb2e3cad5b9161e760182a59f7e52c148 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 14:59:42 +0200 Subject: [PATCH 25/83] update services config --- .../MortyCountsBundle/Resources/config/services.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index b7b5669..cd1522c 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -1,10 +1,10 @@ parameters: - morty_counts_prometheus_url: '' - morty_counts_pushgateway_url: '' - morty_counts_prometheus_instance: '' - morty_counts_prometheus_job: '' - morty_counts_redis_host: '' - morty_counts_redis_port: '' + morty_counts_prometheus_url: 'prometheus:9090' + morty_counts_pushgateway_url: 'pushgateway:9191' + morty_counts_prometheus_instance: 'my_custom_push_service_host' + morty_counts_prometheus_job: 'my_custom_push_job' + morty_counts_redis_host: 'redis' + morty_counts_redis_port: 6379 services: _defaults: From 2e9a343b051e0e729e224bc13da3d7ef20270908 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 16:30:57 +0200 Subject: [PATCH 26/83] add serializer for prometheus responses --- composer.json | 3 +- .../Command/PrometheusPushCommand.php | 18 ++--- .../Factory/JmsSerializerFactory.php | 22 ++++++ .../Model/PrometheusMetric.php | 76 +++++++++++++++++++ .../Model/PrometheusResponse.php | 40 ++++++++++ .../Model/PrometheusResponseData.php | 40 ++++++++++ .../Model/PrometheusResponseDataResult.php | 46 +++++++++++ .../Resources/config/services.yml | 10 +-- .../Services/PrometheusClient.php | 16 ++-- .../Services/PushGatewayClient.php | 52 +++++-------- tests/Integration/PrometheusPushTest.php | 52 ++++++------- tests/Unit/MetricSerializerTest.php | 60 +++++++++++++++ 12 files changed, 352 insertions(+), 83 deletions(-) create mode 100644 src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php create mode 100644 src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php create mode 100644 src/Comsave/MortyCountsBundle/Model/PrometheusResponse.php create mode 100644 src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php create mode 100644 src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php create mode 100644 tests/Unit/MetricSerializerTest.php diff --git a/composer.json b/composer.json index 865ffbd..296b836 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,8 @@ "ext-redis": "*", "endclothing/prometheus_client_php": "^1.0", "symfony/http-kernel": "^3.4|^4.4", - "symfony/console": "^3.4|^4.4" + "symfony/console": "^3.4|^4.4", + "jms/serializer": "^3.6" }, "require-dev": { "phpunit/phpunit": "^9.1" diff --git a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php index efa0d47..3d97794 100644 --- a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php +++ b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php @@ -12,20 +12,12 @@ class PrometheusPushCommand extends Command /** @var PushGatewayClient */ private $pushGatewayClient; - /** @var string */ - private $prometheusJobName; - - /** @var string */ - private $prometheusInstanceName; - /** * @codeCoverageIgnore */ - public function __construct(PushGatewayClient $pushGatewayClient, string $prometheusJobName, string $prometheusInstanceName) + public function __construct(PushGatewayClient $pushGatewayClient) { $this->pushGatewayClient = $pushGatewayClient; - $this->prometheusJobName = $prometheusJobName; - $this->prometheusInstanceName = $prometheusInstanceName; parent::__construct(); } @@ -37,11 +29,15 @@ public function configure(): void ->setDescription('Pushes scheduled metris from PushGateway to Prometheus.'); } - protected function execute(InputInterface $input, OutputInterface $output) + /** + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\StorageException + */ + protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('Pushing metrics...'); - $this->pushGatewayClient->push($this->prometheusJobName, $this->prometheusInstanceName); + $this->pushGatewayClient->push(); $output->writeln('Done.'); diff --git a/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php b/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php new file mode 100644 index 0000000..d75d2d6 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php @@ -0,0 +1,22 @@ +setPropertyNamingStrategy( + new SerializedNameAnnotationStrategy( + new IdenticalPropertyNamingStrategy() + ) + ) + ->build(); + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php b/src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php new file mode 100644 index 0000000..0e2a62f --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php @@ -0,0 +1,76 @@ +name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getInstance(): string + { + return $this->instance; + } + + public function setInstance(string $instance): void + { + $this->instance = $instance; + } + + public function getJob(): string + { + return $this->job; + } + + public function setJob(string $job): void + { + $this->job = $job; + } + + public function getType(): string + { + return $this->type; + } + + public function setType(string $type): void + { + $this->type = $type; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponse.php b/src/Comsave/MortyCountsBundle/Model/PrometheusResponse.php new file mode 100644 index 0000000..69edb34 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Model/PrometheusResponse.php @@ -0,0 +1,40 @@ +status; + } + + public function setStatus(string $status): void + { + $this->status = $status; + } + + public function getData(): PrometheusResponseData + { + return $this->data; + } + + public function setData(PrometheusResponseData $data): void + { + $this->data = $data; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php new file mode 100644 index 0000000..7555c7a --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php @@ -0,0 +1,40 @@ +") + */ + private $result; + + public function getResultType(): string + { + return $this->resultType; + } + + public function setResultType(string $resultType): void + { + $this->resultType = $resultType; + } + + public function getResult(): array + { + return $this->result; + } + + public function setResult(array $result): void + { + $this->result = $result; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php new file mode 100644 index 0000000..fbf92f2 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php @@ -0,0 +1,46 @@ +metric; + } + + public function setMetric(PrometheusMetric $metric): void + { + $this->metric = $metric; + } + + public function getValues(): array + { + return $this->values; + } + + public function setValues(array $values): void + { + $this->values = $values; + } + + public function getValue(): string + { + return $this->getValues()[1]; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index cd1522c..c1e5664 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -34,14 +34,12 @@ services: GuzzleHttp\Client: factory: ['@Comsave\MortyCountsBundle\GuzzleHttpClientFactory', 'build'] + JMS\Serializer\Serializer: + factory: ['@Comsave\MortyCountsBundle\JmsSerializerFactory', 'build'] + Comsave\MortyCountsBundle\Services\PrometheusClient: autowire: true arguments: $prometheusUrl: '%morty_counts_prometheus_url%' - - Comsave\MortyCountsBundle\Command\PrometheusPushCommand: - autowire: true - autoconfigure: true - arguments: $prometheusJobName: '%morty_counts_prometheus_job%' - $prometheusInstanceName: '%morty_counts_prometheus_instance%' + $prometheusInstanceName: '%morty_counts_prometheus_instance%' \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php index bfb6f90..b749e44 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php @@ -2,36 +2,42 @@ namespace Comsave\MortyCountsBundle\Services; +use Comsave\MortyCountsBundle\Model\PrometheusMetric; +use Comsave\MortyCountsBundle\Model\PrometheusResponse; use GuzzleHttp\ClientInterface; +use JMS\Serializer\Serializer; class PrometheusClient { /** @var string */ private $prometheusUrl; + /** @var Serializer */ + private $jmsSerializer; + /** @var ClientInterface */ private $httpClient; /** * @param string $prometheusUrl + * @param Serializer $jmsSerializer * @param ClientInterface $httpClient * @codeCoverageIgnore */ - public function __construct(string $prometheusUrl, ClientInterface $httpClient) + public function __construct(string $prometheusUrl, Serializer $jmsSerializer, ClientInterface $httpClient) { $this->prometheusUrl = $prometheusUrl; + $this->jmsSerializer = $jmsSerializer; $this->httpClient = $httpClient; } - public function query(array $arguments): array + public function query(array $arguments): PrometheusResponse { $response = $this->httpClient->request('GET', vsprintf('%s/api/v1/query?%s', [ $this->prometheusUrl, http_build_query($arguments) ])); - $responseJson = json_decode((string)$response->getBody(), true); - - return $responseJson['data']['result']; + return $this->jmsSerializer->deserialize((string)$response->getBody(), PrometheusResponse::class, 'json'); } } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index 921601e..dbcce82 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -17,57 +17,45 @@ class PushGatewayClient /** @var PushGateway */ private $pushGateway; + /** @var string */ + private $prometheusJobName; + + /** @var string */ + private $prometheusInstanceName; + /** * @param CollectorRegistry $registry * @param Redis $registryStorageAdapter * @param PushGateway $pushGateway + * @param string $prometheusJobName + * @param string $prometheusInstanceName * @codeCoverageIgnore */ - public function __construct(CollectorRegistry $registry, Redis $registryStorageAdapter, PushGateway $pushGateway) - { + public function __construct( + CollectorRegistry $registry, + Redis $registryStorageAdapter, + PushGateway $pushGateway, + string $prometheusJobName, + string $prometheusInstanceName + ) { $this->registry = $registry; $this->registryStorageAdapter = $registryStorageAdapter; $this->pushGateway = $pushGateway; + $this->prometheusJobName = $prometheusJobName; + $this->prometheusInstanceName = $prometheusInstanceName; } /** - * @param string $jobName - * @param string $instanceName * @throws \GuzzleHttp\Exception\GuzzleException * @throws \Prometheus\Exception\StorageException */ - public function push(string $jobName, string $instanceName): void + public function push(): void { - $this->pushGateway->push($this->registry, $jobName, [ - 'instance' => $instanceName, + $this->pushGateway->push($this->registry, $this->prometheusJobName, [ + 'instance' => $this->prometheusInstanceName, ]); } -// /** -// * @param string $jobName -// * @param string $instanceName -// * @throws \GuzzleHttp\Exception\GuzzleException -// * @throws \Prometheus\Exception\StorageException -// */ -// public function pushAdd(string $jobName, string $instanceName): void -// { -// $this->pushGateway->pushAdd($this->registry, $jobName, [ -// 'instance' => $instanceName, -// ]); -// } -// -// /** -// * @param string $jobName -// * @param string $instanceName -// * @throws \GuzzleHttp\Exception\GuzzleException -// */ -// public function delete(string $jobName, string $instanceName): void -// { -// $this->pushGateway->delete($jobName, [ -// 'instance' => $instanceName, -// ]); -// } - public function getRegistry(): CollectorRegistry { return $this->registry; diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index a0b5296..d17c557 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -3,6 +3,7 @@ namespace Comsave\Tests\Integration; use Comsave\MortyCountsBundle\Factory\GuzzleHttpClientFactory; +use Comsave\MortyCountsBundle\Factory\JmsSerializerFactory; use Comsave\MortyCountsBundle\Factory\PushGatewayFactory; use Comsave\MortyCountsBundle\Factory\RedisStorageAdapterFactory; use Comsave\MortyCountsBundle\Services\PrometheusClient; @@ -28,6 +29,7 @@ public function setUp(): void { $this->prometheusClient = new PrometheusClient( 'prometheus:9090', + JmsSerializerFactory::build(), GuzzleHttpClientFactory::build() ); @@ -37,7 +39,9 @@ public function setUp(): void $this->pushGatewayClient = new PushGatewayClient( $registry, $registryStorageAdapter, - PushGatewayFactory::build('pushgateway:9191') + PushGatewayFactory::build('pushgateway:9191'), + $this->jobName, + $this->instanceName ); $this->pushGatewayClient->getRegistryStorageAdapter()->flushRedis(); } @@ -59,24 +63,21 @@ public function testPushesCounterMetric(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push($this->jobName, $this->instanceName); + $this->pushGatewayClient->push(); sleep(3); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $results = $this->prometheusClient->query([ + $response = $this->prometheusClient->query([ 'query' => $metricFullName, ]); + $results = $response->getData()->getResult(); $this->assertCount(1, $results); - $this->assertEquals([ - '__name__' => $metricFullName, - 'instance' => $this->instanceName, - 'job' => $this->jobName, - 'type' => 'blue', - ], $results[0]['metric']); - $this->assertEquals(5, $results[0]['value'][1]); + $this->assertEquals($metricFullName, $results[0]->getMetric()->getName()); + $this->assertEquals('blue', $results[0]->getMetric()->getType()); + $this->assertEquals(5, $results[0]->getValue()); } /** @@ -91,6 +92,7 @@ public function testPushesCounterMetricAndIncreases(): void $metricName = 'some_counter_2'; $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + // todo: integrate initial (last) value fetch for the counter $counter = $this->pushGatewayClient->getRegistry()->registerCounter( $metricNamespace, $metricName, @@ -98,43 +100,37 @@ public function testPushesCounterMetricAndIncreases(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push($this->jobName, $this->instanceName); + $this->pushGatewayClient->push(); sleep(3); - $results = $this->prometheusClient->query([ + $response = $this->prometheusClient->query([ 'query' => $metricFullName, ]); + $results = $response->getData()->getResult(); $this->assertCount(1, $results); - $this->assertEquals([ - '__name__' => $metricFullName, - 'instance' => $this->instanceName, - 'job' => $this->jobName, - 'type' => 'blue', - ], $results[0]['metric']); - $this->assertEquals(5, $results[0]['value'][1]); + $this->assertEquals($metricFullName, $results[0]->getMetric()->getName()); + $this->assertEquals('blue', $results[0]->getMetric()->getType()); + $this->assertEquals(5, $results[0]->getValue()); $counter = $this->pushGatewayClient->getRegistry()->getCounter( $metricNamespace, $metricName ); $counter->inc(['blue']); - $this->pushGatewayClient->push($this->jobName, $this->instanceName); + $this->pushGatewayClient->push(); sleep(3); - $results = $this->prometheusClient->query([ + $response = $this->prometheusClient->query([ 'query' => $metricFullName, ]); + $results = $response->getData()->getResult(); $this->assertCount(1, $results); - $this->assertEquals([ - '__name__' => $metricFullName, - 'instance' => $this->instanceName, - 'job' => $this->jobName, - 'type' => 'blue', - ], $results[0]['metric']); - $this->assertEquals(6, $results[0]['value'][1]); + $this->assertEquals($metricFullName, $results[0]->getMetric()->getName()); + $this->assertEquals('blue', $results[0]->getMetric()->getType()); + $this->assertEquals(6, $results[0]->getValue()); } } \ No newline at end of file diff --git a/tests/Unit/MetricSerializerTest.php b/tests/Unit/MetricSerializerTest.php new file mode 100644 index 0000000..403b009 --- /dev/null +++ b/tests/Unit/MetricSerializerTest.php @@ -0,0 +1,60 @@ +jmsSerializer = JmsSerializerFactory::build(); + } + + public function testDeserializesCorrectly(): void + { + $responseJson = '{ + "status": "success", + "data": { + "resultType": "vector", + "result": [ + { + "metric": { + "__name__": "test_some_counter", + "instance": "127.0.0.1:9000", + "job": "my_custom_service_job", + "type": "blue" + }, + "value": [ + 1587564299.903, + "5" + ] + } + ] + } +}'; + + $metricStub = new PrometheusMetric(); + $metricStub->setJob('my_custom_service_job'); + $metricStub->setInstance('127.0.0.1:9000'); + $metricStub->setName('test_some_counter'); + $metricStub->setType('blue'); + + /** @var PrometheusResponse $prometheusResponse */ + $prometheusResponse = $this->jmsSerializer->deserialize($responseJson, PrometheusResponse::class, 'json'); + /** @var PrometheusResponseDataResult $prometheusDataResult */ + $prometheusDataResult = $prometheusResponse->getData()->getResult()[0]; + + $this->assertEquals($metricStub, $prometheusDataResult->getMetric()); + $this->assertEquals(5, $prometheusDataResult->getValue()); + } +} \ No newline at end of file From 38f79d5f8a418a74f09adb5952f6f38066bcb214 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 16:32:34 +0200 Subject: [PATCH 27/83] add composer description --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 296b836..1aafea7 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "comsave/morty-counts", + "description": "Symfony integration to push Prometheus metrics", "license": "MIT", "require": { "ext-redis": "*", From 224a4f309e90ee348f108b9d2c55d10217a01a70 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 16:44:58 +0200 Subject: [PATCH 28/83] update PrometheusClient to use POST to avoid query string limits --- .../MortyCountsBundle/Services/PrometheusClient.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php index b749e44..5ddb495 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php @@ -33,10 +33,9 @@ public function __construct(string $prometheusUrl, Serializer $jmsSerializer, Cl public function query(array $arguments): PrometheusResponse { - $response = $this->httpClient->request('GET', vsprintf('%s/api/v1/query?%s', [ - $this->prometheusUrl, - http_build_query($arguments) - ])); + $response = $this->httpClient->request('POST', sprintf('%s/api/v1/query', $this->prometheusUrl), [ + 'form_params' => $arguments + ]); return $this->jmsSerializer->deserialize((string)$response->getBody(), PrometheusResponse::class, 'json'); } From 28e2ab2f7b81499db092940a762c9fd122022ca5 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 22 Apr 2020 16:45:47 +0200 Subject: [PATCH 29/83] simplify JmsSerializer --- .../MortyCountsBundle/Factory/JmsSerializerFactory.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php b/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php index d75d2d6..6555887 100644 --- a/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php +++ b/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php @@ -2,8 +2,6 @@ namespace Comsave\MortyCountsBundle\Factory; -use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; -use JMS\Serializer\Naming\SerializedNameAnnotationStrategy; use JMS\Serializer\Serializer; use JMS\Serializer\SerializerBuilder; @@ -11,12 +9,6 @@ class JmsSerializerFactory { public static function build(): Serializer { - return SerializerBuilder::create() - ->setPropertyNamingStrategy( - new SerializedNameAnnotationStrategy( - new IdenticalPropertyNamingStrategy() - ) - ) - ->build(); + return SerializerBuilder::create()->build(); } } \ No newline at end of file From 216a46dc30746cca302555b9e635df920b8a56ea Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 10:58:54 +0200 Subject: [PATCH 30/83] prometheus response serializer update --- docker-compose.yml | 3 ++ .../Command/PrometheusPushCommand.php | 1 + .../Model/PrometheusResponseData.php | 11 +++--- .../Model/PrometheusResponseDataResult.php | 8 ++--- .../Services/PrometheusClient.php | 3 +- .../Services/PushGatewayClient.php | 34 +++++++++++++++++++ tests/Integration/PrometheusPushTest.php | 21 ++++++------ tests/Unit/MetricSerializerTest.php | 18 +++++----- 8 files changed, 69 insertions(+), 30 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6eb4689..798eeff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,8 @@ services: command: - '--web.listen-address=:9090' - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.console.templates=/etc/prometheus/consoles' + - '--web.console.libraries=/etc/prometheus/console_libraries' depends_on: - pushgateway ports: @@ -30,6 +32,7 @@ services: command: - '--web.listen-address=:9191' - '--push.disable-consistency-check' + - '--persistence.interval=5m' ports: - 9191:9191 diff --git a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php index 3d97794..4c0607a 100644 --- a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php +++ b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php @@ -38,6 +38,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln('Pushing metrics...'); $this->pushGatewayClient->push(); + $this->pushGatewayClient->flush(); $output->writeln('Done.'); diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php index 7555c7a..c9a202a 100644 --- a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php +++ b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php @@ -14,9 +14,10 @@ class PrometheusResponseData /** * @var array|PrometheusResponseDataResult[] + * @JMS\SerializedName("result") * @JMS\Type("array") */ - private $result; + private $results; public function getResultType(): string { @@ -28,13 +29,13 @@ public function setResultType(string $resultType): void $this->resultType = $resultType; } - public function getResult(): array + public function getResults(): array { - return $this->result; + return $this->results; } - public function setResult(array $result): void + public function setResults(array $results): void { - $this->result = $result; + $this->results = $results; } } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php index fbf92f2..2c77722 100644 --- a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php +++ b/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php @@ -7,8 +7,8 @@ class PrometheusResponseDataResult { /** - * @var PrometheusMetric - * @JMS\Type("Comsave\MortyCountsBundle\Model\PrometheusMetric") + * @var array + * @JMS\Type("array") */ private $metric; @@ -19,12 +19,12 @@ class PrometheusResponseDataResult */ private $values; - public function getMetric(): PrometheusMetric + public function getMetric(): array { return $this->metric; } - public function setMetric(PrometheusMetric $metric): void + public function setMetric(array $metric): void { $this->metric = $metric; } diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php index 5ddb495..c03c7f1 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php @@ -2,7 +2,6 @@ namespace Comsave\MortyCountsBundle\Services; -use Comsave\MortyCountsBundle\Model\PrometheusMetric; use Comsave\MortyCountsBundle\Model\PrometheusResponse; use GuzzleHttp\ClientInterface; use JMS\Serializer\Serializer; @@ -29,6 +28,8 @@ public function __construct(string $prometheusUrl, Serializer $jmsSerializer, Cl $this->prometheusUrl = $prometheusUrl; $this->jmsSerializer = $jmsSerializer; $this->httpClient = $httpClient; + + // todo: move this out to a separate repo later } public function query(array $arguments): PrometheusResponse diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index dbcce82..d0755e1 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -3,6 +3,9 @@ namespace Comsave\MortyCountsBundle\Services; use Prometheus\CollectorRegistry; +use Prometheus\Counter; +use Prometheus\Gauge; +use Prometheus\Histogram; use Prometheus\PushGateway; use Prometheus\Storage\Redis; @@ -56,6 +59,37 @@ public function push(): void ]); } + /** + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\StorageException + */ + public function pushAdd(): void + { + $this->pushGateway->pushAdd($this->registry, $this->prometheusJobName, [ + 'instance' => $this->prometheusInstanceName, + ]); + } + + public function counter(): Counter + { + } + + public function gauge(): Gauge + { + } + + public function histogram(): Histogram + { + } + + /** + * @throws \Prometheus\Exception\StorageException + */ + public function flush(): void + { + $this->registryStorageAdapter->flushRedis(); + } + public function getRegistry(): CollectorRegistry { return $this->registry; diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index d17c557..c8b2537 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -72,11 +72,11 @@ public function testPushesCounterMetric(): void $response = $this->prometheusClient->query([ 'query' => $metricFullName, ]); - $results = $response->getData()->getResult(); + $results = $response->getData()->getResults(); $this->assertCount(1, $results); - $this->assertEquals($metricFullName, $results[0]->getMetric()->getName()); - $this->assertEquals('blue', $results[0]->getMetric()->getType()); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(5, $results[0]->getValue()); } @@ -92,7 +92,6 @@ public function testPushesCounterMetricAndIncreases(): void $metricName = 'some_counter_2'; $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - // todo: integrate initial (last) value fetch for the counter $counter = $this->pushGatewayClient->getRegistry()->registerCounter( $metricNamespace, $metricName, @@ -107,13 +106,15 @@ public function testPushesCounterMetricAndIncreases(): void $response = $this->prometheusClient->query([ 'query' => $metricFullName, ]); - $results = $response->getData()->getResult(); + $results = $response->getData()->getResults(); $this->assertCount(1, $results); - $this->assertEquals($metricFullName, $results[0]->getMetric()->getName()); - $this->assertEquals('blue', $results[0]->getMetric()->getType()); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(5, $results[0]->getValue()); + // todo: integrate initial (last) value fetch for the COUNTER + // todo: this should work even after clearing redis cache which should be done after every push $counter = $this->pushGatewayClient->getRegistry()->getCounter( $metricNamespace, $metricName @@ -126,11 +127,11 @@ public function testPushesCounterMetricAndIncreases(): void $response = $this->prometheusClient->query([ 'query' => $metricFullName, ]); - $results = $response->getData()->getResult(); + $results = $response->getData()->getResults(); $this->assertCount(1, $results); - $this->assertEquals($metricFullName, $results[0]->getMetric()->getName()); - $this->assertEquals('blue', $results[0]->getMetric()->getType()); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(6, $results[0]->getValue()); } } \ No newline at end of file diff --git a/tests/Unit/MetricSerializerTest.php b/tests/Unit/MetricSerializerTest.php index 403b009..66f1b25 100644 --- a/tests/Unit/MetricSerializerTest.php +++ b/tests/Unit/MetricSerializerTest.php @@ -5,7 +5,6 @@ use Comsave\MortyCountsBundle\Factory\JmsSerializerFactory; use Comsave\MortyCountsBundle\Model\PrometheusMetric; use Comsave\MortyCountsBundle\Model\PrometheusResponse; -use Comsave\MortyCountsBundle\Model\PrometheusResponseData; use Comsave\MortyCountsBundle\Model\PrometheusResponseDataResult; use JMS\Serializer\Serializer; use PHPUnit\Framework\TestCase; @@ -43,18 +42,17 @@ public function testDeserializesCorrectly(): void } }'; - $metricStub = new PrometheusMetric(); - $metricStub->setJob('my_custom_service_job'); - $metricStub->setInstance('127.0.0.1:9000'); - $metricStub->setName('test_some_counter'); - $metricStub->setType('blue'); - /** @var PrometheusResponse $prometheusResponse */ $prometheusResponse = $this->jmsSerializer->deserialize($responseJson, PrometheusResponse::class, 'json'); /** @var PrometheusResponseDataResult $prometheusDataResult */ - $prometheusDataResult = $prometheusResponse->getData()->getResult()[0]; - - $this->assertEquals($metricStub, $prometheusDataResult->getMetric()); + $prometheusDataResult = $prometheusResponse->getData()->getResults()[0]; + + $this->assertEquals([ + '__name__' => 'test_some_counter', + 'instance' => '127.0.0.1:9000', + 'job' => 'my_custom_service_job', + 'type' => 'blue' + ], $prometheusDataResult->getMetric()); $this->assertEquals(5, $prometheusDataResult->getValue()); } } \ No newline at end of file From 24e972cea6dbe0e631bc0e73bc607fc47e34ab77 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 10:59:19 +0200 Subject: [PATCH 31/83] --amend --- .../Model/PrometheusMetric.php | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php b/src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php deleted file mode 100644 index 0e2a62f..0000000 --- a/src/Comsave/MortyCountsBundle/Model/PrometheusMetric.php +++ /dev/null @@ -1,76 +0,0 @@ -name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function getInstance(): string - { - return $this->instance; - } - - public function setInstance(string $instance): void - { - $this->instance = $instance; - } - - public function getJob(): string - { - return $this->job; - } - - public function setJob(string $job): void - { - $this->job = $job; - } - - public function getType(): string - { - return $this->type; - } - - public function setType(string $type): void - { - $this->type = $type; - } -} \ No newline at end of file From 11bf48efe75075b736e6ddaf5ccd6270929a6fa3 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 11:06:54 +0200 Subject: [PATCH 32/83] include metric type methods in PushGatewayClient --- .../Services/PushGatewayClient.php | 34 +++++++++++++++++-- tests/Integration/PrometheusPushTest.php | 6 ++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index d0755e1..c5a654f 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -70,16 +70,44 @@ public function pushAdd(): void ]); } - public function counter(): Counter + /** + * @throws \Prometheus\Exception\MetricsRegistrationException + */ + public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter { + return $this->getRegistry()->getOrRegisterCounter( + $namespace, + $name, + $help, + $labels + ); } - public function gauge(): Gauge + /** + * @throws \Prometheus\Exception\MetricsRegistrationException + */ + public function gauge(string $namespace, string $name, ?string $help = null, array $labels = []): Gauge { + return $this->getRegistry()->getOrRegisterGauge( + $namespace, + $name, + $help, + $labels + ); } - public function histogram(): Histogram + /** + * @throws \Prometheus\Exception\MetricsRegistrationException + */ + public function histogram(string $namespace, string $name, ?string $help = null, array $labels = [], ?array $buckets = null): Histogram { + return $this->getRegistry()->getOrRegisterHistogram( + $namespace, + $name, + $help, + $labels, + $buckets + ); } /** diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index c8b2537..ae51b35 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -56,7 +56,7 @@ public function testPushesCounterMetric(): void $metricNamespace = 'test'; $metricName = 'some_counter'; - $counter = $this->pushGatewayClient->getRegistry()->registerCounter( + $counter = $this->pushGatewayClient->counter( $metricNamespace, $metricName, 'it increases', @@ -92,7 +92,7 @@ public function testPushesCounterMetricAndIncreases(): void $metricName = 'some_counter_2'; $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $counter = $this->pushGatewayClient->getRegistry()->registerCounter( + $counter = $this->pushGatewayClient->counter( $metricNamespace, $metricName, 'it increases', @@ -115,7 +115,7 @@ public function testPushesCounterMetricAndIncreases(): void // todo: integrate initial (last) value fetch for the COUNTER // todo: this should work even after clearing redis cache which should be done after every push - $counter = $this->pushGatewayClient->getRegistry()->getCounter( + $counter = $this->pushGatewayClient->counter( $metricNamespace, $metricName ); From 3356bfe0cf0fe122f436f7538573b39282fdbea9 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 11:07:46 +0200 Subject: [PATCH 33/83] --amend --- .../Services/PushGatewayClient.php | 16 +++------------- tests/Integration/PrometheusPushTest.php | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index c5a654f..87624dd 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -75,7 +75,7 @@ public function pushAdd(): void */ public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter { - return $this->getRegistry()->getOrRegisterCounter( + return $this->registry->getOrRegisterCounter( $namespace, $name, $help, @@ -88,7 +88,7 @@ public function counter(string $namespace, string $name, ?string $help = null, a */ public function gauge(string $namespace, string $name, ?string $help = null, array $labels = []): Gauge { - return $this->getRegistry()->getOrRegisterGauge( + return $this->registry->getOrRegisterGauge( $namespace, $name, $help, @@ -101,7 +101,7 @@ public function gauge(string $namespace, string $name, ?string $help = null, arr */ public function histogram(string $namespace, string $name, ?string $help = null, array $labels = [], ?array $buckets = null): Histogram { - return $this->getRegistry()->getOrRegisterHistogram( + return $this->registry->getOrRegisterHistogram( $namespace, $name, $help, @@ -117,14 +117,4 @@ public function flush(): void { $this->registryStorageAdapter->flushRedis(); } - - public function getRegistry(): CollectorRegistry - { - return $this->registry; - } - - public function getRegistryStorageAdapter(): Redis - { - return $this->registryStorageAdapter; - } } \ No newline at end of file diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index ae51b35..6051359 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -43,7 +43,7 @@ public function setUp(): void $this->jobName, $this->instanceName ); - $this->pushGatewayClient->getRegistryStorageAdapter()->flushRedis(); + $this->pushGatewayClient->flush(); } /** From aef318890f0fe4b8b04f82c21050113d14f8e25c Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 11:07:46 +0200 Subject: [PATCH 34/83] --amend --- .../Services/PushGatewayClient.php | 16 +++------------- tests/Integration/PrometheusPushTest.php | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index c5a654f..87624dd 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -75,7 +75,7 @@ public function pushAdd(): void */ public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter { - return $this->getRegistry()->getOrRegisterCounter( + return $this->registry->getOrRegisterCounter( $namespace, $name, $help, @@ -88,7 +88,7 @@ public function counter(string $namespace, string $name, ?string $help = null, a */ public function gauge(string $namespace, string $name, ?string $help = null, array $labels = []): Gauge { - return $this->getRegistry()->getOrRegisterGauge( + return $this->registry->getOrRegisterGauge( $namespace, $name, $help, @@ -101,7 +101,7 @@ public function gauge(string $namespace, string $name, ?string $help = null, arr */ public function histogram(string $namespace, string $name, ?string $help = null, array $labels = [], ?array $buckets = null): Histogram { - return $this->getRegistry()->getOrRegisterHistogram( + return $this->registry->getOrRegisterHistogram( $namespace, $name, $help, @@ -117,14 +117,4 @@ public function flush(): void { $this->registryStorageAdapter->flushRedis(); } - - public function getRegistry(): CollectorRegistry - { - return $this->registry; - } - - public function getRegistryStorageAdapter(): Redis - { - return $this->registryStorageAdapter; - } } \ No newline at end of file diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index ae51b35..6051359 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -43,7 +43,7 @@ public function setUp(): void $this->jobName, $this->instanceName ); - $this->pushGatewayClient->getRegistryStorageAdapter()->flushRedis(); + $this->pushGatewayClient->flush(); } /** From ca57d38a2c368d92ab96a2b82e8661de10fab4c7 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 11:11:26 +0200 Subject: [PATCH 35/83] update PrometheusPushTest --- tests/Integration/PrometheusPushTest.php | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index 6051359..55363bd 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -55,6 +55,7 @@ public function testPushesCounterMetric(): void { $metricNamespace = 'test'; $metricName = 'some_counter'; + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $counter = $this->pushGatewayClient->counter( $metricNamespace, @@ -65,14 +66,11 @@ public function testPushesCounterMetric(): void $counter->incBy(5, ['blue']); $this->pushGatewayClient->push(); - sleep(3); - - $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + sleep(3); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query([ + $results = $this->prometheusClient->query([ 'query' => $metricFullName, - ]); - $results = $response->getData()->getResults(); + ])->getData()->getResults(); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -101,12 +99,11 @@ public function testPushesCounterMetricAndIncreases(): void $counter->incBy(5, ['blue']); $this->pushGatewayClient->push(); - sleep(3); + sleep(3); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query([ + $results = $this->prometheusClient->query([ 'query' => $metricFullName, - ]); - $results = $response->getData()->getResults(); + ])->getData()->getResults(); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -122,12 +119,11 @@ public function testPushesCounterMetricAndIncreases(): void $counter->inc(['blue']); $this->pushGatewayClient->push(); - sleep(3); + sleep(3); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query([ + $results = $this->prometheusClient->query([ 'query' => $metricFullName, - ]); - $results = $response->getData()->getResults(); + ])->getData()->getResults(); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); From 36ac43ecdffec370e9052357ab3178f79429b376 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 14:25:32 +0200 Subject: [PATCH 36/83] move out usage of prometheus job name --- .../Command/PrometheusPushCommand.php | 22 ++++++-- .../DependencyInjection/.gitignore | 0 .../Factory/RedisStorageAdapterFactory.php | 13 +++-- .../Resources/config/services.yml | 18 ++++-- .../Services/PrometheusClient.php | 10 +++- .../Services/PushGatewayClient.php | 56 +++++++++++-------- tests/Integration/PrometheusPushTest.php | 7 +-- 7 files changed, 83 insertions(+), 43 deletions(-) create mode 100644 src/Comsave/MortyCountsBundle/DependencyInjection/.gitignore diff --git a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php index 4c0607a..6141f90 100644 --- a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php +++ b/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php @@ -3,6 +3,8 @@ namespace Comsave\MortyCountsBundle\Command; use Comsave\MortyCountsBundle\Services\PushGatewayClient; +use GuzzleHttp\Exception\GuzzleException; +use Prometheus\Exception\StorageException; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -12,12 +14,18 @@ class PrometheusPushCommand extends Command /** @var PushGatewayClient */ private $pushGatewayClient; + /** @var array */ + private $prometheusJobNames; + /** + * @param PushGatewayClient $pushGatewayClient + * @param array $prometheusJobNames * @codeCoverageIgnore */ - public function __construct(PushGatewayClient $pushGatewayClient) + public function __construct(PushGatewayClient $pushGatewayClient, array $prometheusJobNames) { $this->pushGatewayClient = $pushGatewayClient; + $this->prometheusJobNames = $prometheusJobNames; parent::__construct(); } @@ -30,15 +38,19 @@ public function configure(): void } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws StorageException */ protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('Pushing metrics...'); - $this->pushGatewayClient->push(); - $this->pushGatewayClient->flush(); + $this->pushGatewayClient->pushAll($this->prometheusJobNames); + $this->pushGatewayClient->flush(); // todo: check if no new values came in before flushing + + // todo: add never ending process option for supervisor, push every n seconds; + // todo: keep in mind the smaller the interval the more latency prometheus + // todo: will introduce on getting counters initial value $output->writeln('Done.'); diff --git a/src/Comsave/MortyCountsBundle/DependencyInjection/.gitignore b/src/Comsave/MortyCountsBundle/DependencyInjection/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php b/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php index ca09646..c6c2f17 100644 --- a/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php +++ b/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php @@ -6,11 +6,14 @@ class RedisStorageAdapterFactory { - public static function build(string $redisHost, int $redisPort): Redis + public static function build(string $redisHost, int $redisPort, ?string $redisPassword = null): Redis { - return new Redis([ - 'host' => $redisHost, - 'port' => $redisPort - ]); + return new Redis( + [ + 'host' => $redisHost, + 'port' => $redisPort, + 'password' => $redisPassword + ] + ); } } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index c1e5664..1c7a2c2 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -1,8 +1,9 @@ parameters: morty_counts_prometheus_url: 'prometheus:9090' morty_counts_pushgateway_url: 'pushgateway:9191' - morty_counts_prometheus_instance: 'my_custom_push_service_host' - morty_counts_prometheus_job: 'my_custom_push_job' + morty_counts_prometheus_instance: 'my_custom_push_service_host_or_other_group_name' + morty_counts_prometheus_jobs: + - 'my_custom_push_job' morty_counts_redis_host: 'redis' morty_counts_redis_port: 6379 @@ -37,9 +38,18 @@ services: JMS\Serializer\Serializer: factory: ['@Comsave\MortyCountsBundle\JmsSerializerFactory', 'build'] + Comsave\MortyCountsBundle\Command\PrometheusPushCommand: + autowire: true + autoconfigure: true + arguments: + $prometheusJobNames: '%morty_counts_prometheus_jobs%' + + Comsave\MortyCountsBundle\Services\PushGatewayClient: + autowire: true + arguments: + $prometheusInstanceName: '%morty_counts_prometheus_instance%' + Comsave\MortyCountsBundle\Services\PrometheusClient: autowire: true arguments: $prometheusUrl: '%morty_counts_prometheus_url%' - $prometheusJobName: '%morty_counts_prometheus_job%' - $prometheusInstanceName: '%morty_counts_prometheus_instance%' \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php index c03c7f1..a2cdfcd 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php @@ -34,9 +34,13 @@ public function __construct(string $prometheusUrl, Serializer $jmsSerializer, Cl public function query(array $arguments): PrometheusResponse { - $response = $this->httpClient->request('POST', sprintf('%s/api/v1/query', $this->prometheusUrl), [ - 'form_params' => $arguments - ]); + $response = $this->httpClient->request( + 'POST', + sprintf('%s/api/v1/query', $this->prometheusUrl), + [ + 'form_params' => $arguments, + ] + ); return $this->jmsSerializer->deserialize((string)$response->getBody(), PrometheusResponse::class, 'json'); } diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index 87624dd..da4d279 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -2,8 +2,11 @@ namespace Comsave\MortyCountsBundle\Services; +use GuzzleHttp\Exception\GuzzleException; use Prometheus\CollectorRegistry; use Prometheus\Counter; +use Prometheus\Exception\MetricsRegistrationException; +use Prometheus\Exception\StorageException; use Prometheus\Gauge; use Prometheus\Histogram; use Prometheus\PushGateway; @@ -20,9 +23,6 @@ class PushGatewayClient /** @var PushGateway */ private $pushGateway; - /** @var string */ - private $prometheusJobName; - /** @var string */ private $prometheusInstanceName; @@ -30,7 +30,6 @@ class PushGatewayClient * @param CollectorRegistry $registry * @param Redis $registryStorageAdapter * @param PushGateway $pushGateway - * @param string $prometheusJobName * @param string $prometheusInstanceName * @codeCoverageIgnore */ @@ -38,40 +37,53 @@ public function __construct( CollectorRegistry $registry, Redis $registryStorageAdapter, PushGateway $pushGateway, - string $prometheusJobName, string $prometheusInstanceName ) { $this->registry = $registry; $this->registryStorageAdapter = $registryStorageAdapter; $this->pushGateway = $pushGateway; - $this->prometheusJobName = $prometheusJobName; $this->prometheusInstanceName = $prometheusInstanceName; } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws StorageException */ - public function push(): void + public function push(string $prometheusJobName): void { - $this->pushGateway->push($this->registry, $this->prometheusJobName, [ - 'instance' => $this->prometheusInstanceName, - ]); + $this->pushGateway->push( + $this->registry, + $prometheusJobName, + [ + 'instance' => $this->prometheusInstanceName, + ] + ); } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws StorageException */ - public function pushAdd(): void + public function pushAll(array $prometheusJobNames): void { - $this->pushGateway->pushAdd($this->registry, $this->prometheusJobName, [ - 'instance' => $this->prometheusInstanceName, - ]); + foreach ($prometheusJobNames as $jobName) { + $this->push($jobName); + } } +// /** +// * @throws \GuzzleHttp\Exception\GuzzleException +// * @throws \Prometheus\Exception\StorageException +// */ +// public function pushAdd(): void +// { +// $this->pushGateway->pushAdd($this->registry, $this->prometheusJobName, [ +// 'instance' => $this->prometheusInstanceName, +// ]); +// } + /** - * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws MetricsRegistrationException */ public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter { @@ -84,7 +96,7 @@ public function counter(string $namespace, string $name, ?string $help = null, a } /** - * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws MetricsRegistrationException */ public function gauge(string $namespace, string $name, ?string $help = null, array $labels = []): Gauge { @@ -97,7 +109,7 @@ public function gauge(string $namespace, string $name, ?string $help = null, arr } /** - * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws MetricsRegistrationException */ public function histogram(string $namespace, string $name, ?string $help = null, array $labels = [], ?array $buckets = null): Histogram { @@ -111,7 +123,7 @@ public function histogram(string $namespace, string $name, ?string $help = null, } /** - * @throws \Prometheus\Exception\StorageException + * @throws StorageException */ public function flush(): void { diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index 55363bd..2007774 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -40,7 +40,6 @@ public function setUp(): void $registry, $registryStorageAdapter, PushGatewayFactory::build('pushgateway:9191'), - $this->jobName, $this->instanceName ); $this->pushGatewayClient->flush(); @@ -64,7 +63,7 @@ public function testPushesCounterMetric(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push(); + $this->pushGatewayClient->push($this->jobName); sleep(3); // wait for Prometheus to pull the metrics from PushGateway @@ -97,7 +96,7 @@ public function testPushesCounterMetricAndIncreases(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push(); + $this->pushGatewayClient->push($this->jobName); sleep(3); // wait for Prometheus to pull the metrics from PushGateway @@ -117,7 +116,7 @@ public function testPushesCounterMetricAndIncreases(): void $metricName ); $counter->inc(['blue']); - $this->pushGatewayClient->push(); + $this->pushGatewayClient->push($this->jobName); sleep(3); // wait for Prometheus to pull the metrics from PushGateway From 5e86d1d934b6a6369557a5ee757575fd7b876123 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 15:04:16 +0200 Subject: [PATCH 37/83] add multi node set up --- docker-compose.multi-node.yml | 102 ++++++++++++++++++++++++++++++ docker/haproxy/haproxy.cfg | 18 ++++++ docker/prometheus/prometheus1.yml | 14 ++++ docker/prometheus/prometheus2.yml | 14 ++++ docker/prometheus/prometheus3.yml | 14 ++++ 5 files changed, 162 insertions(+) create mode 100644 docker-compose.multi-node.yml create mode 100644 docker/haproxy/haproxy.cfg create mode 100644 docker/prometheus/prometheus1.yml create mode 100644 docker/prometheus/prometheus2.yml create mode 100644 docker/prometheus/prometheus3.yml diff --git a/docker-compose.multi-node.yml b/docker-compose.multi-node.yml new file mode 100644 index 0000000..cbfd0df --- /dev/null +++ b/docker-compose.multi-node.yml @@ -0,0 +1,102 @@ +version: "3" + +services: + php: + build: + dockerfile: ./docker/php-fpm/Dockerfile + context: . + depends_on: + - redis + volumes: + - ./:/app + + redis: + image: redis:alpine + + haproxy: + image: haproxy:alpine + ports: + - 9190:9190 + volumes: + - ./docker/haproxy:/usr/local/etc/haproxy:ro + + prometheus: + image: prom/prometheus + command: + - '--web.listen-address=:9090' + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.console.templates=/etc/prometheus/consoles' + - '--web.console.libraries=/etc/prometheus/console_libraries' + depends_on: + - pushgateway + ports: + - 9090:9090 + volumes: + - ./docker/prometheus/prometheus1.yml/:/etc/prometheus/prometheus.yml + + pushgateway: + image: prom/pushgateway + command: + - '--web.listen-address=:9191' + - '--push.disable-consistency-check' # todo: remove this after the pushGatewayClient is fixed + - '--persistence.interval=5m' + ports: + - 9191:9191 + + prometheus2: + image: prom/prometheus + command: + - '--web.listen-address=:9091' + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.console.templates=/etc/prometheus/consoles' + - '--web.console.libraries=/etc/prometheus/console_libraries' + depends_on: + - pushgateway2 + ports: + - 9091:9091 + volumes: + - ./docker/prometheus/prometheus.yml/:/etc/prometheus/prometheus.yml + + pushgateway2: + image: prom/pushgateway + command: + - '--web.listen-address=:9192' + - '--push.disable-consistency-check' + - '--persistence.interval=5m' + ports: + - 9192:9192 + + prometheus3: + image: prom/prometheus + command: + - '--web.listen-address=:9092' + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.console.templates=/etc/prometheus/consoles' + - '--web.console.libraries=/etc/prometheus/console_libraries' + depends_on: + - pushgateway3 + ports: + - 9092:9092 + volumes: + - ./docker/prometheus/prometheus.yml/:/etc/prometheus/prometheus.yml + + pushgateway3: + image: prom/pushgateway + command: + - '--web.listen-address=:9193' + - '--push.disable-consistency-check' + - '--persistence.interval=5m' + ports: + - 9193:9193 + + grafana: + image: grafana/grafana + depends_on: + - prometheus + ports: + - 3000:3000 + volumes: + - ./docker/grafana/datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml + environment: + - GF_SECURITY_ADMIN_PASSWORD=admin + - GF_USERS_ALLOW_SIGN_UP=false \ No newline at end of file diff --git a/docker/haproxy/haproxy.cfg b/docker/haproxy/haproxy.cfg new file mode 100644 index 0000000..3f7038f --- /dev/null +++ b/docker/haproxy/haproxy.cfg @@ -0,0 +1,18 @@ +global +# global settings here + +defaults +# defaults here + +frontend pushgateway_fe + bind :9190 + mode tcp + default_backend pushgateway_be + +backend pushgateway_be + mode tcp + balance roundrobin + default-server inter 1s + server pushgateway pushgateway:9191 check id 1 + server pushgateway2 pushgateway2:9192 check id 2 + server pushgateway3 pushgateway3:9193 check id 3 \ No newline at end of file diff --git a/docker/prometheus/prometheus1.yml b/docker/prometheus/prometheus1.yml new file mode 100644 index 0000000..f10687c --- /dev/null +++ b/docker/prometheus/prometheus1.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'prometheus' + scrape_interval: 5s + static_configs: + - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] + + - job_name: 'pushgateway' + honor_labels: true + scrape_interval: 2s + static_configs: + - targets: ['pushgateway:9191'] \ No newline at end of file diff --git a/docker/prometheus/prometheus2.yml b/docker/prometheus/prometheus2.yml new file mode 100644 index 0000000..80d0357 --- /dev/null +++ b/docker/prometheus/prometheus2.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'prometheus' + scrape_interval: 5s + static_configs: + - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] + + - job_name: 'pushgateway' + honor_labels: true + scrape_interval: 2s + static_configs: + - targets: ['pushgateway2:9192'] \ No newline at end of file diff --git a/docker/prometheus/prometheus3.yml b/docker/prometheus/prometheus3.yml new file mode 100644 index 0000000..233ab68 --- /dev/null +++ b/docker/prometheus/prometheus3.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'prometheus' + scrape_interval: 5s + static_configs: + - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] + + - job_name: 'pushgateway' + honor_labels: true + scrape_interval: 2s + static_configs: + - targets: ['pushgateway3:9193'] \ No newline at end of file From abe92ea9470726cbcaa258d972d160dae34d23e1 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 23 Apr 2020 15:35:09 +0200 Subject: [PATCH 38/83] update multinode config --- docker-compose.multi-node.yml | 12 +++++---- docker/haproxy/haproxy.cfg | 17 ++++++++++-- docker/prometheus/prometheus1.yml | 4 +-- docker/prometheus/prometheus2.yml | 4 +-- docker/prometheus/prometheus3.yml | 4 +-- .../Services/PushGatewayClient.php | 26 ++++++++++++++----- tests/Integration/PrometheusPushTest.php | 10 +++---- 7 files changed, 52 insertions(+), 25 deletions(-) diff --git a/docker-compose.multi-node.yml b/docker-compose.multi-node.yml index cbfd0df..50e5d67 100644 --- a/docker-compose.multi-node.yml +++ b/docker-compose.multi-node.yml @@ -15,8 +15,13 @@ services: haproxy: image: haproxy:alpine - ports: - - 9190:9190 + depends_on: + - prometheus + - prometheus2 + - prometheus3 + - pushgateway + - pushgateway2 + - pushgateway3 volumes: - ./docker/haproxy:/usr/local/etc/haproxy:ro @@ -38,7 +43,6 @@ services: image: prom/pushgateway command: - '--web.listen-address=:9191' - - '--push.disable-consistency-check' # todo: remove this after the pushGatewayClient is fixed - '--persistence.interval=5m' ports: - 9191:9191 @@ -61,7 +65,6 @@ services: image: prom/pushgateway command: - '--web.listen-address=:9192' - - '--push.disable-consistency-check' - '--persistence.interval=5m' ports: - 9192:9192 @@ -84,7 +87,6 @@ services: image: prom/pushgateway command: - '--web.listen-address=:9193' - - '--push.disable-consistency-check' - '--persistence.interval=5m' ports: - 9193:9193 diff --git a/docker/haproxy/haproxy.cfg b/docker/haproxy/haproxy.cfg index 3f7038f..27f3a9c 100644 --- a/docker/haproxy/haproxy.cfg +++ b/docker/haproxy/haproxy.cfg @@ -5,7 +5,7 @@ defaults # defaults here frontend pushgateway_fe - bind :9190 + bind :9191 mode tcp default_backend pushgateway_be @@ -15,4 +15,17 @@ backend pushgateway_be default-server inter 1s server pushgateway pushgateway:9191 check id 1 server pushgateway2 pushgateway2:9192 check id 2 - server pushgateway3 pushgateway3:9193 check id 3 \ No newline at end of file + server pushgateway3 pushgateway3:9193 check id 3 + +frontend prometheus_fe + bind :9090 + mode tcp + default_backend prometheus_be + +backend prometheus_be + mode tcp + balance roundrobin + default-server inter 1s + server prometheus prometheus:9090 check id 1 + server prometheus2 prometheus2:9091 check id 2 + server prometheus3 prometheus3:9093 check id 3 \ No newline at end of file diff --git a/docker/prometheus/prometheus1.yml b/docker/prometheus/prometheus1.yml index f10687c..b54c6d2 100644 --- a/docker/prometheus/prometheus1.yml +++ b/docker/prometheus/prometheus1.yml @@ -3,12 +3,12 @@ global: scrape_configs: - job_name: 'prometheus' - scrape_interval: 5s + scrape_interval: 1s static_configs: - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] - job_name: 'pushgateway' honor_labels: true - scrape_interval: 2s + scrape_interval: 1s static_configs: - targets: ['pushgateway:9191'] \ No newline at end of file diff --git a/docker/prometheus/prometheus2.yml b/docker/prometheus/prometheus2.yml index 80d0357..b1e893a 100644 --- a/docker/prometheus/prometheus2.yml +++ b/docker/prometheus/prometheus2.yml @@ -3,12 +3,12 @@ global: scrape_configs: - job_name: 'prometheus' - scrape_interval: 5s + scrape_interval: 1s static_configs: - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] - job_name: 'pushgateway' honor_labels: true - scrape_interval: 2s + scrape_interval: 1s static_configs: - targets: ['pushgateway2:9192'] \ No newline at end of file diff --git a/docker/prometheus/prometheus3.yml b/docker/prometheus/prometheus3.yml index 233ab68..69436de 100644 --- a/docker/prometheus/prometheus3.yml +++ b/docker/prometheus/prometheus3.yml @@ -3,12 +3,12 @@ global: scrape_configs: - job_name: 'prometheus' - scrape_interval: 5s + scrape_interval: 1s static_configs: - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] - job_name: 'pushgateway' honor_labels: true - scrape_interval: 2s + scrape_interval: 1s static_configs: - targets: ['pushgateway3:9193'] \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index da4d279..16ff021 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -51,13 +51,20 @@ public function __construct( */ public function push(string $prometheusJobName): void { - $this->pushGateway->push( - $this->registry, - $prometheusJobName, - [ - 'instance' => $this->prometheusInstanceName, - ] - ); + try { + $this->pushGateway->push( + $this->registry, + $prometheusJobName, + [ + 'instance' => $this->prometheusInstanceName, + ] + ); + } + catch (\RuntimeException $ex) { + if(strpos($ex->getMessage(), 'Unexpected status code 200 received from push gateway') === false) { + throw $ex; + } + } } /** @@ -122,6 +129,11 @@ public function histogram(string $namespace, string $name, ?string $help = null, ); } + public function getRegistry(): CollectorRegistry + { + return $this->registry; + } + /** * @throws StorageException */ diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusPushTest.php index 2007774..dbeeac6 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusPushTest.php @@ -28,7 +28,7 @@ class PrometheusPushTest extends TestCase public function setUp(): void { $this->prometheusClient = new PrometheusClient( - 'prometheus:9090', + 'haproxy:9090', JmsSerializerFactory::build(), GuzzleHttpClientFactory::build() ); @@ -39,7 +39,7 @@ public function setUp(): void $this->pushGatewayClient = new PushGatewayClient( $registry, $registryStorageAdapter, - PushGatewayFactory::build('pushgateway:9191'), + PushGatewayFactory::build('haproxy:9191'), $this->instanceName ); $this->pushGatewayClient->flush(); @@ -56,7 +56,7 @@ public function testPushesCounterMetric(): void $metricName = 'some_counter'; $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $counter = $this->pushGatewayClient->counter( + $counter = $this->pushGatewayClient->getRegistry()->registerCounter( $metricNamespace, $metricName, 'it increases', @@ -89,7 +89,7 @@ public function testPushesCounterMetricAndIncreases(): void $metricName = 'some_counter_2'; $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $counter = $this->pushGatewayClient->counter( + $counter = $this->pushGatewayClient->getRegistry()->registerCounter( $metricNamespace, $metricName, 'it increases', @@ -111,7 +111,7 @@ public function testPushesCounterMetricAndIncreases(): void // todo: integrate initial (last) value fetch for the COUNTER // todo: this should work even after clearing redis cache which should be done after every push - $counter = $this->pushGatewayClient->counter( + $counter = $this->pushGatewayClient->getRegistry()->getCounter( $metricNamespace, $metricName ); From f589792933e30f4aa143857629fa6cc6bd1aa86e Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Fri, 24 Apr 2020 16:18:51 +0200 Subject: [PATCH 39/83] update prometheus multi node config; add tests for multi-node & haproxy --- docker-compose.multi-node.yml | 23 +- docker/grafana/datasources1.yml | 8 + docker/haproxy/haproxy.cfg | 6 +- docker/prometheus/prometheus1.yml | 21 +- docker/prometheus/prometheus2.yml | 21 +- docker/prometheus/prometheus3.yml | 21 +- .../Resources/config/services.yml | 2 +- .../Services/PushGatewayClient.php | 19 +- .../PrometheusMultiNodeHaProxyPushTest.php | 139 ++++++++++++ .../PrometheusMultiNodePushTest.php | 205 ++++++++++++++++++ ...t.php => PrometheusSingleNodePushTest.php} | 37 ++-- 11 files changed, 442 insertions(+), 60 deletions(-) create mode 100644 docker/grafana/datasources1.yml create mode 100644 tests/Integration/PrometheusMultiNodeHaProxyPushTest.php create mode 100644 tests/Integration/PrometheusMultiNodePushTest.php rename tests/Integration/{PrometheusPushTest.php => PrometheusSingleNodePushTest.php} (80%) diff --git a/docker-compose.multi-node.yml b/docker-compose.multi-node.yml index 50e5d67..630a33f 100644 --- a/docker-compose.multi-node.yml +++ b/docker-compose.multi-node.yml @@ -28,14 +28,14 @@ services: prometheus: image: prom/prometheus command: - - '--web.listen-address=:9090' + - '--web.listen-address=:9091' - '--config.file=/etc/prometheus/prometheus.yml' - '--web.console.templates=/etc/prometheus/consoles' - '--web.console.libraries=/etc/prometheus/console_libraries' depends_on: - pushgateway ports: - - 9090:9090 + - 9091:9091 volumes: - ./docker/prometheus/prometheus1.yml/:/etc/prometheus/prometheus.yml @@ -43,62 +43,59 @@ services: image: prom/pushgateway command: - '--web.listen-address=:9191' - - '--persistence.interval=5m' ports: - 9191:9191 prometheus2: image: prom/prometheus command: - - '--web.listen-address=:9091' + - '--web.listen-address=:9092' - '--config.file=/etc/prometheus/prometheus.yml' - '--web.console.templates=/etc/prometheus/consoles' - '--web.console.libraries=/etc/prometheus/console_libraries' depends_on: - pushgateway2 ports: - - 9091:9091 + - 9092:9092 volumes: - - ./docker/prometheus/prometheus.yml/:/etc/prometheus/prometheus.yml + - ./docker/prometheus/prometheus2.yml/:/etc/prometheus/prometheus.yml pushgateway2: image: prom/pushgateway command: - '--web.listen-address=:9192' - - '--persistence.interval=5m' ports: - 9192:9192 prometheus3: image: prom/prometheus command: - - '--web.listen-address=:9092' + - '--web.listen-address=:9093' - '--config.file=/etc/prometheus/prometheus.yml' - '--web.console.templates=/etc/prometheus/consoles' - '--web.console.libraries=/etc/prometheus/console_libraries' depends_on: - pushgateway3 ports: - - 9092:9092 + - 9093:9093 volumes: - - ./docker/prometheus/prometheus.yml/:/etc/prometheus/prometheus.yml + - ./docker/prometheus/prometheus3.yml/:/etc/prometheus/prometheus.yml pushgateway3: image: prom/pushgateway command: - '--web.listen-address=:9193' - - '--persistence.interval=5m' ports: - 9193:9193 grafana: image: grafana/grafana depends_on: - - prometheus + - haproxy ports: - 3000:3000 volumes: - - ./docker/grafana/datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml + - ./docker/grafana/datasources1.yml:/etc/grafana/provisioning/datasources/datasources.yml environment: - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false \ No newline at end of file diff --git a/docker/grafana/datasources1.yml b/docker/grafana/datasources1.yml new file mode 100644 index 0000000..04cb172 --- /dev/null +++ b/docker/grafana/datasources1.yml @@ -0,0 +1,8 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://haproxy:9090 + isDefault: true diff --git a/docker/haproxy/haproxy.cfg b/docker/haproxy/haproxy.cfg index 27f3a9c..89d793f 100644 --- a/docker/haproxy/haproxy.cfg +++ b/docker/haproxy/haproxy.cfg @@ -13,7 +13,7 @@ backend pushgateway_be mode tcp balance roundrobin default-server inter 1s - server pushgateway pushgateway:9191 check id 1 + server pushgateway pushgateway:9191 check id 1 server pushgateway2 pushgateway2:9192 check id 2 server pushgateway3 pushgateway3:9193 check id 3 @@ -26,6 +26,6 @@ backend prometheus_be mode tcp balance roundrobin default-server inter 1s - server prometheus prometheus:9090 check id 1 - server prometheus2 prometheus2:9091 check id 2 + server prometheus prometheus:9091 check id 1 + server prometheus2 prometheus2:9092 check id 2 server prometheus3 prometheus3:9093 check id 3 \ No newline at end of file diff --git a/docker/prometheus/prometheus1.yml b/docker/prometheus/prometheus1.yml index b54c6d2..8fcc265 100644 --- a/docker/prometheus/prometheus1.yml +++ b/docker/prometheus/prometheus1.yml @@ -2,13 +2,24 @@ global: scrape_interval: 15s scrape_configs: - - job_name: 'prometheus' - scrape_interval: 1s + - job_name: 'federate' + scrape_interval: 200ms + honor_labels: true + metrics_path: '/federate' + params: + 'match[]': + - '{job=~"morty_.*"}' static_configs: - - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] + - targets: +# - 'prometheus:9091' + - 'prometheus2:9092' + - 'prometheus3:9093' - job_name: 'pushgateway' + scrape_interval: 100ms honor_labels: true - scrape_interval: 1s static_configs: - - targets: ['pushgateway:9191'] \ No newline at end of file + - targets: + - 'pushgateway:9191' + - 'pushgateway2:9192' + - 'pushgateway3:9193' diff --git a/docker/prometheus/prometheus2.yml b/docker/prometheus/prometheus2.yml index b1e893a..de97d95 100644 --- a/docker/prometheus/prometheus2.yml +++ b/docker/prometheus/prometheus2.yml @@ -2,13 +2,24 @@ global: scrape_interval: 15s scrape_configs: - - job_name: 'prometheus' - scrape_interval: 1s + - job_name: 'federate' + scrape_interval: 200ms + honor_labels: true + metrics_path: '/federate' + params: + 'match[]': + - '{job=~"morty_.*"}' static_configs: - - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] + - targets: + - 'prometheus:9091' +# - 'prometheus2:9092' + - 'prometheus3:9093' - job_name: 'pushgateway' + scrape_interval: 500ms honor_labels: true - scrape_interval: 1s static_configs: - - targets: ['pushgateway2:9192'] \ No newline at end of file + - targets: + - 'pushgateway:9191' + - 'pushgateway2:9192' + - 'pushgateway3:9193' \ No newline at end of file diff --git a/docker/prometheus/prometheus3.yml b/docker/prometheus/prometheus3.yml index 69436de..74ff9e3 100644 --- a/docker/prometheus/prometheus3.yml +++ b/docker/prometheus/prometheus3.yml @@ -2,13 +2,24 @@ global: scrape_interval: 15s scrape_configs: - - job_name: 'prometheus' - scrape_interval: 1s + - job_name: 'federate' + scrape_interval: 200ms + honor_labels: true + metrics_path: '/federate' + params: + 'match[]': + - '{job=~"morty_.*"}' static_configs: - - targets: ['prometheus:9090', 'prometheus2:9091', 'prometheus3:9092'] + - targets: + - 'prometheus:9091' + - 'prometheus2:9092' +# - 'prometheus3:9093' - job_name: 'pushgateway' + scrape_interval: 500ms honor_labels: true - scrape_interval: 1s static_configs: - - targets: ['pushgateway3:9193'] \ No newline at end of file + - targets: + - 'pushgateway:9191' + - 'pushgateway2:9192' + - 'pushgateway3:9193' \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index 1c7a2c2..05a50ef 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -3,7 +3,7 @@ parameters: morty_counts_pushgateway_url: 'pushgateway:9191' morty_counts_prometheus_instance: 'my_custom_push_service_host_or_other_group_name' morty_counts_prometheus_jobs: - - 'my_custom_push_job' + - 'push_job' morty_counts_redis_host: 'redis' morty_counts_redis_port: 6379 diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index 16ff021..6df2cf4 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -52,9 +52,10 @@ public function __construct( public function push(string $prometheusJobName): void { try { +// $this->pushGateway->pushAdd( $this->pushGateway->push( $this->registry, - $prometheusJobName, + sprintf('morty_%s', $prometheusJobName), [ 'instance' => $this->prometheusInstanceName, ] @@ -78,17 +79,6 @@ public function pushAll(array $prometheusJobNames): void } } -// /** -// * @throws \GuzzleHttp\Exception\GuzzleException -// * @throws \Prometheus\Exception\StorageException -// */ -// public function pushAdd(): void -// { -// $this->pushGateway->pushAdd($this->registry, $this->prometheusJobName, [ -// 'instance' => $this->prometheusInstanceName, -// ]); -// } - /** * @throws MetricsRegistrationException */ @@ -141,4 +131,9 @@ public function flush(): void { $this->registryStorageAdapter->flushRedis(); } + + public function setPrometheusInstanceName(string $prometheusInstanceName): void + { + $this->prometheusInstanceName = $prometheusInstanceName; + } } \ No newline at end of file diff --git a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php new file mode 100644 index 0000000..534957b --- /dev/null +++ b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php @@ -0,0 +1,139 @@ +flush(); + + $counter = $pushGateway1->getRegistry()->registerCounter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + $pushGateway1->push($this->jobName); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $response = static::buildPrometheusClient('haproxy:9090')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, 'Node 1 results invalid.'); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(5, $results[0]->getValue()); + } + + /** + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\MetricNotFoundException + * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws \Prometheus\Exception\StorageException + */ + public function testPushesCounterMetricAndIncreases(): void + { + $metricNamespace = 'test'; + $metricName = 'some_counter_2_' . date('YmdHis'); + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + var_dump($metricFullName); + + $pushGateway1 = static::buildPushGatewayClient('haproxy:9191'); + $pushGateway1->flush(); + + $counter = $pushGateway1->getRegistry()->registerCounter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + $pushGateway1->push($this->jobName.'_2'); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $response = static::buildPrometheusClient('haproxy:9090')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, 'Node 1 results invalid.'); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(5, $results[0]->getValue()); + + // todo: integrate initial (last) value fetch for the COUNTER + // todo: this should work even after clearing redis cache which should be done after every push + $counter = $pushGateway1->getRegistry()->getCounter( + $metricNamespace, + $metricName + ); + $counter->inc(['blue']); + $pushGateway1->push($this->jobName.'_2'); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $response = static::buildPrometheusClient('haproxy:9090')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, 'Node 1 results invalid.'); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(6, $results[0]->getValue()); + } +} \ No newline at end of file diff --git a/tests/Integration/PrometheusMultiNodePushTest.php b/tests/Integration/PrometheusMultiNodePushTest.php new file mode 100644 index 0000000..2d74fe6 --- /dev/null +++ b/tests/Integration/PrometheusMultiNodePushTest.php @@ -0,0 +1,205 @@ +flush(); + + $counter = $pushGateway1->getRegistry()->registerCounter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + $pushGateway1->push($this->jobName); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $response = static::buildPrometheusClient('prometheus:9091')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, 'Node 1 results invalid.'); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(5, $results[0]->getValue()); + + $response = static::buildPrometheusClient('prometheus2:9092')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results2 = $response->getData()->getResults(); + + $this->assertCount(1, $results2, 'Node 2 results invalid.'); + $this->assertEquals($metricFullName, $results2[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results2[0]->getMetric()['type']); + $this->assertEquals(5, $results2[0]->getValue()); + + $response = static::buildPrometheusClient('prometheus3:9093')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results3 = $response->getData()->getResults(); + + $this->assertCount(1, $results3, 'Node 3 results invalid.'); + $this->assertEquals($metricFullName, $results3[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results3[0]->getMetric()['type']); + $this->assertEquals(5, $results3[0]->getValue()); + } + + /** + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Prometheus\Exception\MetricNotFoundException + * @throws \Prometheus\Exception\MetricsRegistrationException + * @throws \Prometheus\Exception\StorageException + */ + public function testPushesCounterMetricAndIncreases(): void + { + $metricNamespace = 'test'; + $metricName = 'some_counter_2_' . date('YmdHis'); + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + var_dump($metricFullName); + + $pushGateway1 = static::buildPushGatewayClient('pushgateway:9191'); + $pushGateway1->flush(); + + $counter = $pushGateway1->getRegistry()->registerCounter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + $pushGateway1->push($this->jobName.'_2'); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $response = static::buildPrometheusClient('prometheus:9091')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, 'Node 1 results invalid.'); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(5, $results[0]->getValue()); + + $response = static::buildPrometheusClient('prometheus2:9092')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results2 = $response->getData()->getResults(); + + $this->assertCount(1, $results2, 'Node 2 results invalid.'); + $this->assertEquals($metricFullName, $results2[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results2[0]->getMetric()['type']); + $this->assertEquals(5, $results2[0]->getValue()); + + $response = static::buildPrometheusClient('prometheus3:9093')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results3 = $response->getData()->getResults(); + + $this->assertCount(1, $results3, 'Node 3 results invalid.'); + $this->assertEquals($metricFullName, $results3[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results3[0]->getMetric()['type']); + $this->assertEquals(5, $results3[0]->getValue()); + + // todo: integrate initial (last) value fetch for the COUNTER + // todo: this should work even after clearing redis cache which should be done after every push + $counter = $pushGateway1->getRegistry()->getCounter( + $metricNamespace, + $metricName + ); + $counter->inc(['blue']); + $pushGateway1->push($this->jobName.'_2'); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $response = static::buildPrometheusClient('prometheus:9091')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, 'Node 1 results invalid.'); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(6, $results[0]->getValue()); + + $response = static::buildPrometheusClient('prometheus2:9092')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results2 = $response->getData()->getResults(); + + $this->assertCount(1, $results2, 'Node 2 results invalid.'); + $this->assertEquals($metricFullName, $results2[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results2[0]->getMetric()['type']); + $this->assertEquals(6, $results2[0]->getValue()); + + $response = static::buildPrometheusClient('prometheus3:9093')->query([ + 'query' => $metricFullName, + ]); +// var_dump($response); + $results3 = $response->getData()->getResults(); + + $this->assertCount(1, $results3, 'Node 3 results invalid.'); + $this->assertEquals($metricFullName, $results3[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results3[0]->getMetric()['type']); + $this->assertEquals(6, $results3[0]->getValue()); + } +} \ No newline at end of file diff --git a/tests/Integration/PrometheusPushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php similarity index 80% rename from tests/Integration/PrometheusPushTest.php rename to tests/Integration/PrometheusSingleNodePushTest.php index dbeeac6..f53c4b3 100644 --- a/tests/Integration/PrometheusPushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -11,7 +11,7 @@ use PHPUnit\Framework\TestCase; use Prometheus\CollectorRegistry; -class PrometheusPushTest extends TestCase +class PrometheusSingleNodePushTest extends TestCase { /** @var PrometheusClient */ private $prometheusClient; @@ -20,7 +20,7 @@ class PrometheusPushTest extends TestCase private $pushGatewayClient; /** @var string */ - private $jobName = 'my_custom_service_job'; + private $jobName = 'service_job'; /** @var string */ private $instanceName = '127.0.0.1:9000'; @@ -28,7 +28,7 @@ class PrometheusPushTest extends TestCase public function setUp(): void { $this->prometheusClient = new PrometheusClient( - 'haproxy:9090', + 'prometheus:9091', JmsSerializerFactory::build(), GuzzleHttpClientFactory::build() ); @@ -39,9 +39,10 @@ public function setUp(): void $this->pushGatewayClient = new PushGatewayClient( $registry, $registryStorageAdapter, - PushGatewayFactory::build('haproxy:9191'), + PushGatewayFactory::build('pushgateway:9191'), $this->instanceName ); + $this->pushGatewayClient->flush(); } @@ -50,10 +51,10 @@ public function setUp(): void * @throws \Prometheus\Exception\MetricsRegistrationException * @throws \Prometheus\Exception\StorageException */ - public function testPushesCounterMetric(): void + public function testPushesOneCounterMetric(): void { $metricNamespace = 'test'; - $metricName = 'some_counter'; + $metricName = 'some_counter_1_' . date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $counter = $this->pushGatewayClient->getRegistry()->registerCounter( @@ -65,11 +66,13 @@ public function testPushesCounterMetric(): void $counter->incBy(5, ['blue']); $this->pushGatewayClient->push($this->jobName); - sleep(3); // wait for Prometheus to pull the metrics from PushGateway + sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $results = $this->prometheusClient->query([ + $response = $this->prometheusClient->query([ 'query' => $metricFullName, - ])->getData()->getResults(); + ]); +// var_dump($response); + $results = $response->getData()->getResults(); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -86,7 +89,7 @@ public function testPushesCounterMetric(): void public function testPushesCounterMetricAndIncreases(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_2'; + $metricName = 'some_counter_2_' . date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $counter = $this->pushGatewayClient->getRegistry()->registerCounter( @@ -96,13 +99,15 @@ public function testPushesCounterMetricAndIncreases(): void ['type'] ); $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push($this->jobName); + $this->pushGatewayClient->push($this->jobName.'_2'); - sleep(3); // wait for Prometheus to pull the metrics from PushGateway + sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $results = $this->prometheusClient->query([ + $response = $this->prometheusClient->query([ 'query' => $metricFullName, - ])->getData()->getResults(); + ]); +// var_dump($response); + $results = $response->getData()->getResults(); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -116,9 +121,9 @@ public function testPushesCounterMetricAndIncreases(): void $metricName ); $counter->inc(['blue']); - $this->pushGatewayClient->push($this->jobName); + $this->pushGatewayClient->push($this->jobName.'_2'); - sleep(3); // wait for Prometheus to pull the metrics from PushGateway + sleep(2); // wait for Prometheus to pull the metrics from PushGateway $results = $this->prometheusClient->query([ 'query' => $metricFullName, From e2c82fae365bb07feaae80cba53e31bbe122464e Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Fri, 24 Apr 2020 16:21:18 +0200 Subject: [PATCH 40/83] update prometheus config --- docker/prometheus/prometheus1.yml | 2 +- docker/prometheus/prometheus2.yml | 2 +- docker/prometheus/prometheus3.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/prometheus/prometheus1.yml b/docker/prometheus/prometheus1.yml index 8fcc265..684ef3e 100644 --- a/docker/prometheus/prometheus1.yml +++ b/docker/prometheus/prometheus1.yml @@ -3,7 +3,7 @@ global: scrape_configs: - job_name: 'federate' - scrape_interval: 200ms + scrape_interval: 500ms honor_labels: true metrics_path: '/federate' params: diff --git a/docker/prometheus/prometheus2.yml b/docker/prometheus/prometheus2.yml index de97d95..90e09a7 100644 --- a/docker/prometheus/prometheus2.yml +++ b/docker/prometheus/prometheus2.yml @@ -3,7 +3,7 @@ global: scrape_configs: - job_name: 'federate' - scrape_interval: 200ms + scrape_interval: 500ms honor_labels: true metrics_path: '/federate' params: diff --git a/docker/prometheus/prometheus3.yml b/docker/prometheus/prometheus3.yml index 74ff9e3..92e6feb 100644 --- a/docker/prometheus/prometheus3.yml +++ b/docker/prometheus/prometheus3.yml @@ -3,7 +3,7 @@ global: scrape_configs: - job_name: 'federate' - scrape_interval: 200ms + scrape_interval: 500ms honor_labels: true metrics_path: '/federate' params: From 13406fc3d095e763a67dcb8f69b401e0bb46b774 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Fri, 24 Apr 2020 22:34:31 +0200 Subject: [PATCH 41/83] Update README.md --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d53e37c..20fb1a3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # morty-counts -Teaching Morty how to count and sending the results to Prometheus. +Teaching Morty how to count and sending the results to Prometheus. + High Availability Option ![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) ![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) @@ -11,6 +11,16 @@ Teaching Morty how to count and sending the results to Prometheus. 2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway +## How does it look? + +### Single Node + +- + +### Multiple Nodes + +- + ## Development Start `docker-compose up --remove-orphans -d --build` From a17d32fca994fe8362d606e416eee61c1d2f96c1 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 10:38:01 +0200 Subject: [PATCH 42/83] single node remove prometheus config --- docker/prometheus/prometheus.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docker/prometheus/prometheus.yml b/docker/prometheus/prometheus.yml index 4f7f73a..f1aec0c 100644 --- a/docker/prometheus/prometheus.yml +++ b/docker/prometheus/prometheus.yml @@ -2,13 +2,8 @@ global: scrape_interval: 15s scrape_configs: - - job_name: 'prometheus' - scrape_interval: 5s - static_configs: - - targets: ['prometheus:9090'] - - job_name: 'pushgateway' honor_labels: true - scrape_interval: 2s + scrape_interval: 500ms static_configs: - targets: ['pushgateway:9191'] \ No newline at end of file From f6fb5a2fa6e69138dbf59250b5e762f03c15b28c Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 12:10:25 +0200 Subject: [PATCH 43/83] add cluster diagrams --- .gitignore | 4 +- README.md | 10 +++ images/advanced_prometheus_cluster_setup.png | Bin 0 -> 112745 bytes images/basic_prometheus_cluster_setup.png | Bin 0 -> 69084 bytes images/diagram.py | 78 +++++++++++++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 images/advanced_prometheus_cluster_setup.png create mode 100644 images/basic_prometheus_cluster_setup.png create mode 100644 images/diagram.py diff --git a/.gitignore b/.gitignore index cdb3d20..eaf6bc1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea/ vendor/ -composer.lock \ No newline at end of file +composer.lock +__pycache__ +.DS_Store diff --git a/README.md b/README.md index d53e37c..b4e4799 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,16 @@ Teaching Morty how to count and sending the results to Prometheus. 2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway +## How does it work? + +### Single-node Prometheus + Pushgateway + +![](./images/basic_prometheus_cluster_setup.png) + +### Multi-node Prometheus + Pushgateway + +![](./images/advanced_prometheus_cluster_setup.png) + ## Development Start `docker-compose up --remove-orphans -d --build` diff --git a/images/advanced_prometheus_cluster_setup.png b/images/advanced_prometheus_cluster_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6eb293a02a00464e65859f55d5970e596f38b7 GIT binary patch literal 112745 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

-brvx`F~DCWm`GkWHjF3M?oOc)<|j6L5nZUC!d0 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 literal 0 HcmV?d00001 diff --git a/images/basic_prometheus_cluster_setup.png b/images/basic_prometheus_cluster_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..6da5aef606731a61b022dd8b8709bfc5b63b532a GIT binary patch literal 69084 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%0DoTNJ@>uh7k4af*Sk4hARmar!{}IB8>ripced&6 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 literal 0 HcmV?d00001 diff --git a/images/diagram.py b/images/diagram.py new file mode 100644 index 0000000..26d9040 --- /dev/null +++ b/images/diagram.py @@ -0,0 +1,78 @@ +from diagrams import Cluster, Diagram, Edge +from diagrams.onprem.compute import Server +from diagrams.onprem.inmemory import Redis +from diagrams.onprem.monitoring import Prometheus +from diagrams.onprem.network import Haproxy +from diagrams.aws.compute import ECS + +with Diagram(name="Advanced Prometheus Cluster Setup", show=False, direction="TB"): + haproxy = Haproxy("haproxy") + + with Cluster("App Cluster"): + app = Server("app") + app_redis = Redis("pushgateway_redis_buffer") + app - Edge(color="brown", style="dashed") - app_redis + + app_cluster = [ + app, + app_redis + ] + + with Cluster("Prometheus Cluster"): + with Cluster("Prom1"): + push1 = ECS('pushgateway') + prom1 = Prometheus('prometheus') + + with Cluster("Prom2"): + push2 = ECS('pushgateway') + prom2 = Prometheus('prometheus') + + with Cluster("Prom3"): + push3 = ECS('pushgateway') + prom3 = Prometheus('prometheus') + + push1 << Edge(label="pull", color="brown") << prom1 + push1 << Edge(color="brown") << prom2 + push1 << Edge(color="brown") << prom3 + + push2 << Edge(label="pull", color="brown") << prom2 + push2 << Edge(color="brown") << prom1 + push2 << Edge(color="brown") << prom3 + + push3 << Edge(label="pull", color="brown") << prom3 + push3 << Edge(color="brown") << prom1 + push3 << Edge(color="brown") << prom2 + + prom1 << Edge(label="pull") << prom2 + prom1 << Edge(label="pull") << prom3 + + prom2 << Edge(label="pull") << prom1 + prom2 << Edge(label="pull") << prom3 + + prom3 << Edge(label="pull") << prom1 + prom3 << Edge(label="pull") << prom2 + + app >> Edge(label="push_metrics") >> haproxy >> [ + push1, + push2, + push3 + ] + +with Diagram(name="Basic Prometheus Cluster Setup", show=False): + with Cluster("App Cluster"): + app = Server("app") + app_redis = Redis("pushgateway_redis_buffer") + app - Edge(color="brown", style="dashed") - app_redis + + app_cluster = [ + app, + app_redis + ] + + with Cluster("Prom"): + push1 = ECS('pushgateway') + prom1 = Prometheus('prometheus') + + push1 << Edge(label="pull") << prom1 + + app >> Edge(label="push_metrics") >> push1 \ No newline at end of file From fb68a2651d9d8fc4a120c9a110d8cff6e9d22545 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 12:15:13 +0200 Subject: [PATCH 44/83] update diagrams --- images/advanced_prometheus_cluster_setup.png | Bin 112745 -> 166438 bytes images/diagram.py | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/images/advanced_prometheus_cluster_setup.png b/images/advanced_prometheus_cluster_setup.png index 3c6eb293a02a00464e65859f55d5970e596f38b7..f76f1e23362240913b9dabcf905421db58842909 100644 GIT binary patch literal 166438 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

J}k(ofiD^jUB$2hl@#P zz3vtj1WtX_!GPN8t#HfL+nQk|9VBK`%;Z5OJ_cSmRd-FI2b#Os%vW%FARg!HJ%sbl#53xaY8d(0^rrca%LoeZuC}KJmtD|g# ziEk25Z&4P&ir&+TMp*|(q<98I_P?}^W$9^b%~m=VG%PV8n(Fu?^;i5-km~ReM5k*5 zCvlU{LCPTZocg1#WP-sIFw4T=@GSxLP0g>*G?#ZU@+Z3SM-`x@X<^p{049x6q$CmF z_lh<9`10xM{neREEbJz&%G+Ei=3|Aphvk`7wl7@eeLP8;)X0^#re(gDHRd>80Y>Bu zN>jiPAOft}ka3d@zWu!TJngU-3sd2(mrUqekMKK2@$Xnz^_x1n@oT5ZdhwP5Dx(lC zXMULZj}K6#+#L`uGcTpCmiHw@U)r~S7jb&-dOnwv8s;gU>vSCB@XNY1?N4~I=6ddG z{7=c*;~Q@W!vaZM-Cx~)nOtu2xCnp$lY`+R{>x}%Ndl|1u~E(|qYn;!zPY|ql2YAm zA9QNft+P9eOm@D?phLI_+)wV_BuK&^pzSE4rOVbu1EOFqDz$Qj=0jUYJgYB*P3MAZ z4z24>(E|01_5GQj8air4uXI$X8`ToaFf5m`7vV9~UW|P1-ZT)$o0>>*XEjlH6@@@T zUQYVSZ$?SL_5zI|Y~bakZM7B&IjS?kw8xaaoJg{^@AnK_zY=N z#F*&U7_e|?Y(Y2ORl01G6sq)oG1zrj2Z-(_1{x&r8c_NEtgkD~*H&jJ2>>IG#~djx z*3i9aJ6V-~N|TR(o>I9vlMbiiYpml-h8weEoZ5D7F-7|K?PP#geW4$=k4cIk?)AliDxa7;+WR=*v zvChnfW;S13J~roBMt~v@24i`wzAIoHC*n>3`)@2L@cfUUbZx-yx>F&lZTmHe!|G-o zkH>9P-{<4}Zr|?>WMShk)FBlAJMxBCwT{mr`rTYodU2MI~CB~xD?cz3KjT-DM_tDeLDY+B$vLflcA5Z z^Sgetf1a(htr55{Rrp;Q7>Y3Z^)e(dn$_uLdX>R-rw4x7c{qd<4C2XQ<156`@bz~6 zCA1ZC`~H&LMSJbNzJBoac_ML_tpA#Q*Pp#XXXn{}-l%Y~&+++^?)W|c(~4x{x8rl2 zD8p_&^R#jmufSK?VB7gZ?(w$1m9=bq>{#}_nb>+Y^A3V+->33u6rjqCtzauao&$9h zCcy1hgizfV5r&8$WC9)Lc9PC>Tqfo$lrr!!wlla$?Nbg<30L2cl!ns1EwR?r0UKsZ zRCJnzNKtp&yQN-ruaRND;tOvHUvWPqb=r4Bv#XxW3>wFYg+dn=E|H~@#47^ z1it5qDhG57^19Oc`Br*$#0mYX$nYwa2@+G3*C#lb-9uYF*0Wph&Cudkp>r~FA#64t z;P&{n4C!h{QZXLGr{!^UiEBYQzUyn|PHUB@g54oVj*u_+xA7!P93hu7{9&h=P3@CA zanM~Tp=bbJf>-i;*-S-~jPNhbC%ul`W%adYX|D5kde$$A)RAc>r)n_hoYRLR3O+TF4r z9v%c8k&_t&-M)@+>|znSu6-Q8L=Z!N*9YBxw=6GH|NIE6ZMTWOZo0ea zp%CyAy5ENVlFa^Eq+Nzm*f(bIDJRtV?0dP5hcuSoXi?oCv0_}xg7r+DV|&kK+mB=0 zNlOE;$7P)MGvNE;Efn;-D=H91#)figUk3C&Jeh1R1-<)C;IK2o2E%mi?Y{g)jhHM- zDyU!ySFt>QSBgEuBZ?|pw39M-7jMWBw$?DQWd6p+GJZbNhoFIzK1X*fI9Z37gQ z@1ie(4yxC_8?(LoUMyI^ODSuaaZXUVksV}C^1CBeD0@i_PUlLwX{O`< z&D=k>%O{Zcps$3N<~|6Kt{w3lh^CdGZ9WA)%f6p(3M3ZFB$xcUw*Q#&!N?$rovoDz9l|h^ou{TJ*U}*8qx$UE0#NDlzKkOBm-A|0Er#(i=|ey71LL{X zRVp?%HubnX2~QHQX`b!ee_z)zzO>Doo{`e1RN=49eqXuLlrUF)VUPco^*tW5lV1YwvX_ji{x@{&f{dT>;JbhQ|e3GrV>-EXP zF{`wQFm-E$vCpiWxNACy3A6S80v0qGK1n;0_TYU57-dtj7}H&2J7ag0xV3bZm_;jF z`*evebvpqP4dKo*<{H@xsv5sXA~Ql@b!LcS%6QOQG$_k!Wa|}2H+T)|nF=KbVb6yyg&Fe}tMtRmkJ3=9UK_;S z{egK@Rau!>|1(k`)cGp=z{Sota>CYHmBAQO-#Ko}E{jJZ=AD{`ZvOs+a(hh|7N#Jv zL|o=(Xdtu>%EuJ9kVGP;jP>DF+pam{EY811v+cR>N9aZ#>^X2SGLhX*Jt27hs60L)VBT#g#@2RG@(xxj6 zU`&wLYcVVI#Gnh6+a80Jv6*M!`=BrJ>7#-;Q_gI}L>U3}Ij9m(K=Cyk71zz7NX{cY zff+;)QbME8cuSf2;+?NKsv7IY9C2c!Z+dfEmM3I$O}KRZGOW#0i`BdngW+pM5kw73 zE=O~s%>GFp>~k%lrN#!S1UkZepzYtO$#d+nFh$D91nk7wj*m#G!wJDUo>&_rE*3Dqt9r>L# z&K8l)y(>Q7kApZJTTrp2MrGf1b>FQxU4yX&*0%yEuXS3JVhe_0FSE1FR&Du>x7ZBN z6NkhdGAOKb^r^B6(A6YnE>xes+Kkcbc0~c@3xOr#P#(4L%EB0YGy&XKXx_Lrj2Bgx z+}}J@Da{4i(IUb4dX>dMsuSdNnQ|XXSGGepRef@Khwi(#o$u-X&+z{`=x~v#4`eRE zn8b$$O-LUfa+>GLMyk3$+pf;eMuAeJfszatAU_F{5iC!_A9p1P6778cc{!r{W1t%E zWm>=zPWUHANV!mc&_Wq_zxTeOYu3Ggen264_JAT{K&;PV$I@A?&K2IJZ*Rqqo`&YW z#aw?PdaUc(#i`KI-7#!Gdwqb3C2rdZ;ysynzZa7FB;GxEI7>PurR!3N z%fCu}t0{cMwn)M%b-V4zwI}MR$0?x6HOE-qM)*w{`KrmVwqRLGN@8UA?I_60xA3p*a&6sP&TnoYTuBCgJ z-vNwSg5VE9kveHN>ZU%hQFPmA*S@QGHChwQ+P!INj>^wh4D|PI^HYRgy%m*lkuwd0 z>jk59X5hb$`e6Yjtuj-GDLt`n=6o{Actim=ohdZm17D0m2<&`I^zc(%B zcY6lx4V-xb!!5>hnFG0Q?7lup!iAKdXGmf!Z?xBb%xS^TPy0Pushz*GTZ31k1$vG{ z3A`(L-0Vu2=-un&&SMSn))k1Vw~lgu51`QJpg7jQUhee`>T%+av;6dINcDs23CN!c z^HGIrBotk8J!uN#z(YeO58V#qhO=XTm2CQ+^K8d=e--;J@eRmv=)}O^(I%Scy1hUi z^qv>K%z_@ZCQg$GbeL!2WC=>R*;Jb^PEX^6XQ@s5P81t0y7?<9yrU{=i<%;Zy*{cYLPj#Fd#$ntwQzt5w+dbRPoYy zq;rgAQ}Z{`Jdxm<%|g4u{h%?icz(=^oQ9xyt;h`HYwu^Go?hIBX^GDCVY^MY70+Zo z&?{9Y{$9_UKO|w2tk7rFV!4Abb|Jwj-sTWxM#c+&%EMxMY-z`i$cxPcX6;&QaH1ox z`EEG+PikE%YUB!KOp{CQx&I>TbcJ0da^yxzb!9~VO#N@m_EsyPkHf8-WVOZ;?_nJ7 zIhi(PS47>ygBUca&uyii#Dzv|ejjsv<^xHxCnRcJ&%`W?% z6l;Ft>02d_)u1EqW6Phv_-|9EM~6S3V_2uVPV3iF1*)|=Cw)JzKZQP*zh1nwI)2A_ zU(ILFG5MZ=`BCb>k7*osLE)=f95b(IeC~Q}gW2=B+NE&?I?@kK1bl=>k8TA@IGuR_ zbXwS@bEZ6*aIY#tqfA^(J>;?UX5_08ryQ`)YF!=Vh8c7;8un?xDPfT0-JYcRa3@I# z2T#smBD&L%7dl>Cq+$M_E?CITV?--&};7GH}au)&0X(f~L6OA$fq*v8WO! zRobTJkDXLiy?HF;%*z#zcJEv7-D4eTzE}f0U(@7@5DGIdZpV`_T>gyaC0_6rTbMr# zm=(V$X_BS`&v+KH{G79Q>Eh#m^S41~)Zu7@j`D^VR5Dc#F?fx24|VFKdABOL)0v&D z66AyHxx#S4S|lwNsqb+gsKjwN^s5VW+w7D7NF8;xG&PL@2ZC>`)^XXG*GHMz*qF<+ zP?#-?|D4X_(D_cX_#hiCtLGOF2``+oe2mKV!RY#jw?{`{2|C;C*8Om`LKi9Uz+dj( zyU*9{BdA{W3xPs5a=_OX{R$#8OKGNd4AJc`pCd!wth}tWv9L}GCIbcJ*LUFZ%)ZVs z#n`Ftx_;cit;il-ryz)pZ)$0mJT4FEDPKDoO!|PZ&(dKC!>9Cv9p6-GTD6r<%>Fsk zsn^LWM}5t(#B}N9cT@DAxWPQ~o~2|HaDm|G`%hs(g$i$5)3OqGZ~OCc`CwY$-W;~< zXIX#N=R-b0oLl$)rDb-DJD#-DR*`TdIL(v{ATgVho?X{?sJ} zz9-@F>ncSJ5hJS5MLGy}3_c(EUKDJA&ke7Iqox+pr&w+m;1n%7r zf?~}UPZzRG+*qC`TV4ysbZ_eV8p*B485s}=J23(rcl@XeXigO@0KAGMAx>REEkt3b zXQP_=Koz_)y*n|`UO56>D@D0=dSZQH2jig8r4C@ znTH~H=k_XTQW@U&K&Ny(Tm0CD#PQPfRzRG0PLLNDt5m<`L|L&1ICzV(ReuZQBn&7J z;#A9LCl10<8H6y^Y1_BAc7JUz-z6p6X=%SlA?d&CB`^K2rDJ%KHXHMC4|n-H&T77uG->QV7fn{Tn=35A8#dFEDKsAiCC9L?~6l08bPKl@b)CTBGVPyOw!#0UL|LTGUWzbRCC~ zOBA*%RJExnqfNAxtOTuTCab}wk22d&Rmnc9(`txwvTBK}7^o+*0o8i9VG8*sqVRbPj}(J-ZW0XhX)jqt?6QWki0yNg8>DT#PcPgc8Q-SYF8Qv zlkcYux>g(y<0W=FPQ{tpk^#w!L0bGQ_}V@gwavP*SyB>yU`=L!FLDLvj8e7W;ZOX) zpnn?=Wy*3eQ<$}SFO0mBU$d}!{E;eYeHQ+xfRvm=BIxc^Sj+a%+hBit%iuoV32tw| zW$55->lle(k+al3yN&ot!x>alC$ezIa&dE!ECXX7$15g-S3EuAhBsKHkov~9q##;i zwlsB8o;IG7xy+*Pr0+(($i6XVdEREOgWClg!XdhNO>h*}X8|$_dWq87^Q3tb7xzF6 zoQXtJ+aX;u&=>cHz$OBdHv+#t=_;T=9acu81H-|~vmANRLc!v6B7>Lq-65|RTsRqf z|9fb_SsuJeBu=r_1d553h@Um|Kj&0g4;z^JITgVc=ej@NhsD{-_5-C}4og#Z=QKBo$RU>^vche}sPh(?U8*v}Dy{B@;311@|%i672QwLADXGv z9d){&`&as7zdCX}p|fWnhy8kdyNWgVUuzM6 zkro}C^vTS!W?_-QISh2o?3aDJsFg1(_w*apbpp`$0@cO2nJGu{-FYFxWI;qdxfLRt z;d|=d8YJB?x0)Wuc2Hv^e=p%W&}jx8FE7{%yktlW)ym2U)7^mW&sPj4IX6M0qW)5h-keeI{ zHo1@#kc&SNWIag!(FEx^^RorKuEfNdfN*Ldkmnyp$D8ORI?O1S^yLOt9tWyW>|fwH zzW%f#WoA-4%3)frb@2GoAbm^UOAD2>ibs@xeaIy~b2z`TdT90+W@TuF4EXj{*Z!@F z4JBlE8mI^BH0QxwiV8(eS$}gFJPVqz&$NGn4fl1GuF(wP!2FYua6=^hdk7R<=T=7& zL$)6%%(5+QTGs@FpB@#;QzLcUfHY ze0YwNQq9Ocr63!!duA`Q(xk0V4~5}co81=}QqGyN2c?x^{VSo`nhIF_>4I~#+BdPM zh}3Z{KC~4EPYh1K{z^cEBTkyoE+ivK0HY82A5UY(^agT2Cja@7`h~63$U-6Ds}DP> zPc}8V4)8*jr0pGuYgUqGX_-K2F;;;SqWc-ga{+Tc(v4l(MG{ zIg!9qnWF5ng6}8;=pl|ko_q7BT09w##&F$WEt{FmvsyGNkTuXrqo{3yQej>%5khLz zCkBm_o2%v+6~b(MA#D$DJFqFhRz*RlHT|fThV6kPapEJsns^g5JQI~2!2c=i9SGl+ zeZ8GC*8bBfeEU?9aWΠ-~58(P1&uMF5tEdN6>}!95rVorJMjI&aXPnDhl!z6eK^ z0vvVgOb|~r@6{HEJQnJht1A)fIa`s%`Hc#9`vTUP%xEbmEuE@gi=@fzU~AEpZO%e? zPba0WT3t0*S%Dx%FYLI2&a)Mcr$Vx0{g)p@TaZ3A{#3n%E>kx7E_&JlDTU+MCXXH1 z?ga9A)iv6ED|%~<`b+fs6@)XO;b;C(KC%cQhcmV6s~&A~Z6x5eKN(Oglxxxeh;45q zj>lpkL4s6^yjv8p0H+$S{U&sRKZp-Z@-b0N)$W@ODvx2)!!^7XYA=On7wH&%AaeS` zdz9@}a|~+7#1X8a0}fdhd%#iBx{&h#Z==254bnPX+thHf9<6nsbA%Xm_Vb_5VLt*| zR|jakqNh}-=LM6(w5GN&&f!6dM|f2TVQy0jpa^^WBEg>s8_pUPsjPt~-)i8de}+;G z*MoL&{{X6gMF}mkFnCN}!6L?Z^K+gui&IhWoihZ1qyqP;F;e#(t#yX|+*|;)CsEOSk{KL4P$`)DC#h2qm`GE1h4UKp<|Z3OAhl7u#Z~RNxE^6TNOfhr*c6H zit*i^RHy&ChoEU{p6MAh%T8M!gy1Phv#qOoF)jfwyqX3RqCqoTk5Km1GU zd1#9b6|}H}l9eTo5E|e|`gz&_kcK~?7ZM@B-H8yTWYieR{9G_I+$Zv>PiElpFBzJP zAP?$H>u1cahW0<{Bm~>h2{F@I)~ovLpN%h=TP#!u)vO2f{dRR)JqN8V%0}02=Ju`K zyh?Q#tA9z)9KR<>s*Y#nSKdtwiPRM*mKEnj#zgmHa~I%7V)xe>IU#%3U|h_H@7R$u4EbBs!VLeR9)>SX%fo&|H%KWK^$2g?5GUkOh( zy*bpEHh7`itJIY9o*26MS{mjXj zO*t}ei{oM{i;0kUu}N8O@X221rEqHYRnH`Ky&Th7S3r5r%t}=Kv(4iTxG9{}?0Z8y zqj{wDo)zL8_Ymfd)QB)w2V44M!w;+KsPqOpH?u2)UcxD)Sy%!zBy$w`1)GPqh)f+pjb|%xE_ylLl zmkB)E8_p$_3R!EL#D)N&&64AdDY|RW%tj}gLq|#CT`xuzN2I0{{IWLmRcL10v%Mp6 zD)`1cT(YtRQRPZCMCnk=cEbVP^FL$BP#hhx_{v77P`{r%G`C_2m2w6+fw(fYPYF97 z4`TdgnlbmafKelDBl#$Lio($QZ?kc=MbvW|L&Ec@O)T1NA@l;O7MIAte`OOk2mOYM z91TOE3;XwdyJ$|m?g+?yz01MXx5z((H6p*o;D5@uDYrs?d^^+}!>>fcBJywM_yCO~ z6Mgj`1~VL0br)squXd7>O7f|Hc}aNsaegSB%xJER%>eV?@-jC7zJ7)FQ+)$S439b| zk~;fkTsa!V6ben!SRLF7E{?smn4N#yqH+C?K>Ymn&q44__cq%_Q0$fWyPhx-9iwCR zTD5qZ5b?G2J%msa@}lF-adY|ibH!x@<=70qoiQm>|FwqBS$xIU|J~BETu>+AA;5O< z3(|BM@4F%{DVSln)3g|WnD!v_`f`KiWA#%5G{N|_3{{82?)OaSLV0hVO#cJ=M1+G^ z6ebBwe<+nDjz&qRp^PJP{4yhI-Jcf8fp0HFQj)Zw=>&+e)iyF&^NW1)zws9gU6=BPo3~!yIzhrn76s|5hvafRRrk~mbzw4* zWkYISWj3)us3vtGsoImxo4iJ zpZ_`d;@4+5_4ajxSLd*A#^v~&qN8C57+kH#Igkp1Y<;MMuQUJWyV_(UF*G_wIU=u# zEDgE|FQ>TwU<5nF0KaIC<=bCNL4bUncetm=_&DWA{+CM(y72V|Cx8T>Ycm2xhiPBo zHDQpqMKzJ_o(4<6F!awi#i-{$WgtWmj~w@Z$BmB*2@)DR2vZr9yDU*p5j}yKV?llQ zEDK*7E9*~A4O-W}4?q{rN+~3kkc@~EdXzAzqt@6CC2(vZ*O-oZ#=OLynN<>CS);dd z85@GwL-UtoH-R0}UXIXgcHH{megvZnJnUfny5mEU6w)sEgrTt5g7aIoS|$C9s5VT< zaqJ!%7k(DZ>a%NeOP*>$#cC(Bp>9C2H51-tTi_S`x=ch^Y+vleoX~7W8+9YYo`<;t zt^=t|&$M+3V*Uf`7r7bMKE4uDv>KEXD|fgF2)~1`9CxZpVW_n$Y$V~Vi;idZXI4U$ zS0^~89)k9OHef+r%4D~Y`R4578x~Me@Y>>0WR2)@@xUw^Ran5f3NJ%#(KyIUuD34+ zMaHldl8ExlHy&JLGx}*snwy<4pnqD*1asXRdromB%LN}Y#arkP&2?-KFkR8M@q1ZJ zx%E02o1zDazPv4!2XU4ctjB-QY|~gR(zEcgyooz)h=6f}`e){EZUdijKGui>~ zK-m4su^rpoed*U@<``X}-Hctqnqu)0qBY~|OMV$s6pbTqx;Mj_Qj!2**pxt&eh7ym zdpL3n@6m#XWL7$urp{#5vmey!u`_s+0s4b6)4zmEVskjj-;Xd6j}E2wj)fbfi|peb z_6+dJP0fOEZ#sVa$iJB{sg6C$1cm!QK{-QmZg#)%O8!Lq{By>Z5ZDdTS^4f;%@atYq zZ7kOO#)KAD!J9p_*ap$_;aY|NCT@=O0SF_nKL4Ku&~ORx?~s#L-y{uaJuk5C*WJsm z$3Ph!HZ>RqQzY7qsOv0=e5`D9mmd0=j>1+Y#VAE#LU(p+UA8$h#q$7*Ti3uJGT>FQ z#=$K`6%Bv3G6O%wtjCW5ze&111R*gG$bx~-O`!Xokh}BXz002=5%0{tNTKNs2=5(4 z1+~<4x;!f`b0PC%)cYz@XGnrv(Q(bfc3&>@1GDjSse<5=UL*3(l$8Q-JE3(Kb zVnYKYZX~5B3V{!0(ulQ60rOCR)eQItd%WHd1~`VYO@IwZo0^!>NNhkrSi-jl>460x z1$$4KYNGwu>NN0yCGn21ibUt29q{exrgc_i9wA|+3Q34!#+S|$^aG&C4Xwior^$qh zbrgA8X_)JGH-6gNBtG|Y{}~oE)4-~^aU?cR!-HM& zSr#Y|s;2e=>GykvZ~W8m!Kl4TU85PnMA2cQa6E5FJ0+wJ-_Jy4$5XGtAK}K<)BPv` zZcC!$2;mnk3Pu$Ai92(0_8nkeQUFCak9=@yGn^>1u1fh-tP9X~U~5dgEdKajUq?90 zegeh5q|-6Gg^l1})X9mK20*T-KE9B6~`h*-PK}{5DOk#5E@3BCAF< zj@B4EGQ0wDl*zeNxPWs^K@47R{ZEt!7-{dx6k%NHe-~VBN5jJE$w!>a$C_*Z2|Rwn z|7Ur{rsp#KuL0w{=DZOc&w1})BM)2=dDp6!P^T@4g_Q(Uims3REC@!o2P%zB%}^Ih zY*v86nYuP;85B5RO>WW!r2pYig%zF)_lLq_F6Qw3-(${fUU z_#?Zepsh~zC{TPvHL|dIW$KDQby<^PQqF}7D9RHh2}l2W`?OJ=6HSQG&(vFQOX^Uy zqP!d2X?Ep7_Pn?iphyAO_jT$xEaZer;a!`h*k0Krxuox=^{2jgJ@ZcxYO`pJm$5L@ zIRuEW$2#8CdeD-`sk*LnBy$eGL5Tbw@m`-B(b*dSXvVViuPR&SXh6COkk=+E_&MjrI3uf#f6XAEjpA+tOzyt0u zBsrEvUX4nuzDb%g7b9lj7afSM(J_Hx5`Sc>;(8)@04UW#=1Zo4nq-ikz0a*-vPBO? zNWBgm>MCtgd)z1BxBuOa zm{CP1DdYC4sI5=BVZkS<-I8;PLULjyhm1$`=oLMRyjk(Xq@Oo@dsP(}Zujr?C`0)M z$3rQp7gs<|fCGwUg;dG9f{C(I=*y2mhBzGNM_gl^o5s8cP5VIsCeE&{W!inR7y(=dEV zh95+gpPLM3IIeIO6_iuJHR`Pd7`@N_hT9Jxk0@fkF@ByzUi2@$!w!flu4c7bAJt5U zxp}2L$@p_tknWl)D&mTkuw8oUYh%0T1jx6M<$9sihL!{dNr_u23s>^aj~&VVFkWRy z#Fqwz`GvD4x=aPr{Xi3r=Orc_Y6k?eHOm-$ilO|v$8Jo9o6&RRQPn}@qZwuFEC7|< zg9w2jWm_WI_g!L$>zO+zYj|~C(bglXLNeMj#8;{DD}Y)Wv6aRq+O!UIW{M zi|EjPr^24FJ(81Vk|*lFwr|INXXBuU?U5{OKQWfldzIlwQDJvC0lvLKb8*io7!p?8 zTACw(+p77OH|}I2e(U)hwfax|(aVU0!w27oi6|Ja1*%dx@ zVH<@-vsx~@&3xs-k*POyxT2jzHN5>D)39hLLPpm!Q_gp;FxTB&bQD?cMJla-7`JSd z@hhLh0CEBVv=7V^Pyy8c3JCBoEH6+mOauBaP}XZs;Ywov&1~Ji5*sJgigpk8*#vB% za>!Rvg)mFm_=*?Q%gucfX4wq!%IeU>ON4*8?GIxJ)IcE=de#)BvN(jxuwYRSj>nnC z&c$2~ZVx>6pTSW^9n1FK z`@Q0P{*yhDXJ!v&X@4b51~;%DcgF4-yb^v_Pn7>C-Q4}1q71t}-us&dpmTL3ZV?p% z7|*foI;)iCj zmwK^y7bL2>``EAU2!o5}Q?yoyBFP~rHwlM0l$knu`yGM?t(KRnW51^4FxWm22>;%* z6$L!8>K*#ou8}9j9-=~HO7CC<1*8>0UuGo@3WUl^{F$*nfbdP_nj6`vJ11o{k9t1G z6v}i4!@cGOhvG$)scTkym%}VMU}^x}QpHKimou)M`C$#Grvc@ojD)J*^y>8*woKnz0-qg=}e zHR&zY^^JULZ6fGwblKCZQ{A|vvo{l)gnZk)&AeYd_!GoZ`+-hoG8!^0;c{kK-|bDo zF$(~a+}xRt^@%;(^w=gbSY>>d3i3Z$9E$-;Cei=K9k;kSXceF+!X&%U258}TsEH&L z>jfwQgCvUkv@nnnpyXx0=eAUK4|1EEkws=Ymg|g z4nehhs%OUSqc!-dwPZ6t5uR7ee#&#rB!TGucOF`F$eSs$|S@2`B@{*9^QRgu$>wi%2T=@CM@nnSKdSu)yQKB{M(zzOO(FR2!6RFwIn^)%XSgLyya%M{=b;^l z#IqLqG69r?6=gY>R9xOgqV`{JY&uY6e=iV3QWla4N4Rj+-~^dvuIo%2QXS!?srIaX z0p`TdHUtiPWc4sFXp4#4(O@xZnYCo4u!z5@xl(}60KAxROd=LxE8Do44K_tSU82u6 z2$Ym=^*$Z~v5jGgU0s)CX-qZhRH1wODwz=U7Ls%hZY# zL7~#tU9HgPNt6N;k8*dG(Xx6Lbu)k^r&s_+_7}F5OCCkcbT_HB*f%O9LOXju|71rp zGE9K%{+JckQXV-JEWR&b_EL|$&?2NEZYKml95pHa9lM(Srl>UJgqnv5v?+WUl zteabQWlsgOqeYnkg?H3Y^yjYL=K}x&CLQ_YA@p#d`$J^z=O0Xoo4k$&G@w@Y79vRp z)Z(8@La&yl=~OQgo4cVEC7?=G46>xM4Xf*Gn6tpEO*rlr@vKX;%qi@Eaz!RZ@1RDB zrG?9ChRPtwT0*(t8zmv5zB33`BR0R_#GQ$wEraPVgxeYX? zGFT5bn4}NZj$`-j+`yVtdLZMPq48S83mXQZMKuS@v@SHuZm#OZvyy`tjkNV9|Vs_Tp3eylWEVJ2`W+1bwVZe|cU!91=!#ellQH{G@ z$a*j^z2E{g=v31Yf;8b#*|YbuMoR}`QRVwG{ya8FcgI#Su25>qwpm{hI0o>S2hu{d zi(zJ*iarU@DK#bs6)zlel&EBlY!w?$KR1xR$s2YWoln5mSAMMxNeZIyN%f9K7dK!V z^3w-6Kgx5iw90oZ{>W|e5;R)(B|{GS4C~bcM#QtI zBy;m`PuQJ`o=LTHSb;6M57E!Dx#N2CS{Z5do}+6Q9#9@XuWma&wfHjieUiDS+~~RX z-Tv!fJB|bqd38S@B(odfhXy0v!wE{oc!%9}IP^EHOV-Fa@SIcf&kTH-=3)O+%9D?nT#O5W>;|j(OA5Ph;`o3JiSe%0~i>Mr4cE4I5{dK=eg zX*91C(kRj^T-e2}RMlYQs>Xe|AC181kVKn|&|%V-0q+Pq%#N)4>d~MG`5s6}VQl#G zOBC9rF$yhd)!a`Dl{|XojR>R|qTU&2qZ4-Gvnf|x6tq?M_Jgcp!6Fpaa)5IFz z|9cZ^=!)92n z(Zl-c+R}?0L!zeZ_#l#b{i+Ib|1y(qXu9K}3xESZM)mw9s{C|retjF+u~{q*411EQ z7?_<)S|*W*Z1s`ky^z#R$gCMGpt#KGE|_^t?BDp9TlV#WFg<=L{~p#P#n_izlr{4b z=NYMwIJr~;NJUP;33wi}%NU^>xivLQV>iXUm&!}_#c;qU%4rY=u`zZEnxITO>$afw zK?g#!vFp$*hq=ufxp=b$6yPa;51F{XM-3iJ#XYC~|DDxiZYb`2n3t(fd@fuksdx&i zYP&yZi0r-zDL)Bg(^YJ%+Ske)>Yq7`8N^X-PXi7Xaz^VcV8AwV zoqACD{e@RtL7`CyX;%9AhC)m@k)OIM^Rq6GBP-hGm=eFFM$2PK$G6=h}Q|;Jj#fh&sSMW$iKX*NZ@E7 zN{-RMRfr^0rzt}-H^+;IFZsyyP=U(qv~V)R}Zf zI=wztFn$YCIq0eaqlkow=|EENt$r$4xsinGk^+ZTqnVO_T}sYW9$wJ1bK}0N<%#>JTpjSn=?khJp^Vd_LR!x- zP|&t{q^5A0e_XPU#Zk{_h^b!n{`24F8xjJKHAa@t6Is2j_bjr6;Z&d4N{ua@@9jLn z-gEqP^hnDK&vp-!Oib_SFl|Iey;}jn-E}y*SWYvtBFgGIbh)>fAo9;==#lOb6REu- z-7sMMnkWa}ENB1uKoBYVv&WQDzhB2ki2LeS$g$(4zAHu}O@kGR1V`QrYG0yQpQh9> zFWp1SnRBc^b9ie7X)14fN_Sn^YAl_IB1t{3R})1plZh{_4a*?#mC5XvI2g5yI3}qN zp_Tp3FH;vjV|Hn6)5}6x$%^o1RWee}9$wqj2bKIYGZJFblsD&J=YGzTueO zzuSKG#1iHeHe`4}JHY1!>z`SX7X2TZzA7xPu4y(%0we?t?he7-2G# zAKWFly9al7cXyXFdH?U+&NCN#uf4juy4pzQ-Ep@?@f!0ySSwi(^ux(vDKc*BW2Q)t07;7SZq%Cx4@8l`G@HtgCL`n}Dc7 zBiQro5f4eT@`Kpl{DpSoFTzwyLY`z*8N3k=eTHgnm{to{?$0@>sl~uY zx>b#CH_hFqt!^)nkgSFKpagxc*@wu!=r|pcxSuVxm|=^oupo3(67xaIlm@CHM&~dt zDqv~2sOXgju3|XiXZ`YAOvl~{H1sv{`Ze=>AuX2QmwlGp{-lcq-KdK<#F}84DH;ux zH!%=r;JBtopLjJV*gO1$L|3E*6A`u##IpY`l{;f!}vb zj5xWptA-_xK%R>{l{?p+ebu?mJ;omo+(cOl!X(eS8n?4VXwR9cK&8I0{bOZ&0ke81 zroK18IpHuEvhgaa9tAa{wcNql?Wg04&INlzChtC{*4MFTx7++AyR(m26iPp@siD22 z{6GWz!CJIGVZZtN2MLDGhcZgjp?Db2-5HC?{p?An$*D*k?(>Y*mG8W;92FNy%9Mi! zlHy1a=ZC~FPcnV30to;Yofy#5!y2t7Gsq<}8}4^Ca*kcv>osNLdeG17_shu4rOfT2 zhQhGN>16p+jNl}pMbU8>M`?z;-7N5tRX#P@Onph}4*(zGB92m`hS0?H*t}!S>xLne zChuWh>EYgp z)aR+D94W*(BCb2w~DoSdM;T14xgz;ENus2yPCIOwu_<=oKIeKC$%hd}> zTt6){nGizDI0tcYloy!J%P^A2(`YD|x3bGr*=^Xuq8#ENyIZXn?kQqZ9hVqw5bdhX zm%a|L>x58%%H~-N$JuR2)1-=C`P@E`@Fb$9vE3p;9NMv<8MnP8 zSLu(J;D?Zi1Z{qpFYS|p;+KHf%bU0$(8xF1Z>|EK8rnSCPx`Y%uL~P!M|%0^`h*|q zHfP6FY!Zk`z zH#7mcQMUYtQC?Y+^!4f37B+P1byit?nJc9sV{*E0Ljl&~0 z5c**@U?*pUX@@Un>R#;B<-XRW!D|+qmvGH6sVgNjvzDt$*j!Jo2%wJMS?k#E5`oW3 zc@-;4_mf^2~f6%e=8s0Hi4ms(74^Ye^)>%}uAOmp0=fxdzVL)Pi zdTIS>k((2H9CQj)KhXKB%*@{GWEXTr|K!skKx__D;$Y4s>(OgePi9~mZkrcWTb*dX znWwK0M|a1bq8dI2G!P@?`iY>iDJ*Q)I~0E#Aq-U@Eceko6T zoUfv)gzcZ4Z7b5c1OAvfh|i6Po@ci8Ez&ggn$D=q7E#qGaA4sYM*IuA@9}$2a`-Wj za$W3AKjLw~8FU7Ub?WZniX$tW{_`ggHaqmV@4ZvEEgGy0&JIhlqyyHph&(#zE)56_gTj|iPzb6(x$+>J36oHS!WZLHZ@)-9%B=a|I!I+)?bjui}`xIxoYr#G4o-ulH9 z%FeCn8>sekem1wg9aZFNh0DW(CbTeS#E5chH=&&TrSeF0$ zBPKIaxTVbva4FwmLo`yr$|idPn$)z&^xStJV@6VU3{wCBwV9#V*C#`q z)VtnrDvCkM&-(-V(V=+*b;2I77RXs|ufEe>&KM4+?cuH5IV1qIvmDd`T|53(!#z^Z zDFe`;=|rvbN9f3ez1$$?*hs?)yhCI>T3j)seKOA#=$$eCQMZuWh-4@t8RcUEH~7du z89TT#n2OM%K#tB(6*l{Z`)zo{B2 z6HUrCNe;rimY6!b?i0@+sWu1pT9}^t&cd?ZhG>c24vZw%ek(+4PnE@}@+S?qgF&5TW+{OkDgUftKOGBL{o9Gr6b1TzqP3z#)bD17fJYU-!$6&i73=i(Q`R zYixrak!WATrcYJ*#go0c-{=j1`h=~*SKUA(Wfg^E(F$MTJxm$AD4?O2c#pc!sUGIM z{@&DAJ{ocd*J$h@6Z*OWPg-lgS5rQW#cDiGp4zq zYkQI!{${Pho!S`fBh#ea96~VADu*+T7|B1hbS7)neS{a8r>rj7?O=!R z4abqQHzCVr{p=?SI;Jqqj7Y1x-XP#lSkvmqQJQ~ZXJpdZcAU{EFW8?qu>c!iEJurk z+@~c2J(|v#UFTTJ+w#bWzyqH&a3?EOi~xf%1Qio_CrDg7LYo>)no&((a@o_b@CSER z%KMsS7PrrfnCTSru-NvCq+MTR2&-= z-wdv4L(}lZY=}kyl{UCTH6%TLo_-HaWZ!Xpxl~=KvqTnXHa5JsvDoVoeF?K{4+Scj zZns_w_;=@!&dks0_xFAM)L8iTDhVsNxbB$+9Syiu+(|p5hHm>Ucr2aUU?JZW=0}Y))H~8G0Jb)#1a<6m zbYKhX*x+gAu@~OMa+jxjYD?JgiDs7)+4k6~uxe0bN+WnvB)n*{2LH;>*@G{#s6hPY zL#RFiU;CaS`ozqZ2*&jjR~7p7Om{1O?q53k%J!IZCywlRSmx+Jb`E!-PK~6ZmfV0?AA?V9JZ)7wpfqSt+uvUT_?-((S>R z;EcU7uCY?X5pZSlF$GS){R=72nmag~Q^&u;AXWYNfQbkuuji#%aBuTFj;V0y&KO^S z#z^jiGDVU-t?JbA(Y48`;jj)U;zQ4T$YKd|v~d-6X<$n&b4tQ~$UK?4^rzxt&Jc3i z@rfNmel)IEbTb|&l(W;+$Eq+ecUN;b5Z~50aVIf$(vo0i?8nVXvlsccW$`>n9S&Hd zcTTh4&8}aqe!RRo)E9wc4AARQm=_my;UK7s6|_)vDEv`U28 zk6`GTnCcE`m~-=UE86|$aIhaiEliqHw?OToHIU@O@pJZq%vPqaIb1)0d1%F-xn3jYQLRxK4$inFt^!xZ}E( z0^%k)c;^S6aADf?v{2h=lj7r>Pkn0YK9Vy$^Js<%YyveUC?#EmjhFQR<-jsbW2opKoF^|VrWNfKry6uFc~;#6eR10+k`pU z?+C>zrDp=Z2~`mv5kIvfB7lMb^MR)tKL;=*rW)jBwXOu2R6*M$&VsDe7nN5~Q^uh* z6uPf^+57#H4xNIeM9fMR9&U1k-DW40G8D%EW-!Ms+gTBYmKB!@A;ju;tI0GQZ7{A1 za}ov)EB4&xpE&Ix$tcs20YKF{!2qzC&X-RH(+QR4RgQe|+x9@HY~uI(9G^##i_;er zZq1}=nz3T1`kIMA7#cMGP-{Fud)Cpm+nhI(&)Gt|ckzobhpO&(mQ1&X-i{HpG(y+GJ z>WeW^Nhy1jtvE6*>zV@c)VI3Yyw0@nv1L)YGIjD8N+i9U&+emUQWVil_>XaYjFWO(@-%3m=ZkINQxm4CN)%;QhKQ}jD~)#-DpzM_{P~q`iVdE8^9yETf}yQoGvyV zQ&drdjI!KH`g-m5f?y?TkASu)G!JWDor=_xja?I&vw7QRIY=p#3Vw~Nm+8^8> z#6AOH*~_ai;ALbM4IwE|p)!1?YKXg8x9WaYY$HF$XS_=gpDL-B=$P6YV4WrdzA7yY zvQMc~r42EmIoq{g;bRHT=fz9nj;3?M*?_%yqybrL=ce+2@hif3TRj&3V#&VFK+5+h zF{#+L6FM%bXUQ6HSl=H+G2)N#)S=Q)A>V}|3Ihwezt$t7b>eNE?sC#@K_5kFJ*!FK zOZU3)78P!4Oeq1n%jFYs;>{Tk8GHwpddYx@R6}DQ>&}@uDW=RF2bb5flkNJ z`-YGq~zOISj6Ej$SB*hIg~Lq7ATxevjXI zG8RcDp0f>R{q3unfn>~zyD238zjT7kqs!(^Bo&q59c@v~wjT{Aj~VZ5@ccT=cIC5~ zd|d!s$Siup1CVB^aRxg_eLaF9HJ>f&7|Ss*%JiyNpFZ(@6>HZ!QWPiOCD>iB`bfCO z>McTg$Yt@2ne}^>1X)izIOZNvvkEGx7a}fi#FwTPBu~@U%}`C_O}6pTDoZpjhkn!uRR^;mx23yW ziQD8L9EbBBRdv)amU7b-p#)PiNN4v?D=-MiNND#JM|_C<|gT56-|m)DU4)0Kzh30}(A zCsvF`H2w-ryk(*D{sGJX+~{W0aNliO;>EPk6$#3S74tEYjIHyj+6nDPWswMZij@4^ zlJE}v^y;j9;plBRycRtv%#yh!E!{UkVa~a6G8` zPV0N4Z!$c}>0E-|Pv;Nz^9!Dt$#X3>XkoKu*ci)-1gSeJ=Lc0QOTumkCBAk%CZo>A z+nnMS3ffdK58h@t>o;r(xzri(`|RPISa6S4z~4|pr%S7Q)L0~x{UgMk8=@QXjvqQ! z*Fpk>u=}zbz)D;B z=TvN!Ub#XJ1}cJUyRywf@!*R^oWIyA@s_O>;^B5mWE$e5M%Ha#qRY#AJCL|=&U)a8 z*i&?D;mK<7m~z>Mlas{J6U}gBWl6{J;>4&@o6MMHy`cvNhkFK~8G~5*Bv=ESI2Clh z)@8e%S#$?0`*>KDb=~hZGZ#`XE6$038S(RGKF4raa5tc={^Ku5{&z>CcD(zGH=JwE zUYl>0`LaXfRhWD0SN{^2R`EUBOF{~qIkVHH4s$v3-vfm}&@$B$Y?}ahH>Y1^{BZv= zzz?pyLFZRZ5Rye631260>$v$3a@YM^%S9CSM+qC93YXD)5&5T?i$gjGeW(Lqq|~&m>`PeYkEcFe;6FI2|qKXc^nR>SqZm@ z9l+ydtd)XL6-(e^r!>TAOS5edKaE%`I7eh}ZP*mB=ciS8;5C! z`a&VbtwlwVSM~8Pp#FF`KZqq5Jcwc_*{-7V+ZC_vf|GqC>`-fe5Fyvv0k1+L;5Kc; zQd8Gurhkrm^8*>ks*!m$*W9Hh@EAoyh(5oUIRT@hY)Sc#uELNcjF<-cVAQ8SL}SCR z`We$cMZC>F8c_Ix-m(hmV0CCq4o8|W+Kn$-rM%#(>_siGXD zLz>*dCBhJT0pWt!@bcXK6IhGb^k7L>q@c+`Sr?V(Tb5CJp`HC<4H3}bFX*7%B7J`3 zQAHYJ%FsQ9IU$xm%#7hhFkG=%yYei9G29?Igip4$qE?_Dxl!`AQjTfbw%*@tSGj?q zH5tv#;@fHcf1T5P&}7v+Xhey5fJCChJPllUB+w`~#@Qhnb4AgIlZ$Zg?H7fzJdDRB z5uc{?Xy9NZ$!M(ilJQu~F^4onEM$inTaS}VCI5RK+GHfH$uCe0AG}}-cf~}ro*t_q8Sv@yR2uz|kRR%dT|J@=2uH?3 z`0LCMa@Fe1TV}luf8&Fn19@S7OAhTL?T0MBeCRfndbw$?|Sp6Z?#I4d6jT!WJfaf>3?eb<045?Q3V`k9Q@xk?X)s^rg8f;GO^-@M; zUqLVIay|*QW8}dd11YX;w0R}L7p(RwYs@W=9y4TU*w~R|kvrH$7T$?NocYuTe?Yl4 zK;KNZJ28Y(++@MzREo>gUWni2l$KM2ADK$YKWi6WnDQf`1;UrZ5q+zSa9L{rIl+yc zWORxS&*>n-ym{@gQrR46nv1j#aLX( zE1rwozrhLKes#bXq#xCl_)3J!tW7bz#WjQBYJ=f`jKW^EuDw zF03emU8`1v6;Okc7|m{+Lm&tVNlSc|0C2;txu;WJc?l3WvH)23K4_8Qyy`?imV*T6 z%{3UKzu30Icc4fHQ60*HmPJQYMYNtzQ<(9}bCbGQU7^|rDSawj3(J2d#V%`|S<8e8 z+LC3FS2v)lJpM;ndx<9o+w?SFc2ru~k%rBZ=$c zB6_F;6}RYBVkfjYXyBr(%6)fW3#+TcEYYu-czEH7sPvWDNy;OQUf99uOTaCqxj9Y; zdc!YKgt5U2VnRdqQ#bLJj5Mq>Gl5JvH| zijorxkgA5}eZa_IcSP?R_3I(>p9ZKqO!6d3fsCrHYh|2}cCg$0D4{4Y_vVaWBZEJz zGYa3O{ms9K#1EJVb46Kdjt&3w7=_~15@R&VHcF48b;%*`j?zV-xtZadeCc)+j}77& zJ{L8K+2j?T;eVRW#IQ$ZXYS8?-%HDpa~9MiLo8u*YzC|10DvjZ2E@8$$%3!OZ~;IIXzyCygqrp`OXFDCTY>22?IDz&eA z!Nxo`yr?@$==1*|CtLXK&z!0fGh%#lH-G}$u#!c*ztcBV|rrRrpN zfW`kvemCQHC579shUur&n7lXr1YI|KkwheDcJ2bp>2SK;=X`@UGC^V`hy~VL(l-zo z(h*`#e;vs=JYu#R=ffZSMLK86mq2N#`y#pBvgF@xmNb_QFA6~)md}W*%8*RISQaA+ z%064mp}w}B#IF#$R_Ne-pbO>igswH?b-3ah%r$io3> z*5FB=emMhQ%pPu6{uRT%s`i^?%Hg(&J#RysC%UPpa+1UZGsu2_#X)tY$lD7 z0=Zo-0Pw{kbr=YiBj|T{$TDh_7zh^e$+NXwD+!wrM^Vkp1fhWXs2zR0)^dQ6G!e&n zF!J{41&v zA3{IKIIXgp|KK&pMX-D?_hviSHaFtJImv;Fe?2hd&9%Ys=l`b+5&bGtruipF5W`QH z)3o#CCvUPCq2X;cci&|*-SO631V=ilZC)CJ=c6m6>Gi4WRB~t>dQWC3SoI%Qhg6=lYl4((wyJ`j9hN zUpra5OuGBWY;4q5i7ooBAL8gV!hl>#lKs5#EQ$jdjtZjzOdj0Wl&XPBj!hT}5N!94 z|6RmU9*GMp%yIO|f-(o9mPh|ycB}8dBz*jloRRh=uzgS`r;cv)U-QXfyM?!J{)X<;&@nsz- z#tdTDLt|^J(WCt@r)q+KxfOzs1MnjsX6&eBu@yo92vFS!v2J?K3S*ey;x`x5boF3v zen!7@$1+3p(sz_0Mv^LmAB5XZlU-3W5?=*1WJ89ph@Y!^@^v&n7F`erRym}?g^u?J_Mn1YQSqk}Cx5ck z6@*`%q+9~$J!_(uC@71{?a?<$f!7m4GJ4}kTrM`jp8Fhvfa1jSLc_H0T;BXXGhw6& zQ~Xh?ZaW~0vM$Y_)TUjz+DKts3I>L&&l|Wrh-V}{P!@#gTE_;(HzowbE0M z;vaqzV5gXsp zt^GwgHoc$0&QXC;Sfbb1P7b3NAvExj>I1j7!+y-caiV!X1bNA%KUTrr@DsTuHSuHi z55b3yC`EbG=~r!br|XbtOxq6M$ZBOs1b*;o5Uc^K2}a4QVO-Y8A*0JBVr2GqR!F7O zkcXpZPP;ic`c5NM=?1@oD6$pLo+|PvVahi!WOE%QJ!}se6LV#v$19E;a)O+c$rC}= zt13j0suk6fj>0n(cYO=PtYPA$DkCgM%pp=8<6RmDv}&Q7QyP)y5&EPg)x}i-zp?E{ z{==Wz*Wq&U!T55`-idY_7{eX0z@UmS zNsBq{xG3V#S(X1&*J!VW_jBrlvamAeXZK-iU$?2OE zVk|GuLE{P!gL-Qk3c4i2?Z{z%_xs^MG@MB(MjVNH;1vYwi<~d`59MPH;kCFph*-mG zP&RgsE6z!% zE}s)xRb(JPCZNKHlAsCb-%muuzM|F+>onMA3#ms6YP1g_!+Ya4*ZEG<%f1@K#NlY| zVu+sRbcJD|M;%=t4w772N@e`q`#Wz!Xp5ReJZ3z(0gX4QpSUXC(z=}od+_OB4!KyI z_)VI0wyp@G??A%DZ~i($8!MCUTn*@hTZsEZ#V;%s#pfs}S5qRNHb#uC0B=navWG1$ zmNMo6eiMfe@jTYx{6MRyW|claKnef78d=!^R$DZWE{hjj9umv&x{x2*)T z-x(?+tO@LaUd$9>J#Zi~NE>2h7{tt=#E4O$D>@!2Gu)n1MAdIJct|HwnifB>n0jAy z`NoOb$Z`)Q>ApFazFcg_508HH$HbB6h%sx;J+E^8Ez19Hk#hpGuYq=+6s2_!&bi73 zq8=DStoV+l^SjRfy)`im>c)yd9KmrQ_PFhS)T)_YsesI?NGB=G&?g>YTlsavy)VKN zeDl{~f*!__Y|2ZxPc4KTBlu|7QWf&v4Fcx2!+&uX#Nae8a-nETL@=LXYMh zBfk2#kb|+~2^WcwC&b-xf9qKHk)=R3BVzZwBU)h9nGlq%G!6j+yTc2h!k1=D5+ulzF|FV zX^CgW`+og$5AU1>sRf2A&5o`8CSiCJDf+m%4zK91`^QvH+wE5t1WuoOjrfEFmU>Tk zNI@>Kj@u^2w{PDz8n+X-P8(D=-~?Jx-QAnS_wXt@49|+yYfLvBGvB{a%HT&Im$wbp zZn}0nlL@yLM)5#Kf#0u4xjkg}+a1V52Ct+=Rp?&onwi`5Mf<+cuDEU2VGHQv6MEj5 z10HuAA1>u=IBth8OO!1yR#V&kuV649uG8-~1MUTc8IJj1F1Q=7h8Q;w3o{B&R4@K4 z`+RGX^S#N{HF&tle%Qh)+b0P{ou*4Cj)4p<-HD|dd8J-4{n)>s;pr2N%>MxY?)t1- z>HW+Q^%q6!t~lKO>5xi)x}dD_*0iIGrZ8im%7;)Ev-xJ~OQrj;OY6&&Z%kZj0Hg0= z&0a<^8*@=Dr8O7BEuKI8NG1(@moa0 zZgp66Q8fO3DQ6NW+jo*fJ+Ot?=i)k9)-9xtNwANs@+wz3jfl(cy1}+Hrkcg;98Q2G z8Splv^l<#@+hd%h6|wAd2ifK@zdfh>Hl+2Zq@+*tywxyde{}tkgQ4jHdgX3;ee-ZX zgLR(Mdab*)A-l5jLt%y&%h~fY%)|BS{YJ#J>|Y|^cU~h?(``#t9qX$M@4dsu{q|>) zW7hNL{R+43vWAOdDTXe6axhV;R;X(dBj+PheA0HYX$D18nts$R6%=&Z#cdGf)pqp! zR)y~?+?c?-mDhEus==&;(9QS;L$tE`j~lrGOR_YcQ&R-O0l zt}qPmEBS7q-s9W%R)WFjlNv_D!PxMN+lqHA7pwJ9ParfQBV(xZ2%XvAi z=@UQ(^!ttS^a`bQyUwZi5Td`(;@Uw%sJNlL7k8UNlb)~ZPwkH=cEfV-!8`UiK6lf)+v%=}xm8t@5tm9YY8Qucx)J(4LAYBD zN4c{POBlMH@Su0y_dTR(v&RSfTXxQFV8LUVt!^ZR6xOzHhcB&4saoiQr}XDi^|rNE zsfxBcOKN(WzH!@E?Lr6go;~_yd1Y;=*pMprVaJQ(AEcj!byck&F+O|jfap0@?VoYbsmh(uP%?@S`gbEu|d$zDg%@$h&) zYQ(9)dc=iOQC=(-Uh%Oo!v(ECF7wyQ%8F#{HTUKFPX2!CHoN5-|@a z-5J#w(|q8|>*l>H_!SsOx%K@1Y)z-eG>+21Y$${QFMQU^Xbmju#$GdT_L=jyufb$451f83QF*U&Ua-98X3n z-Y*TWdzb@va=uTr)zz&JlhL*;;PW2j%y7qRO1tn}|jKwdm$=$hsoD{Wo|Jx-(t@oP4Cvf(V%QI9C zDHVwjhL8~PuMI9L|JVttf0d!Q1UMlx$@VU__z=~4Q~Q3!azutthq0qHN%U$ks{fRu zcZ#3e=0wfw#{Lgk-0$oCR4Id;X47*We4hm^UfR*>Alye5ZjjS0hU&&IDMr?Uk|Z53 zd-C-r)AUe**Ik>C`fGL2;Iy3jr|5q4rgC2I=uS~^_>%ceQLOm1+l5}f_xI}CXYbfo zM(@X(hfQQ3ed!OzppJu(k8GZ=7CTSLlVqgNk8Bv$Ha5)t&&8{0f~-os1elb;4rvJq zzdPPfQCA*Li8{A$vl<%*#^!8VEawSB?z|QUF%{}qf2ye9U9YUaZ_2{EW1ug7VdUvg z9`vcbGF;15PiA#37+hP~>Tzv<_0HY>p4(IhAamh4twpydVlSB2xp!_AW}(^1>o`-& z70nsE(31{5Yb%~Ez=o!I#gy5hvk3X?v?O~~CC!%T!sFF`%MW5sBq!n^cW<4WVUtAn zZnAyx5nuqk*X)5`pFz;2?<9kByJMnOHkM}_KOr1!rtVb3UP}1o% zcBVa_o;Ku`)_!}wJMZs#f8wl*+fTVR&G5nX5o2BSwWrTVnX%Pzl@Sd(yFrG|p|76~ z`kHEXw9jTqx~s*6UCD@Jo$gI+bRi+|#DG9m>Ge0bar^y@63Po(_2nK*2Gi8dIxl^F zEiBQDlj_PPj1tOqBP5x3*NS{9n;6T!TIr`3#WSqVO;St4` z8In|SBr6WX6_?|_{IZT+O=^c9$E5Q|YJ~`n*}$oWn830oMEUQsno3 zfit$K9Gz_UTiv%SPDkCb6hrTo%HabQ)B!eFCmExH$i_QWh-H03gwAO~MOS(J)!{hL z@Up!bjJmPI%k!Et=DZ`-Vuqkvp&f1*&Cm1XVDx^FFLiNKGp_#^jtFE1d)XO)jA!t@ zpmNJFWlj#l6P1kQsndM={r27Rd5#G@ zSE8&?(3DV!*&UCR@R5$!A-h-atp#rr;iW83eU*}oa~VlAnFLb**{bK|L9Seir&RfH zp4Px=SJ-EfqD1_v5G41+X@E05_@GL8&dldI==@qFWE^E9rKTW-9USa9nv&cho5qFo z?tV&7w~NaKG*F~IO=tElA;GB5P?}qR>_PXPlxEOy;v%SA39Z@|$D>cC;qvpHQpjDL zY{U9;ZQuisa++Bh7w`O=wpbanP(~`6hm^yzdz%cCaYN(c6X0qf?!x}%ul^Xjs&D_w zcGbNasZi*SBzIHrUqp>L;URCT`<6URpQ5;E3BZTj%ttdJ=1A<`5QA(JLFE^&TB>fX}9O&f8VXZW>sTO zcs-2vF&okHy$jdH?FVcfI^UJ1I8|O#+Pq|*Z?<==n2V-~#HrXfJH9pTi-*s=!oqWD zzlh_penO~rJp@IZiedSTq12nRLA~rXl(X$Z3}!o;Ped+`6U^@arAb9$ATLkOcMokv zn6Zcv;M+8L0P$99ZoToATQkKnTiM?4TJEz+_KXCN5FU>lnWU`#-e|on>)7Fa^sX)X zb<3LTIzsO1&1v#+jQfGA&FSp|PM}|gQ&+CK`CCVxt6IadVcMhBdeyXB*SE#LH))Rq z9!40*m7qjAb*r?T5HDaj<`}0AUo@9NHa8)U6Z{zOx%AL8j7`hwI}>=X!8EN2Q4a7% zS10@>;_--v&D{Hb^?or!Njk;0JF@{@B}zuI)jm)49Im?UvwyFP$D? zvEv}ek=b}iblY0Budlt|V4GkmI#M!~&-7FKRl@k@xNkd_Z$YBwg__F{f)<=7IK<2` zIuu~viO%RuxgVDaAQH&#Ns|(I6uU+>SZiI}Yl?|RuU2`$wCIb3q4n|O{f$(BNykN} z!%oACg&4FEH91ot-S}A%Rx!{o06DLk((A9)y%Xb9HT>7n#&WR5yRG+6mg1IbKa_qhm)7Ol3>^FPk7;Y2&-F4PqJL#RrMA6sCrMD%eW!1|m_ete zVTfvvuX>(kcXo5#)fmw+i%nA_Hd;}c@;sZ$S2AS0J$T4N7Z5U~;EX$w3wG1RI5o6F zQ)<=k2^Q^kU6?l}?a+UvM1Sh0w7si~sz=iyi>53yJcO6vH)_4z^9<_cdzjEJ2)S|G zALGN8IL$OO>lOL4lDQQq3NoYpODA6o0^ObR`dL^k^xLQBmyVuTlo&0Vc=UaP`wl{K zkf{jdjI9sdA5XP?LddfYoilZ*8!O+d$PT?cB3cQ{zh9f2&9S~J{2_~%&BrCVw-%1U zxLucN$nS9@X}E>!$+x)O-0WefqRo*v!}T+a0n0O5OgDU0j$DF{2Z^90Y(;a@IG?Bm zThVl>cF=_0?xt>Sp`xg$>+OnCI^9~`Cj{qln6W)VilJ`q&-}E)TvQ~U-4%2Al5)qr z;73CDBMPm{CaERuY4k9`&!`Vg7Nklc1!0i7HHdyO3qP>4a2Nl*dYd~w<`yz``B728 zN6W$8+WlVO0=X~S3wl4zy#P%TFP^-f#fHIR9~T#V__6NTsJQ0)=kU+iaO0#FRqorU zQiEj7B!3rys#6-}j9w3${g;cwjQMe~Rx6K%p2h4|6k}6z%zSlmy|xjuRo36GOwl_J zyavybdb!T41}jSoy%G!B3LQp`e9;Dso|$8=DVpyMo+-95culI@LEMRTP1B~m@5Jby z(G;L0$tX2PCnwv25~9#0$U4=6dW5FOvhjw=iayn9aja=?u`D^%35cllxk07izqFYJ z3O0`se3VXet%&~Z*GRR&Mn66o#`c$LbyN4#ghY|}j3GR_-AEc8s<>uQH3_1(Lh2L) zqjobq1qFepkc_$UH_B{*UaK33i|FhyEAf~b?B6W0)M#riC~5yxo~iks`hHyBIRAc~ z7%KF*%c#3%jibTD3_W?T^M&2fGt-yb-ruKnX=2Z7)jXJeX5!`e)>WVv zz(aQkY(9=UlRNQLv~5merxnVfbiQ2Twc4RBeLWE2$)q{9D^qE82ptQhvDBqRh=U{r zP9LJ$l<&{_GrI4diMkuZ$3$d*CI=ZEKhIhV$a4JIJEr{i%;*FYR?o*U*zQB2tMPL! ze@jY^FS>_m?H=E2=49_`>)9>q?Oz{+@Bu$X80UWTVI)Zk|E z{{%C*BaOoUNs8jcOg2|WC#$NzkB)*O4s2a{)N4!#pd(yyji^IbqxlyJP|cOaC4(ow z-Bv0eN{jy{mwKM!NV&@|_}$`~H0+0KJ776?b}-9eyH>qk`kO8%mkm<#(F`g1U|E%r zTrT`~q5Mdh^iVHMjP-{`)FXHs2yUIKbBp<)TQa?n{OwlS5=(GrnBVd#uP}ebd}dj~ zQ~S}9=Y0sy^A>u`CoR)yiM*746_0o0T5C9$|K3|4SLN-=ZDFCw34?ag$?a>Nux>8kTDk3w;iSY9I6~t@PY|E2Rjr`47Ak z0hCnu@~uM^1$4xhCi80>1yS(MJ=_H|(70q;g6Om}iU1>-|K2VcyN0ibSlRnr2)))U zh#2y6BA+x`{!23Zkxux+hqy1rr_@w=jLKTDlsr|Cn5$f8V-SJ3>n$RL$zyX;X5!c2 z)kG=S_j1~%l+?d1dT2Vggq<$mJ9=9l|5Rs7JLWu-P6<+zJe;$}@PbWK^BSolDBot2 zq(W$LTBdAUJ!{1L2@4X;x*e1xtuayfKk4>gEPh5JucZ=}5rZK&jMwo{Mji~^Hl9H;hsk0pIw`|DyZRwmFcQH-S zf+U)Gbk#n-U)WRjnNGL;<68_C>)xnbkw2RxvQJ}6L@wrmE-YKG#QRo79YlZnCtw?) zKyOt!&%JysDlO_PUu~(>-{$wQ8x^vN!s-%?DSy@Ot0|OW*mi%6x4e5ay8F0x;FaFB zn$Vg)_``{>H}s}GN!L~)FJN?Z;i9vHxz)}rFB4%`bTgJ(*R|aF;}>3AboNpDlhkCY zJMvr6sMSQHqjTA{h5Em7u_sM#)+aXVEn4g%UgWHwTzp!-PWD4tAT%hT#qNJN;#a*Put8Dy(%u#wo70+%vWWDov|b?2%YCbJgO8bXhwr*U{^E12e+IMIcLU zhaU-iU^hiOW9QGv#8Mgl&Y?TEdcNzR&yfu{$4&yz=G&fWC(uSX=1(nSeMARi96`Nb z6$UVbRT8oOid@I&s`XYY;8>G1E5m+5f&M`XH=$>)^k3bjBqmf!M&Lfc}Uu0$WY!HWT=jOs8=cp^ndb*fAAj2#(T)aK9Oii^5 z*)(u;gy6ZMk>4=daRu`>i4(;WHJ@}AMm4zPdhH_j;QqejV9v+oj#5&%$>{@o4 zk9%rqr;V%SY!X7Lh442FkoWh*(oOi+tNRb4uu+*x*18s|+K=O=kHyyFiwn9@WInY~ zP{eMxTmGJ7!$w8^5T{<*lv zuy`pP=&0~_PyGF|F%E>t;(BWd_IfJjLX0pidhWtIyahtAs+5wJW$EyH65_JrTV#CM zlP8u3R$hDjz46ir;g1+FxeDAG_KN>p^YaGFB?Bi8S-m{1#AdI ze(m*Ugm2og#+lsQP77%|y_dc?=*0fe&L0hV7n_B;)>1CySb6a;E$6Z5C z9gC7K&*_;|=GS`r%Iu+y_EMx!0c z`|qJX-vJ!jNP3U92EWP%>g>|!T>!6F$cu`jYIs1NG2F2to zP(#DjsFa-KbD+dLj%QLr*5E$=c3rV~Rdf=Qhk@P@vv@SpFPIm?X%NU{K93iyj}qsZ zFc2R%;r6ei2-O3DXrH*!wTl<4=S6Q6qiI@WoSEvpK52<y z7VFUD@uBo900&(sySkI=ctHRSu)Z_!m-P|>S2T;JTI?VlRL--=OVLMA=<2Afa~^%U zuh4Ow#b(N)H|L;FB8jd;TEc`3eovG3yjRz|^go*!LkCQK&@eibA~)zh@fpq(A~O|3 zxl0g6LC6*lx8S;m!)_jQu?$@zTS8+%c&-%LEH?D8YhTsdEsfsuy82cgL8k`J$80_U zjk@`= z1{_XfAp%O`xTpPysrYse%2OXFeKf-X*`GviiWKCs$F^bM~ zMNeliMEOH}DyHv|6|FkVEI|MQi9E6Tj^jId~0YG}cwzHA}Ns38kt;RFs zMfYPd?t@A#kE^*P3;=>73>@z;P5Sita-VZ8sr})l-{XQ#Y`Up{)QsN!Cta`ISKMd) z!JH;>WtS>cPP6OjABMipd=H0&{3Krt^=)=baRr~Aft<^k=2PVP*rC6rVB76Cx$$Av zf7?x1h_cf7+$=Kp)=EUg8$FWK{XX;9_ciRC`6ct`g1+~q!oyL$f9LA?w$ViQDV_ag zx;t!4d4@kOzODzSt|INzF}nNOP?y@ePcCiL^NsMGs1^6G7<7V?Rm#eXe@5VvX9s8T zl(!!3&sO?jKV9^BGe=&V%Q*hfIw!b5`g~IVZ6viWyDp!TaQr0=G=8A#hfj~j#wPyv z!Wx&38Xe-4^P(MF9*6nfa}7+dX1q}%JED68;h+|XQV{%tGD!wES~S1Zm=7+ zEB8gBaMR&N}e&3~Ko^G_~y&gxa ztgi#9^!0UQQSUBcnxEGqO_qG(?aC>csc3&fi6rF;*;+Y2Sq&{Y862|z{csN50~74~ z?Wx8EC95%3`6ytd_=fIg!_a&$Hi^U_%E^rB0t}&`%cHQ z00Bo;gWAlaf&!z3jg_RSDelu{1?{--S);|N&y@51)xyx}!+FJTZ1(+y7EgM=o4`!t z1I2`(-5s;MFmGpBTE36<~YLJTn4@wP%J1`#qg!X4ANEKV1~Gr})(W zSz$sAz)?yBoBvt%?H{tOpjKF9Yb^#`puyWEy*BQRjs}nmc!36o=&Aa~`QX}x?kY#x zBsLb(_QpkuH>s_LF}!TA?o$*{=g`inPoH)xOZAkWQ5V=r3n4e+{}SnJ%tC(60G?_c z+V1h0?CW;#b#$swYU-YwgUuwPiCkp%LmkV}KR10`gd@Y`e*UzuN>tds#UAbM{>KOW zwwvIRN^>YoaNJ~oN=-x5ZPEKUFvR0M-zGwN&u|Z8{i4}f1Gh}l#r?|TT4!lSkPb za!>z_t?f5$qn0szm5e~Yk37HR11PDUx{$d$FA^QXPfg#fJk!`FKG-Hrr3?V*P+4Z$v zxqBL`Yc|iO6ZH)(jQ#JZ>2$m4qFLowJs{*Vi$UUcqkFS6CZ%>qNda8pz1y8>Tegbh zp5b|{`RX{NWY=X`kQwAWDzH>~FR+_y?1)b)mhQi7t}KE*176GSKgWDb6F)8}j`Fn} zeP?^+C9vgLyI}8fQCwKRI%bXi?g19=es8Y zo7A@}avPxe;b@%i>4yGbz81-7-Zr&XR^P7a*6ZOqL7%nzM`2;5!u8Rg1#)0tmH+o_ z6li+`l~Z{MUyQ&VyV(S?3S-UDd^7&iK;N*2^0CM1#c5*ZM+_4Dw99p2?;e zs|9)gCH-;;k$7U}SdW~Xlt#z$xr8P|+3}H%3zjs2D#qMjA@i?ZZ>`?hFGiB^cAa|h z->i`P^u^<9ky;v2#LLSR^B$OybnM@@pwuG8iEC6}W2gWzgZXzi5meb*E-B<*zrBuqTy zi`-2qAUyt&ZIt(oV$3E?8jH30L$s}XW7*}B@R%N@7oNI9ud7f40zkGh_%<$58nwPgiSX^WE;BYup^)Kldx-ENe59`}-f;d>B(wQh~odc^|r;j`E!<7+mJ)BG4?U zAW*?rV65=LFrkhA{VI$UMF!BEXSyAUjGs_ud*EI}M~ z6KNOi(90XQN(jUzkAq)tuXdq-Tun$?>A2m_OwiOE{v|jwoBGqSr`^@ZKn&ezC4Dax$r!S54r{J% z`q74RJh&+LAJFt){msC=N6JSPd!AECN$4dld=pKT(D+Q#-;D<=;nBdeKw8|=f0r_S z;)v^t;UhBQeH+9wHuhp%ez5JK(b*|h$kV9#Xa`w>VhNLg!zt`klLUZ>xsiGE)^&{S z2TAkpZcQ#X`F;alRcQ_PS|bO>cOLplSiFG6<4@#s$G%bH;&s+a=Es?Cubx3NFIb|V zPo|bo`0uzoiz#gcPAX67XYEZzbu=PP4bnstx)fJzakawus_-#-&aZC`{UWRAjBueJ!A?$LoAE#I87qsB7KzUDfM5kQ4vQ`g zCGj04EGm5mG|l^hVG42(IH>7c@ALro%x<9HIUWo6_b>`IzA1q9Z;tX@yF?POpwgzh zFdQ|V3#L8$a1}if1yhxc5yN-Q}UV4b9QaKDLEa{BOk2)OO# zOB;~?V`hIE1t$RX%)taHrzkv!y?}tA&nfJe=N92>R8iZ1@?N7OWe;nRx>T{t?8YheUIq% z1QHyFxkBcTvBdwJ94o?9E}f~en^NpBkEvN&dH9wmP>FAVdp3?HqF`FZJTs%b?3WuI zybL8phE{<*8L49$kh9R)Oi{YnCR-kFKp`I3Gb0~d#(L?y91(n!hYm|VCe0aYsQ;H1 zz6xNU5l0!$feOBPpHeA%rVNA#S$>(DA(!}Gff=UKa#?sc2Z|!|!-NYk4?p_j{hqHN; zW0#3w?z{*f=+QxH1oH`aT_~r(#a^h;^H^^+Y@oP;hb9nY>F?j>VZ{nsRcSyxpB>x( z>vZ`YK!6~rLQI&84URL1RTXmqa5>_#0n@SxDoex|KW(=z9BDK*N(r%>XhHe$4B;2I z4=m=B=VMKOCaP`ci+={gQb(j24=elsC0=lFqZ<=*Kce4^?>IwqX(nRQ;ts`tvz{&s zFboK*D3k>~uUB4G(iELI0y(p_##)%RpOL0)6IcB$z3sj$he%vdl5E7;kAv=D3&1-#Got#dbfQIL5f6w6cmv;4+(hDQg4dm4tr#s9z^+k4Gl(fwUMq8;!eBTCm zG}5?l(9vG$Drvx>xpgg9{JxEdJ$ zZUOd(q6dJApUAFf83K!6AK^3e<^vmU)$+H-S#51ac8T;dYea5pDKS@zYV$YR}q__IdhFyI+8>AweN-CEHeX9i5`+a7nonu|6%NVsfk|9%59CbKi@ z?f4WEKwA29KqXC;eh1-3LVm=97PL~ZJMh6Rd_lm|zwp*d*W$v2=(*=E3Q;UI`+qpp zTlkm6aMb=Uy&q~WVP+dk0<&RAmyGkjlEGW}0idvJd`dM9deYXjROMTQNZ#g4O*HJ3 z`Z}}VZ=ER*D%&m}F?ZfP*G~|O->Ln36xEpDd1Xhm*zWOmERT&n#Fct1Z(%!H#k`(V z6Ai*)kE^B$X|HWKqJwY!0*gd?0qVj3ke2^|LSFw zmJ4vfhf^1G$LC?334O*q#42mw{rwS~fMH?bb#b#^?!NuJ*oszE*<>awFvtGO$1oGQZJhCAa6O*NW2KoZ-k!SaP~~lMRWIO;=Z5D zFzL)d-=JFm=Vu!S(8L~#Jn&j^nSZg!rEbZX9RAsgoy~a>vgi8cI;QO&BC5=m_X73{ zbT3pS{_|0G&!2Iz{zYLG1LuKpDb@VEaxakr5RS=xuhG*CNp=|3v3SO$loy^=EdQ5H zJYycPSHk2}uoh$VpVP&EpW0s|HE;mNc1%>tk>YQ^qmqMA863TACA^T7Wg?m~sV`LLS?ZP|Y=m2NIJc%^Rq;&~@MQ!uqyT%cT0a|~N0{pCTIgGby zFHDk7Opg78xVD1EZTGg?xIc#Pd2;2URvJxg3xB@$#ujCKIIpFcT14&7%)I|eK|<0V zyYMD-=CzbY^jzoq=B!y4-NH`{y`DDDt}gSVz{qAo#M#!=fDv`9YsmZgtZ6A( zq!JK)Koae`p}1E_x9h4$CV4xV3&>@8jy@g^Ftqu<)h7%RejE1t$+hDSKj4!+Ojn5! zp3yZV5{!oxR;ZPCfFc4`@My=SLy`}}^j;p`KMXV3NCT{jaNCQ2FzG7~B+L#^d%kH) z@pySYee3m7f%_KAZvf;O<4;i};@wi45XJgkrPTGpCOZ0l>rsQ(B+al%PBS|F^Vggy zp-hrPH)@z9br=rj3mo}N8X?`?ujQK)UE4)yTqGF7jd}zThOW>3w%z{taa+CnT>K7U z&kCcoV%v8`o-vpFedA&0uYp#Ia4%Ws_x)vQ5EeIOHsmKBXXn*X`p-GJs6W3LHAta` z8utUZL!v&X`e$Vuaev~yq_%;{x{?9EE2+j%et`SmW)Mcl#DH(SRN($7i125Nt1w{I zgm*a9W+2*vikj9GkDeNdSK74RS zk>5Yd2H;e0I_TEtz&=^1aOUn_XGhy|#+{ z^s*wpJ`!;_cDt#w4PNii1NXI_eEdiyy|#m99h?UZ!AWVJpI0j8Y>!EiMPubi3>Xx9 z092F0`H`G%$9{+iaoPb`Wl42BtK8=Fb+K5X*2ecdbTZ%6jGy(tVehe4H7-q_K!Z69 zOD@nn#Xm15FGkUjKvQDB81TCsy@94Q7~6n~!e9O>NEvN1QCe0^;U$pRvaFJ#+EVHc z)DF_CYoI(2;Yc@RiQBjBx8#B;XvQ}^d@$ybp&|8N7Ijm5H3EEjqQsl3&5*)xCCdm; za&I8P1JB2K-qnxD?Pe3~f9-Z7bEXUOVWn~M?timZ@7DCG9aAiPt1&!rVm3@z4M;NO zbvIr1C3UN;JkA({hz;&&Ky5XJ8&}clEooIEYZL@S%o7bPQ`SHO(Sd0r|9=lhxs33v zE0qIM^PH;0W*C4(d&%Er&A%6K;ow2BW`d*~hVjPU45nWS#lgR4^J@`u)nCdu%#*NX z!agq-_zk<5f_oJ!y9*M+VW>un$0LW7x%OX(ClN6Qr?ZeooD6{=WJw9l_uT zzgIl};<%V^T$MS*dZ)K4IwO@!8=CQO#gHef2-O}Bo@kMI$*y);v97)RiykBUYFvtS zH#>}?!WAFW6SZ3eoYR1c#yg69uwS4pl&8U3&yJw0A7*{cW0^?tzNju8w1xsuP+92ID><_$)TjesP8 zLEwGXm*nq5t@mlTrxio*VJKM!M~qo{*NuY6TL&SKr9t)+GV`-Y%#PG^b^^T7{x4;U z=y)OVy;?>OYYFAmBf!oBGa4~vW)53&&dCX8MHClsaX6D2NUilv^+KT?L288lvCGZumxwJigfWEm|Hu4PazTG6_4YubgpNkln#)yV=otq7t1+OW4OizCOA~lD)p> z!T%|+?ZCc#E|nvSXLBHxUyx7(9(Wg|(emXD-XD zc!OYFh~Fs;*#$6XF$Ho4z4TIQXc!V6B&rcvxyX-9%?S@FZqg90$M)ZaTW{pZovrbXSVCm5y*7lH zsA{~CzPwKAtTjMh1WKt;&ns!m)af3n?-xwkSs+S$hd$S8&6TYs{u=rPDLm`$PE@$Y z%B8`{49;RRS~;Ru1uFUnhFg^=(5)Vh2zxHHjjgL_kKACLfVTp zOl~_fQC4;dM|&poU57O{_JWa7%m;({&((;9=ehdtN7$J(+>%-N(74{4sQo)ker43h z1D`RkE0qC(h=3;O2XI8{^M{XkzYtDw_AzMr*9fGIw2tP&$5d!L6p;AQ>@_}&UMwce zW(&06PgL8_7hgP+^u3}&>;9L{i(vq4yRTnR``!mqorj>DUH_@RCNpp%ok`yDw=a+(*hpKa zK!T^}K>fn=Rx6*;(srnB!(2zNjA6n05c0Up%Rje&a7jA{^=rOo(5b>D0YwmkejRYMxo{pFJm_t zwcK&u*|n63HPAtSdIG=@pQE^+8f-lsg1__<14R`~mv|S&*)UTI!vn`kzY6E)5yDz1 zsLt__LA5THh)WFkpODpFBlkMim_q|`-T3pg6B1n9*j^>G6%@whA~&>Lu+mcY<83D! z6=IbXVOsV!L@wV`P-GY#wt1f&?w*WzUE}*I=~xO#z~(DntZ;pAIal8O7yRK6Oxjuc z;|T)Bmk_nuUaYb$Q9JHY4IBgqCTPXh3c1;L&nZg1q@~aNIpRXAmH$O;#&c_fPq640 zvRkju$@J9ukclco);bO=K(G5a|6ck1F8c@(A+Jb=oB&g!`f!=f^66{>9eUtpOWn`2 z7m}oh>27u$1?u1RXp^;k5$??7v`x&6SEY#?ly2eC!Ay=RM2%Nm`jUG+{!$MBF%Qt~ zQ?;JcuEAPqluff8p^eq!LpNLaI4^Hg_=WBtN}`cAn&bitY6w3tdH#ZAUf&CER}Q~% zSkCp14GJ(_4ET|HnNhoQUNcT5@jVlEu$+T_ws!w->mk8ct@KkNJ&qS$jR(BY|6HJZ z@b-Xr+Xk!JJxa@4^4d%|JU3RX_~2l0JZ!iHKWm^Q7Fps^CRhq8YSQbasgB)n#cfb@ zOx^fqgL;2u$ZoC~dHQ^>IYA-eg~&z9H>;y4eY`^2s>ieM43o@b^^N4>B_#r7PzhfYm$i;zoJr2cs~A zDtz5mrg|KzZKU2|CbxZ=|4xgM;fTMK!kK-Ww<38qZLJwS9vKcP9QhA|NCWTZUQ#AXgWjUKK}rigp4;N1aM*i0Sosyhc< z&Fb%rs);QzAH2Qe%H$^HrPak_};{N%_N8b5A?(KHMsi+&T)4d1P4h-hhTw2rtBU&Q}`RD^x$FR zukU((J3|j<>JJWLFkryJJBOG2-v*@&_}tEddSI7lql`HqKZu|k6R986{}75<;*C1K z>kj`zJJ4~++h48#h_q{C!f*6d5Wd;%UFYO9CBH8tmXv<>E>MA@f;8JIoY<~9idJjW zXC!{aBv3py@1+7ruF}awdu!=RMI*%gG({=>=av4$FGZ8VFiy>6Y?%A_=m&Qqt;Y-< zJa0eojMQ$+{RkXn=luTYYDK|yP6`(G%J!xPDQ%`@xfUB*0FBwS$7RcL&HePK>9HhC zei7xO9U<6l(avTE;2auzbgiS#U`d9(R6_cGYJ%&X;0$)-BSo?GUC$`NvaK{4Qid6}?L&lf*}l_)vy1vNRaxy#WGV@-!RzpMjJ zt#}+SN-b)Qk9h4UMJK0$jyF6Y#g=H7b;8gM2UfzPi;?)p#xNY22b?-8uEujt=*vww zg&g|cqBwdsjpSj^S<6+hS6ajBXIGQJH^<1SWmAU93<`G*;tVw zW2?mkh7At98pdwxGM<>Wr$d0QOZ@zuv3kx+4^WEq>w^Ec_uog~fxq6>i(sKRY z@lDuRDb?7==OhVN#P%F}Cw2q1E2T!)*q0J))X;B2v#*cv#{6_pOpuL4dG8hEBN;_lIYEI& z`LJ-SBCCLw$Za4<$ZNC8k31ZC{q!hRx=jYMkve11shvXEzhARMLhFJA9pPkg=^YQ0 z?!&%CRth51a+cR>Rng3moRoLPUFXU$3`?6X_1_kMot%X~Gy91ClWe3KGE!fa;ms=R z$dRQ`7&qKm@8JpQ1MDJ@xY{m%h? zruq$}AQqXs8SEMHhNiI!9-vdnU`hXhe4y#YNUuZr@hS%VLNEf5zWq5RN1m^XFYV8Z z)0aY2bfscFgV3=>W*g2O)=>l5jD?V?!~q&jLYMRZ&+#0d9=!pC!JEhd&;Ya8D`3cW=(hPYZFMON+pIcH40 z${;=6Jl{UH3PrjK8Uz4Tn#i0FD3v{$GcEr=Er7K)DT7mf^CC#HglB>39%V_(!ZUDH z|5I+7?jMkM!3Mv0f_%EGf`V0uhG&|RvH-8mK1X{!P=kwg43+d))a~9nTU@8g@J@5& z;_9mH&jm~CEe774&R`1N@UIoDNL?URD$ zN*UZC8$&|Eduu!?5sAyMOXghkDx@r4`saGUI=))ccaxC}9y1j;AcSx)AfFGv1<-n3c6U~ zsgTcGt4Vw(f6j-|DXj7T3(8#Zqmp&)-oKuF5KPn-h()PfZzqOfMpFednhS&~3OTmz z>0^PojnPk|3sK*KBIewIbvKq7{w?TP^K=J8l4o~xupzC1S7M@M^%Rr3G4kLo?@>bz zdk?cQt^7%!jI06cFZ2CVmpRfIzT|W)*6Gy&W@Gm=oxTTIfnsUZa`pIHKM z%aTqb*3uFn90#8}of-$y>pjWdqQ~0eV-A4nrn(Q3ouLl_>bth1)fI;{g;l7ESH*hbHJ_c79zjfqDugYlDXukvuH zmUs{Q6la9+A4=sXdyPLM65jvdTn9`C&MK6?SW#g;BCgJ@wXN1uK2sk}6e_w%ru3i@ z=a^N?5|zdqy)p{swMbG(aO z;OSUOOA9(?Mrh>pY2@aCx2K*He72lmz*x7bbeeYPRTmS5uN(b9_nU$kjPSyjq33kQ zWTN6#-Uf)PYF6j-D}JQOzT{{9)-9zkYs4te?QBnLytaL%4?WPQJ)I#qnRig%^7`?Mx9sztV(F&(o1v9hk(3aVXgzJkr))$;>rD4ZQ*? z+Sg?%`62$k?N_zT9XYu-MDvvrp#Q?^wNJi&8xP`YF|jlnIT!X6o_y$Y_0sysPLK9n9xQJNIdH;+v4ofFi{y6al!jTsk>eo z5Y(PFz!ywYjt=CvqX{L%Ju@G^8umdw$tO(R~9`56SU_fv8v9 z=p??trr1bN>5ISf;QoOs9X4kkxsAw%)fsqJ=76x;0;7X)_4kqmR2cYug4D*jaD+lbJF|EQfb=q z1)R}Zv7j67h4-Eptur>rtUXRpwq~i;=1-VAH~CBDfSs2A1cpNZ-`=G7SP)?W;-jQx zTcoU{4lvg(CB0&dn`A4Bvc@Bcr4{t|ws^Xg+N}GH?+5BVI8P&TdVcqQvdt&b7XCf?H*BYK9Hkb^wc3IA$0ZEIl z$&syk4nXXIzd9?aB(c}882L;F&QzVKc2R4UGI;=(G8%Kl5O$h+dpNXX306HbHVrK_ z+=R*^-KLSiXz_u+1Ni&VpxCEZy}sA&+t9H%mE?OjVFNQzE=Xf{G|C1xmz_$Nfvw?l2JP zI9T5loBS<7vHchigHBtdQp$TJ$8219-X-yiyx9;7lh-z?`MNuu%75KJYKx>VPRtQo zWKC-zmldwblw7rv5hTKC)s;kH6Xim zvLVJaK$_6z%p)Wzg zYjPS-;sfWc-7n5_M)^gTw4|%=}Ip*>#I<*^2l`09P!(#94+Kh8~8ilKW zW1IU?1>x%Q`>2T0&x(p6u&P{vW!|)O|0G$hCrR<&MQvG#4Pch zAgM%!Mu-Iv$W=~cE`b#d630U9qRsNHk?sV++TJGmhq=Aj;g-tSbEWsZWSBjsy4a$@%>M* zmjt$q7y?6(WwAEPG290R&ooNDBauR{mR&&=f1E=pu1S|miEbrZF?F9_a{ zAdKZTMoJr6cvobPI~dKtF3pU#{AtprLrxr29V%FQthzl)@krTK8J290zHF@D5qm;x z$=gz-*#Z_a+rSX_^moa{jtUv)bYfT!8(jlCh`HeG#oLy#7~k5HzA=QktC2iD>gn*( zMkE;AL+NsW0mf>}9X?NB0WhK;K4K8^&JHL8llcl#L2*(snOt27nQA5+-ZLLqqk47N z?-etd#cXXYe-`tFr6&RAY%jb+xvX2!SP{;A77*tEuH66pd8?%Gm2{Qo%m*3-)Q&vJ zAx0URXDbj)g38tFHbRgRST4b_F3^j||M_HAYtbUaWAqeDX8qn`;hJP#sU_H?>s1c& z*#IzgNKg+fKeQJjO$6oT(JqlMusFiCupkMGrrOy{-r@2+elLJi?gKU}?ACm2wP5H~}NPUoPL-i%j_E^AtJlAjUq7QHm zbguH#!$ESpxqZb%fy#$C)vNf(Soyg?9?#~86zHHzKRdW|fA9Eq$1<7+)WWyn( zX$C|O?k+OA&*pxdQem>DSpFQ*9Pt*Ji{+cz-NdV0x3e_5^xX^Cv?95WPKV6pIoDq$ zUQjeQAtJNzeQLzROFzD#(c-9;mXsDIOd9{jvu!;r2%~}Ln9gVfUHgO~D0ton$_(1m z?F#T=HeTcSZxm4vF#f4q(DJ_(9%GgGUIU2t=SXsEdH0u|^vpsaAOmcy5+;?(dei2 zHWkRpVS`8oCHFSF~s`fGG@zI{b z^T2a7)hxn@ONJ2UTz36u3sA9|1wXq!vaU!)4>q7WbLE#Nr~~4}-B?Xs@2jP$L?DwG zP;@+$!*Ruog@XYSn&wvF@pQ>8?^k;i>9p?H6gK{<~@r~;(?lB()mTTHH~!jeWPMM4^f4h z-E4_$$6wTWCLG6{&FClIY`+c764fTOj$PI>J|_n?rUn;Zwp$np^~S_XlP#F^e?P^e z2PGQsV8+F>M0Aly13m4KCT5~p+dxpKX@TH=nB%AAL61wm2KuJ2;zYL(&X;d1Xx$v- zyrm-a!R%tsw6qaVb0jRQyYiz{T}$BT`W8;p}hPuu2U5v%@ zEop8!WbyPNlbY;faxRlU_mM)9_yj_l67YkVIqj64#(S>_?GA6t2<~6~vbsE?*>{Mo z%}*FbB?WI&=Q9(nVd5dsxnq`T-=O)<;INT}j(sYSH2(tH0{|I26qeE2tXdFNZ)f;N zl5jzFwJGbY?2Xz}W1EJ*g(O|)>}CByG3F&E9`N)cDum5XB>_;;aieds#mVp{A)hjs zP|1wgCPNG;v*@yic1gdTk~GU^jjtorl#{vZ*r{OCZNFi2nKj0bHB>VuY(3WtiQ*Zv zHwQ`(6Sir@bZ7a7v3AQSv6q=Wx*&yWnJjf?qvQVn()lhlI79xk83{0(aKPCF+65@BmsO3p-rL|JBCa%;)lkAmQtXrN@2Nlzy&X0kVVV6T#t z%|PESk2BrChF4vl*%<@JH(RbZmdqPW!r4oPjt}xr1X{mHTP)N~Nx1K*Sg(DOyMs2w z=K0<>oWK4(Afy?u(i(emHslXgNyD@BZyY zcPrU7@?Fg7rV8F5sa|vFk9YdD zS%#(_EH5aDJ=?si?n)*WGt7KSz8;@vmMG5;AEDf&@iL;n;#tB8OZIc zsUMP>RtRRwEN*s|YH4L!8s}k!OI~l3@H&lcuCNUD12IzM>i|e!T%*@30y?zMUYyfL zP4U?N95QZg1-LV3_IBqIJVL&fJn3BQ9t8kO=<(asv zREqCKz#G?_Q#d2>C!;5`bNtZ$S@72k@gAED@6vov167iXG05hsf`z~ZD;WO@?883k zlt^q~k4`V%35*HFkh|v1eup+t&{RT@-!ib z6Vn>1y|glEl855%qp5BnZW+lgMJT@6HayZq43i%0M=as7PEj-!l8Fc2b z5BoZ!C)_zL7gN$ogt@L{gvIeyK)|~H6}eUo$)SBKN=@BWafuNukJHKx$45xtv3{}{@qHf`Z+_84 zR7@DNQ`)TD7@uF_O#WRhZMXAtY@tvH-rjp28Zd=l>n93NnNG*^3D$1JPu6GjmXSt~c zI3HN@Zp2itU#|K`VP1rf$X$~fD^o6qz7~2SrWHmb! zszp4NIRq(s6ZnJ8sk~D})yyY`6N!HI5|fxH>0Fj&e5)@gd=a%+BBuQ#eF+wRPh7DL zHKCw{s3nCu+Fn#KyKjqMo!5P<#%ROrfY+TwtoF+TH_!E1r-Z>S?!0n+k)|iCoX+?a z`jU>fr<8}5Y&(TTUn(X(ac_3k<0GhsP|VAvB5+}6<@-)`EWr9+fC#*^&*;0Y-%+YAwWa-mRkov#q<4{FG^`}o`&0e97AV1{y3i-9-F z$<62fL0)^hmn^|g)Um5<#we*QTV>%PY|;~2N=B3;7D+zw(e8L)<>f#P@WAkHi+L>F3?VUJ?Pwv1qyhGh>VrpMyJpOFaa@GaZwL*F)aZW?ink6$?7)+9; zqu@QvoqO+SQH^&xH%iPn4+;5VyIS#UW}ee;wgsIiMd= zk&`hcj(4l<>*k901}j@Cc-F?~cE0V&nQ_ZSJb6C!3AwxPUbgA;bYrCem)Wp2A{`N^ z%k%okgUeDz(^SmE9V5>CtBj^&#UppMijhnZ_cxP1d?>o$Ab^VJ%jnsxEtAV=BwpYU za>Wf>I`GE*u#%$cBA2^klOY+}n43gPMp$o7q~zJJK>ebgOBEX^{KwDRiFZcl@7m!6 zzz*f9+)BnDGRW+lix7Vc8c{S0FugkSOC+Ra>h3FH0Tf4^5feM_ z_Oj-2x8v5W#{Hq)t}^yj}y z&^1qX+POeMkSe(#Ws*IHzr8&5^!OZOAlm%M<7-3z0a7Xr>*T~2`E$m#!+8{ZmWpLg z7J@O|8k}!eb;lV~^*8Gh{=|>3!-v^9;Ocj>IFk1Um}{e{m@QzDk;g(m3QhhmsMrE*zRFDU*!Xc&yYrZtJ_z(l-|;wbq#C38_=fr!Sgs+i4T=_LsfCodPF4K1cIN| zg@KU6mvI-SX!Y{1!{z8nY4TngBzQ&>@;ZoSm+dEMZ#}&Zhj#D!&fYubDsN&5a1rf! z5F2N6j>$N+h^toja0?lkB<-eCDWg3v|4a3Rzv??3FM!{P!vnnGTDeRa1mfc7Qk_FZ z2%0w0by-BtdYZI;Ev24e4%qCa#_XG54wU{JFj*2h#!CBY(6Q}@&9%OQ!~s^VN1`KT zLWkQCnUPS(R4@tKf{;4Dmz9qpmJ!lO$*<0KTz6&8mv=U9k5O0)VF}!SPFNttn|d(ag&Y@SlLHwFO2qB8 zh$qp-_K1W+kwyF3c=P#6W%r|(`~y*!Tb}R7|kwnCQAHHxaiu1ubc^ z%sTV?b1Bj{#3=xFHJ`7o-EkIwBjxqIgQHJ$R~t0q@cxM7_`ZSVf5unQ!Z4mWZ224= zrNK3ReIMOQAyx%A2*&%f7Ud*tJ2UPfupH~oG^QecErzwXDU*1ViCwrtzKx~>u@6u}Pz%VQ7&wgxVZk*4^Qnr( zX{>NTyq~=TCAIl4RBTrC+=kTx0e!Z6QEX<+D)e+5no4PGApG#c6Q3U!BA#h8M}SC- z9CK7lm8|!f1c(^&GAb?JxnI8Qp;VCxRoXj`f7u@VAh|dCp33r$5?VV^>M$~+b-%3u z>2&~(=Tx=aH8a+Q^QF&o<@3;-sgwr;=+G$tgeCZL6MTHRp+DNn_Wb8mh_ayfo+{4; z3|zTBrha>hY+qQYUGbd-Y&Ekw~k3MMle! zHZ1z=w1$hJxE~-r?zqKs37=4S6WY|SC^_yCy<-_Tg(k_aG@}R(3#&5}4(oKD3%@2I z==FZgbu&Sg8z@Xd%gny_M5G+*6=2Su#IH~cojohdDt|g?6jjQPkpUb2LAi6WCs)aB zO7)8G8PqV{Wa{%xNWOM^fZ;Xg*KRZXs<6}gHv&CD(2kf?vnA<4drXvX!P2$?Ksp7m z?F9#gOgda>ZPi`bpTHdneyT{kHUVi-xOq1i(8x%ig40LxRm;-#CPyGR<~zRzpo7GB z@(`Wy34)#J*sbU9%Rg_Je>zow^wC00ltt4#Yvkv2Ok0u-VicY3SgrVp9dQ#m!g>>H z!>6@AlVD!-J1it<+hEb}r)e-1A9Rz#_5a^^+ zCZ7`&c(6{y+@fePcGgd;HRe8djoC=Z!%8&%m6lY)&&kT#E6Qy~(}+U}>RWczSJ~*T{RgD|$Q{As2FhE3sKxOQ>wFMR5j*7w1?Fe`HT=rz&8(!4p1M zMD|rm^m}itAC$a?RDP@1er|LtLJ^iV8sij~EU9FBv=Fgb7lWX|!eJ)saBz9!b$$pk zK_wFpHN(7!m|N{cyNkm=AMy;v86xDFX^zm`47wHO$92XymkfqlsKCszV3j`{LbLOK zmg&OGp(HV)Q5@0~DhIo*dFtA5d-%tI2x0Z#i;OwrmoKH_8t7vqij`6{%{SdfnhIwW zOH{UL5&Ne8o@vF&tBRPt-|uH#9}1!xtutG~#OP~0hn5eB`td+UBmfSDw>RuA6P>ZQ zS|S_5!(Blmep2g#W>BGn!F0Q#i)#;Fr5=8so5O?eMH@GKoa~93Z`qC98A^3e>DcGq zoCSj?8JT7NG`-zRo&j50|5%y~=H&7;bdKKE24B(mh&Q)iN+!APpvYV`>mc6cz>>wo)$01ty!2wq84{wHu=1X%j$e@M76?b0%nN6^Wpa44+*`dHMi zhdXyHp!DY|bKl8piFXCvl5P)MYF+~6XL`RX!qhbQm1RF63WGmZXn z#QLkpJNWsqSc4VV;^mIP6XhHZ@FlrJa$<;pu6;@_$4-a{vdD%(>=rMu;Jj{-mM7rj zN7g&=`=Rs?XJ_|c6oaGaV;l-m_dOci;e93%61S+8v6GQ)GFh{3zWJ-Eh9NhF&%+UP%)UntC<>Gg z&*D#>?=688bqOAn7w)&&v(>RwSSW{Yi?0ey_gZX2e$Ttt8d%!d!lAt2EeT*q{^3QhJ@BU)18wBDf+X$8n1OZo{yFGQ@;75%zz%R40U=V(*Z!(L##U zvYakxJ}V|5T1^vM-ru`C(2FRV?6XjuZPUzNHWMXr!{G~|;uv?g5^}^z+6g`b z@ns^j^4UW+g9%Ms11Bg=A(#&?9l6q6eRbDdi6?9!`BFOyx-?p=Zg_6-OwjkHB~PiQ zuy%!Fv}I-ed`N=&pWhDMo5!FZr^)0!dvYUzP;3yufhXyBdt%Ll*g)B1H-fDeW#Eyr z@9zcsoZ<~1`&}c8##YRAD-|IkuSX4&sjxoKjMVA}{Y1Dq8_^Ia&luc3 zR}Q`+93Y;&PO|Y=f&G3ziOqDL;bm_5pnyW<7x~oJ9&0L^*?%lJ=ezA*^?cJ{js6;h zQipNGByeU;v~rCqdSt2pI+hutb24TbD7dGHrDbl<&TIPv=EdnCl_CEUA6R7{U%d2R z>MndLa)C49<8BmK568Zlhd{Yk?NZ7PnEMiXSQ4Bw2^L{Vj4|A6jhw`4N2FQUOLOwu zj2#K1hJ22qm=H%%=eOwAt-G~I!d4V}$c)DjIY)$C$>6UBY1*kZO7ijYRC zhUECkQ;)2Ug@5J@@#1oh9VM9#F&3n9ZB20BMp~lyn(KL~*?~u$B9#--30c;D_<}_L zDuG(i5VL^v8K0f=Q;mn%s>;p?rPp`;_(<2Ea;3`4o&%lvs0yYSd(v21z-W2k6U^@z z?nT1-8eYHQKSd?%E^fkLCGOdEwIaeJq0zI5f)xlbzQI%wUwE%>ANRw{U;5$gy>Rd_h# z0o(8%go9E#SjSeUbcTXN)*>khS|qHsltKW?YABaDUeM)h7?baPTR9K3>)c>$ZAR&Z z%1aLAr8HDgZO#20fFd?VHY?eze}_;62MT)l zhqIwyj9L=GGJEZR>VaT-IT&9%beS?6fIq3`7SUA58DEon>|k>4mJ#Z+G1B8f2MA1( z8HJ;nH9McTTXf%G8NHk*%XV5pi>`Mfa7Gy^WV+)m;DORua(f5BU)Z_#=a?yd7`1sv z*Z$`5q6Ul0C~<=NfR7+iN`||3&;UEy!V)bCje(F&Pg=q-DJ{+*6x4Rz>kZh;k(Sp8 zvI-^pEi=8e0LEsrG-$#W&_A;w$|5L6w`7B3mVp??85M2eC-)QUA;j*OMXv>bhyTe+ zV4`7ZQSNo>*>Df>uM<1A$6x)1iK1u-r#G&DsVP}*+F1WCX82r^n;6TsVFhrbVOW~~ zu{k7%FcmJfwb)=Na)!fs;sKk(@=!TF0=7a+Mjlh=4!&&OiKlvdCO%0nHov)HN1%Xo zYbl0qhnHLW=aqBdKUaW!-i7h(i}qKcDKDSdV1~D}D(({ac3+l@{5% z`O9479&tTLUwVB}kzHD)d$G^s;_^POP@l$cRpC4H@r6Mmnx1kuYi}6MXc}*TX^LSE zerR?nh;z-{N&*_8fH0EpC-iFA{+>Tb{Ai-~mL!vkRHtdMAjS3rf)u`)uGqxBid!DBtkKk zP4_rK{XcNNVET^JL#w9d9C^rM*gJ4i{As7upCS(goG>yopMm@?OR>XA4|4%JujYu( zw`oER-k~P;0v};b&TM0lrtJsH33UoVZ)UFC1M~HJDgX<~U}<09(ZWIc1h?61By>=| zuuhCZ9(xF;yOaW^+{569DqHUlztW*-uTrNRp_uGdp9V+WlsyGn;2xaG=Me{tM%$B7V?0iKOqH zeRS(LU)qc>fBGg1keD!~)cX`5kJS_&N8X1S{T*`;ZCToopVK)xWq4@rxD)s)=+5HA5{Ze4TmXfNRt4LPNJ~{yp(HMbC z#?>l=xzH&hW<09jF?|HC>L#IEv$7esA^{nqM;vIhut1j!aV*g)T)o_WP1?U_*ukU> zbUqL2RBDunp!Ay=X(Uo}c|vZV(0NHzJ`zGm;x+^)pxRpMYSJe{C7y-+?7Xr!MJOWHd{i!W6W%1rj_#;Wbts7iJgaDA zqGeY6pvYAvib40{eJ1CZE&D(BHunfoTtnol;g39fj_seDL3fMObtxpCxaM{+=H zg`XMV>+N)x@lyb{7fy0^c2ie%~(2uehy)P>PnJHn!tp6x1 zGZ3(0SgD2A(w`57#{HDxil27uC7}FRAdIz8yLkk^SYLw79_ zkWRN77^#$vE0)uadQLuN{%7Z1DsU{u>gRTey&gOJju`(tLWRniM?g(lH!v8mbnEJ{ z?e9?x-V6@>N@@3DhDpr+U_sQ%3Y14j*f-g%Yfi@Z4(!1Lp#!hJ$1??aFvOIZAcmwa zM9-h|&+vepKQw^1=*}rG;$K01e~*CR-K_*=5-zFqePCu7buh$8%f?^rzq3G?@Jgcf za8j0)Nh8&aS3ga`P@V7LaMPNW7oI(DG}sOh0I&{kGl(T=&owD}J@-@$?vXjh2bgA0 zM(7IyRVO%LieC1?cO!Dl>uwPvb{cDG|Yz|eL093#(8JQ`84(Sk1?GJ*UAL*WNIgP^&jR0w=G%W+mmI@V!4sdj!F zb{@YPgEujlo&jCtny_y(43H_{s&|fpIqDY-*3?!rj!?$}Sw?tnYYKvq+xdtuu2bFu zBMcflzwm^(?U~Y9eN-^x-1~O&YNnJNt2l#u(GBhQ!EaB936#6VI%FegPr1OCK}A+J z-ozsJW8vLK?;FcKg8AH1P~c1#`c~nw56(R-IcUJwi@^epXLXnAf9YHY;nt(I86AW= zO!+CsWXwY5NcY)y4Ub{e-UJC!%WP*n$n?7mv?uQzZ*y*&Xji`@@rk}afTo1N65&f! zOBiqJLZ{MMBcK|LgG4H7y{{tKGm^=-2lF;`OGI_m6Dv4l&r*#e7&6`xcUMi->=8~q z3UKv}m^iQ;c!Dt;hLuSbG*Zs`9bC|9pznLW&K>eBhjT+ZH@D!-MVfGah3$SeJN6P} zx#LTV*NM26U;%eF{{(U8Q+SbRs3BsUFvI>s-r0-oj*=FC$;RRwLWVJE z?aA*nH%Ht{ZuN$xCvD!p&O#|$CgD}KN#e*zSjlXxC1zt~pPo+vj~7v^YJYh~inq%CS!KMtMf?y;{dpgt&sRz~JVP7m;ms7j%NAVY#m5Q-nY{_Uoy-#j^ z2WF#HM*@N@brZb(`I~cHFd~+@&AlDfOlU733#3L;peg@2H|~4P*&$(GkQ!hfh+MaH zdjB;HIat4hp1YG%5n7)#{vosv^qg8Q%f zkod>7zY_iwU6ona?OSEWLY!ZJIWhXkGYv8QDRA~qv6H=}A4Mf`eKfQ(b$uZvyEZAM z{&)3tsHhJ)`t0VfECCF&Yk%gDfpNii{JkIJr2%GVg?V-tQ!Ua9`DkO!>vo@6Oc=Y$ zIh5IMn2oiy*{qn7Zki=kY6(CPu`vYx<1eYY<}xduomo1R7WHN#SyN%@3j&tz<57;L(nsEx(o_W2Jc1Xv9rFH?49>^M zMK!n=*;4eTmcjT6`BXQ8uNs^=S8S){=%nzz{sNmGPHx5x0eONa{)|T~t&2x8>VNQn zN|x;DR31Q8>)k3p&?=>OOrzbX7%m2~c%H>qGV~M1izvX{4`8l9_OIGzO8$kGjWN7E zx3BQc9uqhx#Jr*yyj{3{7+8*@WGyws9=Mm_g2xrR@u}(1E=@~EenOS!b5Hq=d;*GH z>qZK_<8`*_!l0NV2yj=xE?8?mmZ-Q;UOQ$pEH|!dx#Y*`g_3#HyC67n%dJw&49T-U zU?kdZ)mt1KNlkV;(9>VWj7D4}$lEia{VbGZC_JswaF0!L2qWw6&T%dXMc$_QND)c+ zbi(2cnHFyS5ybnb{CT<~4Wn$KnsIQAjZ>B(^q2zWhms$+B6EQ66G>~|2{ z@&@_$eD?Y1!6M^D%0`{;HY2r3p4>N(%*vu)1)ZG3ESuzX zOd0tk^KyOY_L7J=Q8lC;PbC5nh1r?LV{Z%V=SW^FCSn}pB{aLzQivY{-=kzNJiUm!rIn1%ESw1LKt+jcN?oYpKszhfeo zsxF~i;DCjyqY|98#tfqL?He_j2vxI3L1w~Clm!gVGkriUK~G*`uo_eG-x=hJEVchy zTT`>KTkbF`x9+;J%~V+ugUmG^55R>38D_v_HS904n!#6vuK&&5zH320s9UbhFk*!V z$EbzV;Gb*aCCB}rS+&EE=ZBB-=Jr6CjU<2c&geR=EW0M9g3ks`9HG{dW=k-0Sq<~` z`VcduC~zyAgez};fX7n7;UAqQ04$>96Wwp9PRzjsA2#5`CIF@lgL0!dM(SIcjr%EPVv3l&6@?@jEZx@zDHYqH9?ES-z!%9G5r{Vej z9kX72AQ0d$nPoLjJKw9o@{PT;*ADwD1*m;t(Glrtri7qwdxfetXkv#s>r7oW@9Cu) z=X$BeBmVUN-#+PUgkIBDETu{e>ogWUZmlTx^F6^#S7Z@CSZj@jAQ7}$A3#hMuy6HEU5(` z;fo5#0GN=_Oh`72Yy?@nI%fCmN-q$>?PqS`O-Bjw&?x15g5eD{cW19YS91m0q@k2X zj<0W8_7;G>9Njkerr(T9cB^l8_E3(w>jF(x1Zu2N+Gk3~iIe7g7fhBPxrWfIqp!1Y z5JtX8mUg9*>@#X{hKVfafZ&PHQG>wplp{axME%sM% zr2qk0<0;Y3zx%ci%;&F&=l8Jl9y^`WU`gs=@d_aVUxsOG;@GXv>2m#^Qd_Ax%JBll z@*N+u#faEtFtFZlI4LT&E`}A)R@~%ABC>)8gER$yOm3kZzMuV*U$A^ak3&>mzFQ6! zc?g4>JyA!D4%aX++(o0bX+>i%#6%I#Mycb%h;7&Fa``=I`lglN1L7}jTAGiI5FGHA zmo;?p2EAw=42^Vo>M__`*NSezO{yZrjhXhM9UUbnlnmRU5a5hCS4iP-QJgMI%D1T6 z``||ZAsaS$&45h__>_CCTK=IO9eA&gdxUH>%^_Ny3_)GDwNjX%y@hD8Md|Dct~4{W1P=Xha=()FP_Tz)QMA0r?>I}|2U(IP3h~(Zwg3?!pFW! zLmXs@_GVm>z=8ncjw&2rH5bA9Y<+r~Zd6m`B+6K5|7z;DP(L^kFHz#pa>ZcBoMqwk zOoB?o(!A@Nc^s2nP3hICNgnvYieCJX|g$RC4sg9PbTO4A2v>mDD=DJeL6mB!=v}JvaIKPIvnp+dFt;Vh(nv)Wm;| zc3$l+0J(LtOn;gFG1{JIpah-wI_NtOxh9P+E7+DJ&$V4d*`ulqTh@?yk-#kI1Z!jT z#FJf*!Gy#%DQ~|_M2N7N@;XvONXdUU%x}<;pRZyC>o@*Tetes=xHW!2x|w>`^Ru&W zqs*2sP1=LW_!W`K{KD&`;Oi}qZ{qHs)v2ymH(;%_{qPwsU*7({ETe7{jgOU^OjmOr z6tns>#_mf-^FT@D{@+|i)=w07FT3}N0&*CG-|Sx#BM@!bWZ3wZ5Nl5Gy8g)%In$umKa}wE;9od3IZ_T% zBdQo&N-@=`?bH>SgXJAJ=@>KCFMllhPNBbfcfn$A_EPUcvgvf?*++6hQ!rzK7_Z3A z<6z72I42UKsLTeF^EU)XuYhuwAd_$@lAN&ih* zqKW9yx~6ObLxLS2AY^WfwvsCMkTT*$C~XO`)W%h%xj;26rgy001^xT?7|>IB)0cJ3 z@KtBF;Y!){HW()Lj`MbAocU#OdW2GGV>4CJ*89cKbWt)u}!AUY2krJn_9HNpH7uGgWm;&m)y^m4kUdNp64I-kHePpjf$st)G z@+2ahCSnY6qW%6II-S!gZo$?tapWX^$(o>kqzVO9)&O1e=Z?>O9WdKZaL2>r{^37w z$bR1+)@2O~CJuhIp=D{guVMPJyWhC1F`?P1iY}NMkzjcnnUvf-HKY@s9eiW9`GT_l z^8%=xK5qnU@DA%p^a!x9Uv?7#b%eeS^J^P*&qQ5W#C@ekZX7S z{nfDN(J%8z_^r)(8suhY_3 zfT5q+QJ&bDS`I^6E5c4&-oNW(KkcrhGZXE@No6>`43bFVK7#(+eTrgyM_;8GQO$Mw z02+Sh1@p%VkEbay+D@`*`kJ!e$wIv9)>nMFd5`}Q7lu{^pK;20`BRADW;zYKSIK(z zZJba}xh9%WbvZ;C0|`&o?_@vB*^#w}%Mi49Vt)%-$=OlERKomR#Zy18H1^|OnNQR0 zEhDaZ#jsvQ#ELG1u>|Kh_t^8KqrJ*I;|@(N$KSXsTBHv^E-vz+%A~{+BQ|H7sSODF z)&dt5`ur(=JHvEqmU`_7sQJ~4EgF933p=KhMJDJ!`wd~^{6P#>>wM!#I3)ldZn6m^ z?Q;wdbJm^T36-5Q-bW>G(LCO$@ws73EL4-ueI-h6CwilxWl5wV)voYQ@*0J>um-LU z9)vlNi{=v?C&Z~Mbcf205+9*TT5#M;iJ#`pH8mt5t0>EmDuAr+SRygUki}}Tj)R| zIyTd19lbh&BMJH89h&WT!O~Na=Z72omWL-x2!-yhkAIXgp=!NlFsyI0%&VH8?O&l< zK|wAEe7cW@Hd!;ftv9V{l^l8tQ4t(|k=N<7Two!UUZ1z9N}m%`05tt&_D081%`Z=? zzz5q^VkFl=sD{Y-of0Wxm?i~lh%>gqY_wP!N*5T$5`;$kuj1rlhjP=Rkdf;&mF;~n z`;vo3)(=HIU-(-yDR=VRwY;_z!yG@`IzfwzO=y_~{RZ^37_UYL2Bs7g6JjGhF0wq% z1Z$gHl<7LoItL;fy_pKQ>HcxOrJpsv2UUIq_G$Fp@%N>|l9}jB@j+f@ zmG`gskRW`$_WCum@}Z8T{~Xdifs6_&8ac~qoz#dhcWnuagmX0j%aat4xjb9Zua)O; z8ztx!MsA5V5yGn-^-XI19HWX20GtY?bv-_N&A*g5JWAq1At57hv~!bn)oKNZW}&cq zdbLnhk)O~T$R9y(B|Kg%Kibn*i6I<{yubx7Lv2^XM*+zZ-+}P-3Q+)2@HSr<&aq{vLKmAcnVkZQC) zIIpv?^#7Fr3^lnU>ocg>qk#yn;J5rmvxD^YQ=?IR=7_rqa*aIynpEQb1G(b|LLD1C zJ8P!R4pofvjtTSK_Rg?Ef$7@zvYdt&%5(YtOuCroroE2q9amC?aFpvKmqdSOBUgfn zw+nP`#=U3>spjf@6swl`JSJ2@Gb>iOGtS#mo8`Ui}Be$yK49?zxd+y2QILgcj{;}!XSu3@>lhLY9w zB`{o<10p5=&DH;qlZPuj)dQueCWkH}P1`*?vB#)9>TXEEul0QQ8FhRtyh z!kDqu=2_ImdtU_1lP1&#Fsh|wV`DO4k(Lpj&+K1& zu+HC;lOc2<%=fbRFBX_q#73}OmN!|2*1?ANRA>*NpXPMas0zoV3@;lcx~Jj2*YgMS zA20%Q4-WWYoz*Z04C_lX^O~P(6-Yv|A{3W|!13gIIOa|;ukrhF;g-SUTYSXhVd;XrSi7`-^;K$pL{w4grbN@~-Pc3BUIN8w(0?yZ%@p;10@!V6hG)Ydqjq|PV;3C4!>KP^b6Hak8Y?@P|yEZ3|w_rr8ARg~( z%W)VGhN1g6Tnu-hl0+d*K*3>A18k8ckt$5{VZ(50lDul$Mv}}siLf_O=X#5v7W!Z~ zZKGiv*Tvui>)u~WW(XGgyrRv~{a=v7MgEA+c;(i|L&~Qym8lt%oGAquA`s+zFa2hZ zdTu7kVt_P(Ak)4(a1`6UdNE6M&R`TcF0Ph4`L#f|5&gV&m!~;6&H)cSS2cCXvE-uI z2Pz!Lq8}cw@0~hd!YO=TPJ6ni^qc^`*wTMw61*7f`FvkD^a-I=8F%_iX&WV<+?fpg8h;mHOgfNRUvz!TjDXY_AUkK5UZkgdtv+2#H9by)!BJJ5Q6nRmC7O4rL!!N*OJa7!7yD z>2j)krRDwS3vD7BZlj(^-Qb>$+w)Sd*D|PN9nUu|E1mu!8>ge)4|dQ_`bBH=)A-h3 z3|D`>9|L_vV%al4WgD(M<6~y`jKMrhVGd`~bcuBLDJI&uJBQ}&wKj+w{vsO54v)H*(-?8(|fesVoE5_Z#OyeDwm?;X7 zu%C7qQ*G^~muebaxsA|oyCj$>bH74_ZQ8-JwO%#?ntW=1XGaybCX&UuBOgv2u{+BK zJXw5Qc*Y+BsNQV?2-$b53-;vJz?_M$x&2SP5WoR)uhYPeMj^Pb;X&WlJJ|rWje$An zz(87hnm%^iiz#_0uAVCROb=3NlR1)0nq;i;-}r04&8grVTdaPg=dok^8o|<$7P961 zKi0(RHHTzdhXxvGofpBI7s9zM#Imh-Z%2x6SD}TLq-&b^ zb9?$KiO?`MablWCU!CvZk`DU*J$3dle=Yv*$_Sww`&%=;wmRUmmRGXJG;)ERuGscE zl9Tjt><49t@p@O!P!rEm(()Dsl0zBiJPrT*irnQk2cK-eC@JwaY}5eOp(%OUt$bD5 zjn+0Qw*_j4#>VYp&RHZreF~53KWsqxw7|j0;@%WNL{?<^elHZERB>%R;p)G8Bqwk$ zEW2$$dssYCR9;PIG&1w0jejmdGnK@V@%gB5j`Oz-Cl>Ze(QA9&-1kZk=1QrrA0n%R zi<;12lP~HCh%-k-q)df0+(FfbZ*ois4o98h&lkjr6n1ZQ8Rs$mFL^;{%elK^IUQQ#G)BJ44<0dx}(_|Bk}~{_8o_ zYbSkB9%uPi7${KnR{eoG8;q4$;o>Mc5P=Eu`Bm4NAom`)U9KwKD7ZcRCjEyTO09Rv zj5-CXMK^R{&;voe3!w%NGX8M+jeqcNF8zVC#(FNWLlE!oH_Kxd2D{t2WaC*k%$&`J z3zdvNP{`x@LDAWLWnk5cVmlR#Q|OlF_)**em$G^XE(eV)haf*&mv-jh6J*9%-iRQK zy~&04d#u0xqN_iRqPX_3!Sr-{3HcrB*<+b~eZ;a|*G7Rk3y5;!Dn8ou%Z0qR;hvOz zFBRUKA@id|2j2ARGFYqYI*)wK1FY>Mwn=|}+t(#G9CDG#T`8zHG0t4;lT1s)6e7JoKuBQ ztiR2ckvxtc0mwMsJWWHv4kRI0_#u*~vl~Qb;3#1mNhn}L^l5G8i8%efZ{%Wd^K+4A zxqqn!{*TKe9fynUHS`Dc3bQB@B#&zy0P3;S?kcGzZd7Z%Q%u+#Y`xC|eQdZJ1A|sE zQ#YLTPd$T)&c0AdUm!j=NHOIjjuutqV5lQ(N>pK@T=35${k2r9SO%>fgd%M8N;N1MEh5#Px~SDm~exn0;kK-5Wa{+BaI7RJ1W_ z*m(ir(%H8QEe}X3#|-MXI$eI}uULJ~(gjWx#*^!A)DeMSxP0w1WJ z$Hj{@j|D0Dwu+%w0Fdh1(RxTcHg@JGK+}X-TT%-;m>=Td9#p+YU$X);^h0hoNa+>) zRt3b^wS_@d*F5X<>Hmc+TBBt$GIB+M8Hd^)(Uhv&8TK1WRB4K@dR#cB$w?x5hc!)j z@ouC;a?tXS!s{G=n2-v5g)c>#Pu2+=hRK0;C_avNgL&$OD4Vxr8gO#xKp@5@xR;ZJ$>w*17&-im>!=C zZzUU)3@h+dSCaANd}@{zOzwX=)I@2Ip&5rd^S2}6LN14C!6_hBQ%h2~q%~`LxbL)K zpJ8?ATUbPArQ$NY`TcUT>Bl~6{cB-r-@bXv^>*>loj8~FN9X>ufHow_N8-S@xa^B9 zpEglH*sHQKeKXJet1H_L37R}!1p(SIY#VFgD{6AKI?aHtD;ml&(_%@}uBZ;}Q&t7) zFdkjv0aiS#lN=2Vg;aEOtjW>vIRtQy)NTfi(;9M7WgdpG2O_#s!BzYo{tk_`dl8DA z)I*L6;LNMe7Uss_`F8t(yfhhYOQ|YCoR9-I_3U#L%(n>MzefT7k6V@7G#h`!%-Lo5 z;6<4qd*5cm>x|VF5kGqs{y%FkYv|UlrJaQTJsMopE0+qPDan2VrX&?NVQdKdpjhNq-kHwHL1qF4kXQ9N>hmW`V?J;_pNjqVAvxV5S>)D>`q3L>S=FU@mg zA|w(Ff!2JLd}%(8(|($7XC%v!lA>#3sbe)6zk71cry6Wf&lWc#fhU+>Wao zz$CVSKN!glw4hGGoV?P^JIX%eE6vE-zZ}s*Ug_E_Xm7GoQ$!=kpV`Ay5abdfi8Kh} z{5mVvXvQOWz!uiznbwkjntti&B}eC~lYR?_0~saerq(jSNAIv4g(A-Wx}4RPz?#ye zW}oEMzFa3HF#{^7zZdxYBC7hlk`npl zUl+BCPFK};(9v7euPu2nO)1!fx);cB=~@>`WD&?>0BJH_j=dn?i9=~v2H!h9$}f|? z*&Ovqqnh}Zt|7nN-s%b6;bUJaLHrn5zx!qW>t^Fdk$_=@;puI`*x~2C?3;J*&n?+H zBd8;-Z_OqeKdaFEazrrpKpLHY*HHH%5jXJM+=@D6Gttnva!3QHVh-k&4aRu43`jId zyCE-+HFLu)1dCV;_urn3l(hkARh(Z$gd|2s{|FhYH4>t|VM^hl$xXUlv#wAir8JF{ zSKodkAhW?Uh74$u(A4Dwg7<2EKb+gjkUc-LzS<9>RF;OfSvWBxU{f3W_klY|UOuoT zV*RHl6cUGYC8Dg)sb;nE;xMnfTICEgTP zv9Df>XP|=^FHc5}0^)|9f4nrSqODf7{})2|zNFUYpRxG-S4vTJG4O%#h~Q4~=O^UN z+3J&pcd*K+cBpVVGkyHN0vV=?kM{A<19&QWWtWvK4&{Vezwq|^wsHN8tCK7Gsp5$MTFff zllAO(H19P$k+AP{Ci|rPuKwC7Jl~X<@AV&xS&R>7*}{*~+G?N9JY27)cvy`( z5f*)(bzPqyNp2sXcMAWMl(4hcHdf;B*etfLQzM;Kirf$kCJJG-TyL##+qXPjwMfvU zb}!v5hG^)ykvyM2n%O`6b@r*5U;=9TwBtq;kSM#;Jlbi~$hC&)v&t68H&CzQqe4DWOuDVgp81=^+WjY8of ztp6~dZoJ-kb_?C{sb4LeL==+9XsEuieZEf7iaM{JZM(S`vh{`&a5-*!e&Bf)QA`)^ zabZJEe;VX)g`P$5Iv)a_Hlv;qqXh5CSFUJgtuOPH9`Pg7c_W5OTO#@kWT9j&ryQn3 zy}gPsu*24K!)NWb94kTaD`whVNYt9|`{TW;?i?FAE2O7Wv}a5*>y;2~Z(8B!yYzOU zo1z#Q-F~o{{?pV-JI9FU;K{|8m3v`ABElg;oNxCx&s#yWT?hVW#%C8I&#HfKnyP@kR(nk&(cvvt1E`c8GZ5rQdc=+>Sioh0QkX zym~quX*PW4wP!ChoZhgjl#yTeR>nN{qvUDw3KSKUg!kvlU25rSrN{%lpwjx)@WRQ1 zlfJhb$8_lzKNin52VRGJ#wT#+r}3NS2RP5<&C8f{C>^Qy=4;Ozf#>0&OTEqwI|;-V zCDqv|pLKfZ@`)D?)8Pqh8?%UfL;AzrNWwvklHkvPFx=H*o|P`L$J&;5eoO-j|2`AM z=RFbcw^+0atzBX9C}+{{Y%9`IMi#3bN-bLMB3xLVVTMu911(UZ6g~&kmb+gp>+#-u zW+3YoPI&vVb$$e9aczJuHP}011a~mq>i8;~6Tz|edjFtwJxIj$^}`KWJFU;5h0fpa zAN22rR=7mqp|v9SEg({|ZnEbwpPuPrvW)8Lsm2YwTjMsR$4QO^R>MXLZ;zY99+v0+ z5o650XP@W77B0UyGLh!XLj3@R+`HuGEjdk}8Ex2OK7DXLoQ+uIqCr7D6hRJq_PQHr z31`ceSyOu6Jb1eW4A`JmTr-vM%V!|dD4E=7?~(%oFt=qQ`(kM9p)G!D(6Mc_TR17J zFAe&&jEUla^3fKNuLQA(YVZ{p$_ggjr0#kDux2}lTqQP`I*1Kb98M+*5E*xe zx3@qCDm5FNal9jwWI+?T3T;YHojYY7H{PnuotIQ(ZiCV26h34S^kuIT_rnzz1d)e1 zrDSd;;X4G=!4$D^wm85RdpB5zl+T`6$!F7UFp&c(nWx2%>$#!n;Z;=m`a{g#VYgg{jK;p0X6>vm8e z)5Xbh_C^pLkE3tg$`8Gav6W5(+;ygdI4U*r79OR$i#_zJ!nOKY=0m6}9#MM_1>15V zW5$68U+90Ss7OctUA~0aMk^_xnW^9Ha#hM&G>n@x>@n$AI;X~R&&(`e7)Kr@Os&1Q z@eqD`;`{zy}8iIQIg*Y2OpeTE3tBu-QZmB&Z~oaaXh^{D;iIs2kg$5#gK$px~=|SD5wiNPJ8296^0$sd(O}_Q7&GC$NLCp*JBAZC2SNu zr{Kf`(xQ*f>!SGrNnk2 z@?32>?`T6pLfUNfNIrDd-|X}JF@pm(#a>I2TDS*0?K(zVelBI6HzvrzWlEl}o$pS% z3`0=}0eL)e4gr<$nrz3%$2TXv{f?SfeSXXSLR>a=FSZG6c$Yu9%mS*K5zM>GNhAd- z@K-r^28V5}1=04+`LWbA2MM?$n@YTH0(`+8?iqe&EKQta%-CF0$fe%vAv;H2b2)u!EIdCQPJww#|t>S8eZA4@bu^sYB(i z_JewLE`l0RF{aWoW(Lv6$rX}rQv}a@0Wj+L_#7jm${ZtlmXOCBHOhXj=Y7B+_r+9P z!d)=dP&>ESd==Z&yQrxG63T(N;^@AZ6%Mh(H2wp!EyBeT-OBFkSkkGI2(4(ddV(~5 znVMvrFHVu$yH+-Fy1BKV@!ncGn!pLjR0bqE7 zW^d}RH&+dcJfcL4xU17$P_O73toC}ma`_r>;iJpC6S`)6C`9TO)zwd@F6^GR+`*5m zy(7Nwm3PySo0^OFxus}yt&Gc3y%I@fFP`xKwfEI;QElJaqF1!)+%Lt0|!P`OBh#1KO&F~kft3?1Krd++Cc@89rsemKv0&U5x&Yp=8R zYpwm-=d2N5I%=>G=s{f$Y{$3@xJ&dW&TVIN0xfUjZQ(_}eGdTgvM z722@Q`@QK+Z8WzHUN@h$f}Sa^-q;HzC^Rz9_96{l=WM5sah$A#o|`nev98ZFKzg@d zQ3Ebsl)MUCI6%TQ=6z1(#-5J%k(i^L!|F8C4-(jcUVbE(Af8xQTLXgr1R=HIsJAQG zHBj5O-A=FHSK(3+B;er?pZ2= z7*oC9m^c>^AgvFVWILlDJ9Ed)vSn|1d+Y8Rn^)RR&@B>?1%HB(Rv(MgZP|{DA5Gu9 zQnTK)1STEF7ql3@EY&Tu9^qbcG*5f~u)Z70>}$5dv$GpA8FV zFGCt3=Bbvz5npb@8Wa2Uc>pSRgu-ZS(8K+Ydm3=#l1@CRzSdY@Qb50=fN)KHs!a(< z0F*Y74)RJ#;`6|z&~O+GW`ie`SdAqCsyenbM{2s#vQx(#+|KBOytmqvpE_0P77aR# zf3gm5RNRU=M6V7SBR_9^NaC2fne=TqvbFo$p+b91Qp`}MNrSW8+B_jZf3tdALaSIN zq}h|(^{BnoyTf|$u_4sAW!!}pytP6pPypVY1*{z9&n$PX^pXd8<9{C^rzR!uW(>Tt z8X0%&pesMI{fE@~rV3-P6y4__dd^UD4)`g*m0CJt5k)Z0e5gdkiFrWG;ZdECQ6OsV z|Ff*BohxLR-jEMrf@_`H$ydG~ske5lh9}mBhQ&o>pq{QQ_VQfW$h_I24*!Qj7uUDv^GN4R{ zH|E`SV+^c_78=++S`yXYUu@6NLk73AcUrw;q|FG(HPu2Rcre#sCzgFjX6+S0`H`2EWVIt@cFTxA^ni+1gG89n??NZ)nc1L zovW(Y<~Vrt1c|(I;{AzSHmi3lF`p)MC~)!Jp62u?avC%m+0%O(IM*&p;FF}_$SmXL zugYGxX(t%3G}hNEpJk*GcE(g}j8kFTJmGb@;1H*(aSW9#qeSeulPE0)5|YW&KX>NF zRvEj)`1}EWUAMIU<3Vm#RyMUZMWr;v5Enm)$jj18P_MK}De<$5viH#oF}W_{-(e=r5Y+!GA9#eetjlaWgP(N{+PUN7d@z!*7y<2r>8Hy8g)Z_4K zPw6^$NyMu~oUw{WK2pZOp&*kEjKf4vpOu=`<|>!<&B=ROHS+P61vV*P>QdGO7K0Z@ zrAWD%z2>MKV-Rgw^!_IDo~LgIdaF+}kgjsAD-nl{v-i2!d=Sf1vx%&1h~)xK?&y!n zO06?_u%`_OMR6XZi?8)PODurf-Rll@VA1L1toE6Gk*#DdW6vHvw05o=Yl%@=ed3cB z%xC;>+Oh>vexl7D0_@t&Iwsv9GCUtfUhZ~(v_vDn;q}yDbmb))FVQt^PZ5$UohVOQ zLP#f9>8R}6Ob(gWh zu?W$Urzbxa72!S;g!An>*B-x15|vm0&v*M}i1NWPhrK*+iTqZeGjWzD2V&@(I=cmycs)4pCf|}XMhpo1az|acGK}yh~(wn+hITY0D3Dwp7l@6k^ zg@39nH)}W15_aa?u__G2_UlT-nRN(B%MKwYMFRxkD<%gvfbUkzD?;^4It78Dlt@{irHOP+~O0E+0v|9Tr; zP-QlL`h{>OBId^CAdKuvHet2&#%jgh(r|}bnvaQ+AbKsvjpAt-efNuqG7ao4Uvj14 zm8N@#eH1lry;>!vwWZJOo(oTwHHmRj8Zwb_^F}lBXM`MHTi}ienL)Mv#{ttu9ii0l zUE-NW#X7>Rid!gdm#?Nr%MwMP=h)JgVP8ok+1rn(_~9M>rV^ zr6anXlQv)+Y9XBtYO1{%03|In3sY=29)6t9UG;-&)#!Pu?eZ$n(_Dz2fxR!P_plYKC#svKskkm}XI>`>mo0&`v%H5z$tDLj z9hN;Vc8!|FxaUvg#kt*#J+q+$KfB*`#LPm{PeKt?t&=!fR2v+bTB;l=JXs$o=ML41 zW=$eNWIZfFZzS0GV=Q~ITlZInCw^F_%QqbKi0L}cK99gRFeoMye5@;T1uIt%=K8Q_ z6v)V5723=2?~7zlexr`@e3n zXF;u$*je)rj{ToN!Z;imOD22u(%}E=_Ns3z>d9D|5hVcrk@b((cbJJ@SZGoFOJywF zS6$(+QOeo1bN?eXNcK_e^N0=ED>Z`fxUjT^^K=ua7`yzZT66o(k&z5wVv_kl$(6An zvo%#M7at#Apd80s{b0{&VbrSMa-~#PtHNHl#H_+7h|9)P+LwXLuvuNG&^dlXx2%^b zT&H*I{=qfi-)9W^cC0Uri&yjn8{xcfN}X7Kc;+x;rnwbhWRi5|zJVC6ALFaBhb_FJ zGbbY*-2)u{QhO0u?>_Cenfv%Bz|`*`-gvv!7`q3357T-EZ*-awIzBkvwwgP^)ZclS zVRt_7zkPnjp_M!dK5aWJ(4KT2E!$>y+X|&p8)B44vAj=QnOn7+%KDb zh|nk)yjZ62+1gB4h_93cCi>sF)i;eGP1<6^BnyOPuykDR+AQZ9`VaN*S^2#1yndkX zuu)O&e(RM-xIN}Q&h$bO5K(a@oBN+~%_KnCYFvvYF%Gc2(7Td{w5RCpF(71brLXsC zRR{NF+hq`*?s=D5a$jgCHzc*zn(C9A0_AG2O;(bFORHgDB0Gz46dl*$rB}v23LIa4 z;s?Fk;#Ru& zhPK_hK9yO`9H8DL30L(|O?HXix$;x#2Sa@t*Ipz0au5#P8}wR;yrm8p%wXS6nJ;^+ zM4uX&LAbz92X9Cq8V2y_@XE^OhUAHQEi>`v{q%uirxq#2noxt87{}6-Q6wDR#j9Ci)ulW*m=v}FwWDY6UVNz zU++y7usQNhH(N#GJ=gkh?XzTR*cp{fa(d;3ocPad)qy}rStTvEg-hcLsiQRuYL68P zE$sIC59+ZZAmlwzic2k-D=Cclq4J!VhwN$H?GkrY_9pa%vFwch(XLX{Wv-It(Py;+ zjWWGGnD9amjY}IB;NqEFsZI$eSGq8S$%eQF{d1zin60y_*=R@%z3^Bhof*qn$Gffc z^{p3Yaojk`wnvX=4R>e1?OWbWE;sLxfkW+_{606+`jyXhI3Bw-P41IioNZQVm0Gf| zk5`A>ZCU&FBSV93RTNuzeGkpkp<4KX0{c-pTUcLOg0NWk&JQ?L!7t`n&KWjwa$E$h zE6A;kbU#)_TWhTJ^@sHiOxHU3T%3U_6FGIYqEX|$&Xe?wIqhKJ7T1Q@d3UxtncF)P z{(ZdTlNpzl%)*~}WlTpdp)&q%z6n*{FH*P6k`hz_n8ip$+;vQ4${Z;MU z36CY1vAop5QNuhKXa-&)_Bq+@Mk2P0G!ldte3jbySGXNEimcja_xsjO#(E0c=8PMh zp)#+@q;GZaOI1VE1rF8gMC(trqnpsHC=1Z)7uTAN+k zPq_;OP7&rv1{k&qU!gICyT*6$VJhz%E!zN$z3$2!snq>Ur3a5PpB_w}9gj}!+j5)K z_1xWVQM?e6qvR0`nj`3D;Ay@LGj^^G-=2l4S)ZTPnh5%qBWIyw_+rKVC&V-Z41Jez z9jk*4-LscFEPH{+b~DY;a|^?8Ky;&ZRHk2%WXX+N#PxEbry1_??wfE0Ghd9Lc&j#0 zQvi2QRE{U{5OAg(?KuA2e&Q2%!@NhsvbFM7e4(0C73u{F4p(s4hZ`OAD@DhT50(S4rk(-YdGI zTPYTf&yNStJX8D*iVv07$y89sVlF+?TGg^QsV(p>5azzqx4M+JiRq0}7EMCV812NJ z=9&i+e?FUbri73Dggks_`yr`#%iM0Y#eQx-O=h$y`D^U7LL{W8u(Rquar3^~ZKrgE znfJ)8=C8XytI(93pBV&mqSc!lM^M6ZPgugu>6;un`f|-5$ipqYI*@QbfSDJXYwuX! zT%|i7zODUuE=Tgvmy}olCAPk9gQR+3XJ@yn7G~tuPdqupbAP|lU}&TdlIdr^VSTz1 zLPAujQxb1t>Dwp3Ke{sdwDLaPYqh`K;Y+)@-zxHLv?3O(TgiU_#1N@3fqtlG=l%F` z&S>GOP-~#NO+QoMBx2@V_**9=tGI2#dcJa5xW!oX_Th{isEb z9LXPDywYzO4=gQP_h>zCc0l<{)?ZSGAQ{HsWp%yy7A`6C)y?7C>r54n7me+M_#fZ` zB{E3tmJpJ*_2T?w8Xe;}uDsQ1W3mP}Z1X`4_7+iLj9ZLv7^7~E)5CGkPi@2${2Ic{ zec#V{9`}?X`N-)T%~cbp#?*9+-0f)YI}Dpu6_X{M@H*}Mp97@lyoG#Z6!*g2nW9awZ5m-iVI);VS+uP|& z!fteGKqX;1Gba79rdbEFd>6vqbw9bupV7@UC7`BZ^K-W_o2fA8NO?(z(9~^%QSU@9 z+#Mh63v7B(HYOG*2nXh%mH5T=1JhVg&4ye-+g)e zZL<(x%yLK!pkAgx(rZR&eG*|QsZ%$(MJDhL(*-e)>ndUc`k|i%mg|({%`u!+foJN! z8qXMiVtD2{mL)(Z2A^LhFTh5ZI3B=pkN-G~7ZYqB0BhkYv=`I}to$(zB;olb=Zd}gRn-*<`!Gx#g z-?+q1nJ0Zg5YA&zom>cf7fCIuGWB(G1#JTC#0Us(EeJVhfu~ zKtQdedP%x)4>fHyUfKF4)tP8&nGif)Yu_VE5@6lQ?uav^`HGx?MwF7Eb`N zin@L7Z5I*_D!o9G&^V{90s#u+p>TPr$7= zQQrLU>3Q}#*m3ko*$?1A+IW%ix?Nc5c!*@^pB; z%3G`jbKAZ~<_L=<>tCh!K>^rw^s;)9?#l2LU&eVl5bQAQ zW%l^N+l5J|7}&R=SWUggSVG`;bK(QffmB%>)GQcDz-=wIL9eWaVeypG6% zpa(v$?gSbRufJTSl-lXZ-`lyQPq@8BM`gsTdRQ(9i-7t2$)Sf`UEc^}VRz7cyC`S4@l) z;pflMF%_Dbe@HV<;w3EjPu{vM+3eMy7%p|F8J?q=evwZ+p}Fo?lX;5CA;59prA0ZV zopeD`hei-=oRVrXfa4pAi-)*isO%@32!G zIkpD%$j!!1GHvW<1h4dboUHK{+w`;Yzt(Chkr#q5_oUBGov`2DdL^ z*Lee*snhou|6HN!!@zL8H^oX84EB%EW<&y`0 zm|_e%Xq&c*(oxo#fPaEGj%1uD`j;)13N*l0%QX#xp6;5mvc5Jbtl3At38wpXl55DR zq)(M8>=LwwCw`J2oJ5!3;388pIou4NqTglwH`mOv%M) z@zv8E!-@03Ois8GvDO@g01!c%Ta~Y1_c?EqzLWn5} z6<^C|a(7ODptI5{3Y@ zV3_i$*$ve9$KGRR(wQI;%OBW3Xg~`d=y`6ddHQVN@tHArW4Qk;0HnD;sOHW|)NNk=mK*Q5O0D_qE5hql+gBqh)E|>dIktpR`{x(QETgMw zaV)RrdBg{(=+nNTkYN#*>#?SEvZbr`1u6_qqf-O9u$wu}DY~A5RtQ={DO6X?inD;= z<(NX0yY5SrmA;oGkm@t@HC3{#o)bZRu|IrNoRQgom4D-4zZNg&k9mt_o(gGS(KF>n zwl6eKk5lO^xq zLhj9{#)Ahx;rqC3d>HJJrhX! zuWqw<$mE;fJfixSx>(YY2sc=nCoNU=FP8eR4sh_CvC`&5;)(u4LM?{k$P`cws|z4>oDknP9@GLA-C7hzf1fBM9p1=3)p2}dvgm-6yvk|tYM5YSfnuVx>y z(rA?2{!7!fk}*c?=cSfB`mbh+SZNd2hR*UVBe7eoqPY$%#{Tz?YDWq{5J2k zyIp&)(z_xG92|lND)KTqzdiXkP+XJrzk%X9wEYH(zrx4wFn67h{04{L;PAhc_cu8F de*g|g0WYHF_33iQKH*@0DhitNm9j5`{~r-2KBfQw literal 112745 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

-brvx`F~DCWm`GkWHjF3M?oOc)<|j6L5nZUC!d0 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 diff --git a/images/diagram.py b/images/diagram.py index 26d9040..b063e70 100644 --- a/images/diagram.py +++ b/images/diagram.py @@ -5,7 +5,7 @@ from diagrams.onprem.network import Haproxy from diagrams.aws.compute import ECS -with Diagram(name="Advanced Prometheus Cluster Setup", show=False, direction="TB"): +with Diagram(name="Advanced Prometheus Cluster Setup", show=False): haproxy = Haproxy("haproxy") with Cluster("App Cluster"): @@ -35,13 +35,13 @@ push1 << Edge(color="brown") << prom2 push1 << Edge(color="brown") << prom3 - push2 << Edge(label="pull", color="brown") << prom2 push2 << Edge(color="brown") << prom1 + push2 << Edge(label="pull", color="brown") << prom2 push2 << Edge(color="brown") << prom3 - push3 << Edge(label="pull", color="brown") << prom3 push3 << Edge(color="brown") << prom1 push3 << Edge(color="brown") << prom2 + push3 << Edge(label="pull", color="brown") << prom3 prom1 << Edge(label="pull") << prom2 prom1 << Edge(label="pull") << prom3 From 0049781d00a426adad23f90c218660bc57c379a6 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 13:24:15 +0200 Subject: [PATCH 45/83] update prometheus config --- docker/prometheus/prometheus1.yml | 4 ++-- docker/prometheus/prometheus2.yml | 2 +- docker/prometheus/prometheus3.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/prometheus/prometheus1.yml b/docker/prometheus/prometheus1.yml index 684ef3e..c0544e5 100644 --- a/docker/prometheus/prometheus1.yml +++ b/docker/prometheus/prometheus1.yml @@ -3,7 +3,7 @@ global: scrape_configs: - job_name: 'federate' - scrape_interval: 500ms + scrape_interval: 5s honor_labels: true metrics_path: '/federate' params: @@ -16,7 +16,7 @@ scrape_configs: - 'prometheus3:9093' - job_name: 'pushgateway' - scrape_interval: 100ms + scrape_interval: 500ms honor_labels: true static_configs: - targets: diff --git a/docker/prometheus/prometheus2.yml b/docker/prometheus/prometheus2.yml index 90e09a7..134d239 100644 --- a/docker/prometheus/prometheus2.yml +++ b/docker/prometheus/prometheus2.yml @@ -3,7 +3,7 @@ global: scrape_configs: - job_name: 'federate' - scrape_interval: 500ms + scrape_interval: 5s honor_labels: true metrics_path: '/federate' params: diff --git a/docker/prometheus/prometheus3.yml b/docker/prometheus/prometheus3.yml index 92e6feb..f140d8e 100644 --- a/docker/prometheus/prometheus3.yml +++ b/docker/prometheus/prometheus3.yml @@ -3,7 +3,7 @@ global: scrape_configs: - job_name: 'federate' - scrape_interval: 500ms + scrape_interval: 5s honor_labels: true metrics_path: '/federate' params: From d2874ce1c10e55172cbb080955002796b674fe9d Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 13:26:09 +0200 Subject: [PATCH 46/83] update prometheus config --- docker/prometheus/prometheus1.yml | 1 - docker/prometheus/prometheus2.yml | 1 - docker/prometheus/prometheus3.yml | 1 - 3 files changed, 3 deletions(-) diff --git a/docker/prometheus/prometheus1.yml b/docker/prometheus/prometheus1.yml index c0544e5..e3fc92d 100644 --- a/docker/prometheus/prometheus1.yml +++ b/docker/prometheus/prometheus1.yml @@ -11,7 +11,6 @@ scrape_configs: - '{job=~"morty_.*"}' static_configs: - targets: -# - 'prometheus:9091' - 'prometheus2:9092' - 'prometheus3:9093' diff --git a/docker/prometheus/prometheus2.yml b/docker/prometheus/prometheus2.yml index 134d239..9fccc51 100644 --- a/docker/prometheus/prometheus2.yml +++ b/docker/prometheus/prometheus2.yml @@ -12,7 +12,6 @@ scrape_configs: static_configs: - targets: - 'prometheus:9091' -# - 'prometheus2:9092' - 'prometheus3:9093' - job_name: 'pushgateway' diff --git a/docker/prometheus/prometheus3.yml b/docker/prometheus/prometheus3.yml index f140d8e..cb868e1 100644 --- a/docker/prometheus/prometheus3.yml +++ b/docker/prometheus/prometheus3.yml @@ -13,7 +13,6 @@ scrape_configs: - targets: - 'prometheus:9091' - 'prometheus2:9092' -# - 'prometheus3:9093' - job_name: 'pushgateway' scrape_interval: 500ms From 1aa439340f9bc8fac77d7433349a8d7c8d76c8bf Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 13:37:21 +0200 Subject: [PATCH 47/83] optimize tests --- .../AbstractPrometheusPushGatewayTest.php | 37 +++++ .../PrometheusMultiNodeHaProxyPushTest.php | 84 +++++------ .../PrometheusMultiNodePushTest.php | 132 ++++++++---------- .../PrometheusSingleNodePushTest.php | 75 ++++------ 4 files changed, 162 insertions(+), 166 deletions(-) create mode 100644 tests/Integration/AbstractPrometheusPushGatewayTest.php diff --git a/tests/Integration/AbstractPrometheusPushGatewayTest.php b/tests/Integration/AbstractPrometheusPushGatewayTest.php new file mode 100644 index 0000000..de9b78e --- /dev/null +++ b/tests/Integration/AbstractPrometheusPushGatewayTest.php @@ -0,0 +1,37 @@ +flush(); @@ -64,9 +38,11 @@ public function testPushesOneCounterMetric(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('haproxy:9090')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('haproxy:9090')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -77,17 +53,17 @@ public function testPushesOneCounterMetric(): void } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\MetricNotFoundException - * @throws \Prometheus\Exception\MetricsRegistrationException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws MetricNotFoundException + * @throws MetricsRegistrationException + * @throws StorageException */ public function testPushesCounterMetricAndIncreases(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_2_' . date('YmdHis'); + $metricName = 'some_counter_2_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - var_dump($metricFullName); +// var_dump($metricFullName); $pushGateway1 = static::buildPushGatewayClient('haproxy:9191'); $pushGateway1->flush(); @@ -103,9 +79,11 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('haproxy:9090')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('haproxy:9090')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -125,9 +103,11 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('haproxy:9090')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('haproxy:9090')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); diff --git a/tests/Integration/PrometheusMultiNodePushTest.php b/tests/Integration/PrometheusMultiNodePushTest.php index 2d74fe6..83d7d84 100644 --- a/tests/Integration/PrometheusMultiNodePushTest.php +++ b/tests/Integration/PrometheusMultiNodePushTest.php @@ -2,53 +2,27 @@ namespace Comsave\Tests\Integration; -use Comsave\MortyCountsBundle\Factory\GuzzleHttpClientFactory; -use Comsave\MortyCountsBundle\Factory\JmsSerializerFactory; -use Comsave\MortyCountsBundle\Factory\PushGatewayFactory; -use Comsave\MortyCountsBundle\Factory\RedisStorageAdapterFactory; -use Comsave\MortyCountsBundle\Services\PrometheusClient; -use Comsave\MortyCountsBundle\Services\PushGatewayClient; -use PHPUnit\Framework\TestCase; -use Prometheus\CollectorRegistry; - -class PrometheusMultiNodePushTest extends TestCase +use GuzzleHttp\Exception\GuzzleException; +use Prometheus\Exception\MetricNotFoundException; +use Prometheus\Exception\MetricsRegistrationException; +use Prometheus\Exception\StorageException; + +class PrometheusMultiNodePushTest extends AbstractPrometheusPushGatewayTest { /** @var string */ private $jobName = 'service_job'; - public static function buildPrometheusClient(string $prometheusUrl): PrometheusClient - { - return new PrometheusClient( - $prometheusUrl, - JmsSerializerFactory::build(), - GuzzleHttpClientFactory::build() - ); - } - - public static function buildPushGatewayClient(string $pushGatewayUrl): PushGatewayClient - { - $registryStorageAdapter = RedisStorageAdapterFactory::build('redis', 6379); - $registry = new CollectorRegistry($registryStorageAdapter); - - return new PushGatewayClient( - $registry, - $registryStorageAdapter, - PushGatewayFactory::build($pushGatewayUrl), - '127.0.0.1:9000' - ); - } - /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\MetricsRegistrationException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws MetricsRegistrationException + * @throws StorageException */ public function testPushesOneCounterMetric(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_1_' . date('YmdHis'); + $metricName = 'some_counter_1_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - var_dump($metricFullName); +// var_dump($metricFullName); $pushGateway1 = static::buildPushGatewayClient('pushgateway:9191'); $pushGateway1->flush(); @@ -64,9 +38,11 @@ public function testPushesOneCounterMetric(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('prometheus:9091')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus:9091')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -75,9 +51,11 @@ public function testPushesOneCounterMetric(): void $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(5, $results[0]->getValue()); - $response = static::buildPrometheusClient('prometheus2:9092')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus2:9092')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results2 = $response->getData()->getResults(); @@ -86,9 +64,11 @@ public function testPushesOneCounterMetric(): void $this->assertEquals('blue', $results2[0]->getMetric()['type']); $this->assertEquals(5, $results2[0]->getValue()); - $response = static::buildPrometheusClient('prometheus3:9093')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus3:9093')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results3 = $response->getData()->getResults(); @@ -99,17 +79,17 @@ public function testPushesOneCounterMetric(): void } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\MetricNotFoundException - * @throws \Prometheus\Exception\MetricsRegistrationException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws MetricNotFoundException + * @throws MetricsRegistrationException + * @throws StorageException */ public function testPushesCounterMetricAndIncreases(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_2_' . date('YmdHis'); + $metricName = 'some_counter_2_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - var_dump($metricFullName); +// var_dump($metricFullName); $pushGateway1 = static::buildPushGatewayClient('pushgateway:9191'); $pushGateway1->flush(); @@ -125,9 +105,11 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('prometheus:9091')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus:9091')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -136,9 +118,11 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(5, $results[0]->getValue()); - $response = static::buildPrometheusClient('prometheus2:9092')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus2:9092')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results2 = $response->getData()->getResults(); @@ -147,9 +131,11 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results2[0]->getMetric()['type']); $this->assertEquals(5, $results2[0]->getValue()); - $response = static::buildPrometheusClient('prometheus3:9093')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus3:9093')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results3 = $response->getData()->getResults(); @@ -169,9 +155,11 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('prometheus:9091')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus:9091')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -180,9 +168,11 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(6, $results[0]->getValue()); - $response = static::buildPrometheusClient('prometheus2:9092')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus2:9092')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results2 = $response->getData()->getResults(); @@ -191,9 +181,11 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results2[0]->getMetric()['type']); $this->assertEquals(6, $results2[0]->getValue()); - $response = static::buildPrometheusClient('prometheus3:9093')->query([ - 'query' => $metricFullName, - ]); + $response = static::buildPrometheusClient('prometheus3:9093')->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results3 = $response->getData()->getResults(); diff --git a/tests/Integration/PrometheusSingleNodePushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php index f53c4b3..3ba383b 100644 --- a/tests/Integration/PrometheusSingleNodePushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -2,16 +2,14 @@ namespace Comsave\Tests\Integration; -use Comsave\MortyCountsBundle\Factory\GuzzleHttpClientFactory; -use Comsave\MortyCountsBundle\Factory\JmsSerializerFactory; -use Comsave\MortyCountsBundle\Factory\PushGatewayFactory; -use Comsave\MortyCountsBundle\Factory\RedisStorageAdapterFactory; use Comsave\MortyCountsBundle\Services\PrometheusClient; use Comsave\MortyCountsBundle\Services\PushGatewayClient; -use PHPUnit\Framework\TestCase; -use Prometheus\CollectorRegistry; +use GuzzleHttp\Exception\GuzzleException; +use Prometheus\Exception\MetricNotFoundException; +use Prometheus\Exception\MetricsRegistrationException; +use Prometheus\Exception\StorageException; -class PrometheusSingleNodePushTest extends TestCase +class PrometheusSingleNodePushTest extends AbstractPrometheusPushGatewayTest { /** @var PrometheusClient */ private $prometheusClient; @@ -22,39 +20,22 @@ class PrometheusSingleNodePushTest extends TestCase /** @var string */ private $jobName = 'service_job'; - /** @var string */ - private $instanceName = '127.0.0.1:9000'; - public function setUp(): void { - $this->prometheusClient = new PrometheusClient( - 'prometheus:9091', - JmsSerializerFactory::build(), - GuzzleHttpClientFactory::build() - ); - - $registryStorageAdapter = RedisStorageAdapterFactory::build('redis', 6379); - $registry = new CollectorRegistry($registryStorageAdapter); - - $this->pushGatewayClient = new PushGatewayClient( - $registry, - $registryStorageAdapter, - PushGatewayFactory::build('pushgateway:9191'), - $this->instanceName - ); - + $this->prometheusClient = static::buildPrometheusClient('prometheus:9091'); + $this->pushGatewayClient = self::buildPushGatewayClient('pushgateway:9191'); $this->pushGatewayClient->flush(); } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\MetricsRegistrationException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws MetricsRegistrationException + * @throws StorageException */ public function testPushesOneCounterMetric(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_1_' . date('YmdHis'); + $metricName = 'some_counter_1_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $counter = $this->pushGatewayClient->getRegistry()->registerCounter( @@ -68,9 +49,11 @@ public function testPushesOneCounterMetric(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query([ - 'query' => $metricFullName, - ]); + $response = $this->prometheusClient->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -81,15 +64,15 @@ public function testPushesOneCounterMetric(): void } /** - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Prometheus\Exception\MetricNotFoundException - * @throws \Prometheus\Exception\MetricsRegistrationException - * @throws \Prometheus\Exception\StorageException + * @throws GuzzleException + * @throws MetricNotFoundException + * @throws MetricsRegistrationException + * @throws StorageException */ public function testPushesCounterMetricAndIncreases(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_2_' . date('YmdHis'); + $metricName = 'some_counter_2_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $counter = $this->pushGatewayClient->getRegistry()->registerCounter( @@ -103,9 +86,11 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query([ - 'query' => $metricFullName, - ]); + $response = $this->prometheusClient->query( + [ + 'query' => $metricFullName, + ] + ); // var_dump($response); $results = $response->getData()->getResults(); @@ -125,9 +110,11 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $results = $this->prometheusClient->query([ - 'query' => $metricFullName, - ])->getData()->getResults(); + $results = $this->prometheusClient->query( + [ + 'query' => $metricFullName, + ] + )->getData()->getResults(); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); From 0debda380ddcc6efc883fe4e031d02d480c98519 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 28 Apr 2020 13:51:43 +0200 Subject: [PATCH 48/83] clean up unit tests --- tests/Unit/MetricSerializerTest.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/Unit/MetricSerializerTest.php b/tests/Unit/MetricSerializerTest.php index 66f1b25..c9fc182 100644 --- a/tests/Unit/MetricSerializerTest.php +++ b/tests/Unit/MetricSerializerTest.php @@ -11,14 +11,6 @@ class MetricSerializerTest extends TestCase { - /** @var Serializer */ - private $jmsSerializer; - - public function setUp(): void - { - $this->jmsSerializer = JmsSerializerFactory::build(); - } - public function testDeserializesCorrectly(): void { $responseJson = '{ @@ -43,7 +35,7 @@ public function testDeserializesCorrectly(): void }'; /** @var PrometheusResponse $prometheusResponse */ - $prometheusResponse = $this->jmsSerializer->deserialize($responseJson, PrometheusResponse::class, 'json'); + $prometheusResponse = JmsSerializerFactory::build()->deserialize($responseJson, PrometheusResponse::class, 'json'); /** @var PrometheusResponseDataResult $prometheusDataResult */ $prometheusDataResult = $prometheusResponse->getData()->getResults()[0]; From db0eebf4777534742c89d958ddc5cd8b4d0f8d07 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 13:43:54 +0200 Subject: [PATCH 49/83] update tests to use ->counter --- .../Services/PushGatewayClient.php | 27 +++++++++++-------- .../PrometheusMultiNodeHaProxyPushTest.php | 8 +++--- .../PrometheusMultiNodePushTest.php | 4 +-- .../PrometheusSingleNodePushTest.php | 4 +-- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index 6df2cf4..bdcd2ad 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -5,6 +5,7 @@ use GuzzleHttp\Exception\GuzzleException; use Prometheus\CollectorRegistry; use Prometheus\Counter; +use Prometheus\Exception\MetricNotFoundException; use Prometheus\Exception\MetricsRegistrationException; use Prometheus\Exception\StorageException; use Prometheus\Gauge; @@ -84,12 +85,21 @@ public function pushAll(array $prometheusJobNames): void */ public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter { - return $this->registry->getOrRegisterCounter( - $namespace, - $name, - $help, - $labels - ); + try { + $counter = $this->getRegistry()->getCounter($namespace, $name); + } + catch (MetricNotFoundException $ex) { + // todo: try to fetch from prometheus the initial value + + $counter = $this->registry->registerCounter( + $namespace, + $name, + $help, + $labels + ); + } + + return $counter; } /** @@ -119,11 +129,6 @@ public function histogram(string $namespace, string $name, ?string $help = null, ); } - public function getRegistry(): CollectorRegistry - { - return $this->registry; - } - /** * @throws StorageException */ diff --git a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php index 4d64c94..6685ee6 100644 --- a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php +++ b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php @@ -27,7 +27,7 @@ public function testPushesOneCounterMetric(): void $pushGateway1 = static::buildPushGatewayClient('haproxy:9191'); $pushGateway1->flush(); - $counter = $pushGateway1->getRegistry()->registerCounter( + $counter = $pushGateway1->counter( $metricNamespace, $metricName, 'it increases', @@ -68,7 +68,7 @@ public function testPushesCounterMetricAndIncreases(): void $pushGateway1 = static::buildPushGatewayClient('haproxy:9191'); $pushGateway1->flush(); - $counter = $pushGateway1->getRegistry()->registerCounter( + $counter = $pushGateway1->counter( $metricNamespace, $metricName, 'it increases', @@ -92,9 +92,7 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(5, $results[0]->getValue()); - // todo: integrate initial (last) value fetch for the COUNTER - // todo: this should work even after clearing redis cache which should be done after every push - $counter = $pushGateway1->getRegistry()->getCounter( + $counter = $pushGateway1->counter( $metricNamespace, $metricName ); diff --git a/tests/Integration/PrometheusMultiNodePushTest.php b/tests/Integration/PrometheusMultiNodePushTest.php index 83d7d84..aaa7677 100644 --- a/tests/Integration/PrometheusMultiNodePushTest.php +++ b/tests/Integration/PrometheusMultiNodePushTest.php @@ -144,9 +144,7 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results3[0]->getMetric()['type']); $this->assertEquals(5, $results3[0]->getValue()); - // todo: integrate initial (last) value fetch for the COUNTER - // todo: this should work even after clearing redis cache which should be done after every push - $counter = $pushGateway1->getRegistry()->getCounter( + $counter = $pushGateway1->counter( $metricNamespace, $metricName ); diff --git a/tests/Integration/PrometheusSingleNodePushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php index 3ba383b..3be24c8 100644 --- a/tests/Integration/PrometheusSingleNodePushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -99,9 +99,7 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(5, $results[0]->getValue()); - // todo: integrate initial (last) value fetch for the COUNTER - // todo: this should work even after clearing redis cache which should be done after every push - $counter = $this->pushGatewayClient->getRegistry()->getCounter( + $counter = $this->pushGatewayClient->counter( $metricNamespace, $metricName ); From 0a1c3b079eea95dc534d931f046d02a1b6e82a62 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 14:02:08 +0200 Subject: [PATCH 50/83] extend PushGateway to accept basic auth --- .../Factory/PushGatewayFactory.php | 2 +- .../Resources/config/services.yml | 10 +-- .../Services/PushGateway.php | 90 +++++++++++++++++++ .../Services/PushGatewayClient.php | 3 +- .../PrometheusSingleNodePushTest.php | 4 +- 5 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 src/Comsave/MortyCountsBundle/Services/PushGateway.php diff --git a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php index 3467f29..d8ee0c0 100644 --- a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php +++ b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php @@ -2,7 +2,7 @@ namespace Comsave\MortyCountsBundle\Factory; -use Prometheus\PushGateway; +use Comsave\MortyCountsBundle\Services\PushGateway; class PushGatewayFactory { diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index 05a50ef..4554d71 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -17,11 +17,6 @@ services: resource: '../src/*' exclude: '../src/**/{Enum,Kernel.php}' - Prometheus\PushGateway: - factory: ['Comsave\MortyCountsBundle\PushGatewayFactory', 'build'] - arguments: - $pushGatewayUrl: '%morty_counts_pushgateway_url%'] - Prometheus\Storage\Redis: factory: ['Comsave\MortyCountsBundle\RedisStorageAdapterFactory', 'build'] arguments: @@ -44,6 +39,11 @@ services: arguments: $prometheusJobNames: '%morty_counts_prometheus_jobs%' + Comsave\MortyCountsBundle\Services\PushGateway: + factory: ['Comsave\MortyCountsBundle\PushGatewayFactory', 'build'] + arguments: + $pushGatewayUrl: '%morty_counts_pushgateway_url%'] + Comsave\MortyCountsBundle\Services\PushGatewayClient: autowire: true arguments: diff --git a/src/Comsave/MortyCountsBundle/Services/PushGateway.php b/src/Comsave/MortyCountsBundle/Services/PushGateway.php new file mode 100644 index 0000000..8351004 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/Services/PushGateway.php @@ -0,0 +1,90 @@ + [ + 'Content-Type' => RenderTextFormat::MIME_TYPE, + ], + 'connect_timeout' => 10, + 'timeout' => 20, + ]; + + public function __construct(string $address, ?string $username = null, ?string $password = null) + { + parent::__construct($address); + $this->username = $username; + $this->password = $password; + } + + private function buildServiceUrl(string $job, array $groupingKey): string + { + $url = vsprintf('http://%s/metrics/job/%s', [ + $this->address, + $job + ]); + + if (!empty($groupingKey)) { + foreach ($groupingKey as $label => $value) { + $url .= vsprintf('/%s/%s', [ + $label, + $value + ]); + } + } + + return $url; + } + + public function buildClient(): Client + { + return new Client(); + } + + /** @inheritDoc */ + private function doRequest(?CollectorRegistry $collectorRegistry, string $job, array $groupingKey, $method): void + { + $requestOptions = static::$requestOptions; + + if($this->username && $this->password) { + $requestOptions['auth'] = [ + $this->username, + $this->password + ]; + } + + if ($method != 'delete') { + $renderer = new RenderTextFormat(); + $requestOptions['body'] = $renderer->render($collectorRegistry->getMetricFamilySamples()); + } + + $response = $this->buildClient()->request( + $method, + $this->buildServiceUrl($job, $groupingKey), + $requestOptions + ); + + if (!in_array($response->getStatusCode(), [200, 202])) { + throw new \RuntimeException(vsprintf('Unexpected status code %s received from push gateway %s: $s', [ + $response->getStatusCode(), + $this->address, + $response->getBody() + ])); + } + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index bdcd2ad..43ed26d 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -10,7 +10,6 @@ use Prometheus\Exception\StorageException; use Prometheus\Gauge; use Prometheus\Histogram; -use Prometheus\PushGateway; use Prometheus\Storage\Redis; class PushGatewayClient @@ -86,7 +85,7 @@ public function pushAll(array $prometheusJobNames): void public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter { try { - $counter = $this->getRegistry()->getCounter($namespace, $name); + $counter = $this->registry->getCounter($namespace, $name); } catch (MetricNotFoundException $ex) { // todo: try to fetch from prometheus the initial value diff --git a/tests/Integration/PrometheusSingleNodePushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php index 3be24c8..ae45e7d 100644 --- a/tests/Integration/PrometheusSingleNodePushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -38,7 +38,7 @@ public function testPushesOneCounterMetric(): void $metricName = 'some_counter_1_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $counter = $this->pushGatewayClient->getRegistry()->registerCounter( + $counter = $this->pushGatewayClient->counter( $metricNamespace, $metricName, 'it increases', @@ -75,7 +75,7 @@ public function testPushesCounterMetricAndIncreases(): void $metricName = 'some_counter_2_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $counter = $this->pushGatewayClient->getRegistry()->registerCounter( + $counter = $this->pushGatewayClient->counter( $metricNamespace, $metricName, 'it increases', From 12a1463a0b4b77df5971b83e7d6f83095437cc6f Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 14:07:17 +0200 Subject: [PATCH 51/83] add PromethusClient basic auth --- .../Services/PrometheusClient.php | 39 ++++++++++++++++--- .../Services/PushGateway.php | 12 ++++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php index a2cdfcd..77234ed 100644 --- a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php @@ -6,6 +6,7 @@ use GuzzleHttp\ClientInterface; use JMS\Serializer\Serializer; +// todo: move this out to a separate repo later class PrometheusClient { /** @var string */ @@ -17,31 +18,57 @@ class PrometheusClient /** @var ClientInterface */ private $httpClient; + /** @var string|null */ + private $username; + + /** @var string|null */ + private $password; + /** * @param string $prometheusUrl * @param Serializer $jmsSerializer * @param ClientInterface $httpClient + * @param null|string $username + * @param null|string $password * @codeCoverageIgnore */ - public function __construct(string $prometheusUrl, Serializer $jmsSerializer, ClientInterface $httpClient) - { + public function __construct( + string $prometheusUrl, + Serializer $jmsSerializer, + ClientInterface $httpClient, + ?string $username = null, + ?string $password = null + ) { $this->prometheusUrl = $prometheusUrl; $this->jmsSerializer = $jmsSerializer; $this->httpClient = $httpClient; - - // todo: move this out to a separate repo later + $this->username = $username; + $this->password = $password; } + public function query(array $arguments): PrometheusResponse { $response = $this->httpClient->request( 'POST', sprintf('%s/api/v1/query', $this->prometheusUrl), - [ + $this->buildRequestOptions([ 'form_params' => $arguments, - ] + ]) ); return $this->jmsSerializer->deserialize((string)$response->getBody(), PrometheusResponse::class, 'json'); } + + private function buildRequestOptions(array $requestOptions): array + { + if ($this->username && $this->password) { + $requestOptions['auth'] = [ + $this->username, + $this->password, + ]; + } + + return $requestOptions; + } } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PushGateway.php b/src/Comsave/MortyCountsBundle/Services/PushGateway.php index 8351004..8db24d7 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGateway.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGateway.php @@ -11,13 +11,13 @@ class PushGateway extends \Prometheus\PushGateway /** @var string */ private $address; - /** @var string */ + /** @var string|null */ private $username; - /** @var string */ + /** @var string|null */ private $password; - private static $requestOptions =[ + private static $requestOptions = [ 'headers' => [ 'Content-Type' => RenderTextFormat::MIME_TYPE, ], @@ -25,6 +25,12 @@ class PushGateway extends \Prometheus\PushGateway 'timeout' => 20, ]; + /** + * @param string $address + * @param null|string $username + * @param null|string $password + * @codeCoverageIgnore + */ public function __construct(string $address, ?string $username = null, ?string $password = null) { parent::__construct($address); From 6237d4e7b10f5d33b3bb3a4fe3b96cb1afe6646c Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:04:26 +0200 Subject: [PATCH 52/83] rewrite pushgatewa --- .../Factory/PushGatewayFactory.php | 4 +- .../Services/PushGateway.php | 53 ++++++++++++++++--- .../Services/PushGatewayClient.php | 5 -- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php index d8ee0c0..c2ba49c 100644 --- a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php +++ b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php @@ -6,8 +6,8 @@ class PushGatewayFactory { - public static function build(string $pushGatewayUrl): PushGateway + public static function build(string $pushGatewayUrl, ?string $username = null, ?string $password = null): PushGateway { - return new PushGateway($pushGatewayUrl); + return new PushGateway($pushGatewayUrl, $username, $password); } } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Services/PushGateway.php b/src/Comsave/MortyCountsBundle/Services/PushGateway.php index 8db24d7..cdd5fff 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGateway.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGateway.php @@ -3,10 +3,11 @@ namespace Comsave\MortyCountsBundle\Services; use GuzzleHttp\Client; +use GuzzleHttp\Exception\GuzzleException; use Prometheus\CollectorRegistry; use Prometheus\RenderTextFormat; -class PushGateway extends \Prometheus\PushGateway +class PushGateway { /** @var string */ private $address; @@ -33,7 +34,7 @@ class PushGateway extends \Prometheus\PushGateway */ public function __construct(string $address, ?string $username = null, ?string $password = null) { - parent::__construct($address); + $this->address = $address; $this->username = $username; $this->password = $password; } @@ -57,12 +58,53 @@ private function buildServiceUrl(string $job, array $groupingKey): string return $url; } - public function buildClient(): Client + private function buildClient(): Client { return new Client(); } - /** @inheritDoc */ + + /** + * Pushes all metrics in a Collector, replacing all those with the same job. + * @param CollectorRegistry $collectorRegistry + * @param string $job + * @param array $groupingKey + * @throws GuzzleException + */ + public function push(CollectorRegistry $collectorRegistry, string $job, array $groupingKey = null): void + { + $this->doRequest($collectorRegistry, $job, $groupingKey, 'put'); + } + + /** + * Pushes all metrics in a Collector, replacing only previously pushed metrics of the same name and job. + * @param CollectorRegistry $collectorRegistry + * @param $job + * @param $groupingKey + * @throws GuzzleException + */ + public function pushAdd(CollectorRegistry $collectorRegistry, string $job, array $groupingKey = null): void + { + $this->doRequest($collectorRegistry, $job, $groupingKey, 'post'); + } + + /** + * @param string $job + * @param array $groupingKey + * @throws GuzzleException + */ + public function delete(string $job, array $groupingKey = null): void + { + $this->doRequest(null, $job, $groupingKey, 'delete'); + } + + /** + * @param CollectorRegistry $collectorRegistry + * @param string $job + * @param array $groupingKey + * @param string $method + * @throws GuzzleException + */ private function doRequest(?CollectorRegistry $collectorRegistry, string $job, array $groupingKey, $method): void { $requestOptions = static::$requestOptions; @@ -75,8 +117,7 @@ private function doRequest(?CollectorRegistry $collectorRegistry, string $job, a } if ($method != 'delete') { - $renderer = new RenderTextFormat(); - $requestOptions['body'] = $renderer->render($collectorRegistry->getMetricFamilySamples()); + $requestOptions['body'] = (new RenderTextFormat())->render($collectorRegistry->getMetricFamilySamples()); } $response = $this->buildClient()->request( diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php index 43ed26d..e404d10 100644 --- a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php +++ b/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php @@ -135,9 +135,4 @@ public function flush(): void { $this->registryStorageAdapter->flushRedis(); } - - public function setPrometheusInstanceName(string $prometheusInstanceName): void - { - $this->prometheusInstanceName = $prometheusInstanceName; - } } \ No newline at end of file From a9d22f011d7e73047363a26fe51bb428161d96e7 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:17:52 +0200 Subject: [PATCH 53/83] update tests --- .../PrometheusMultiNodeHaProxyPushTest.php | 70 ++++--- .../PrometheusMultiNodePushTest.php | 195 ------------------ 2 files changed, 38 insertions(+), 227 deletions(-) delete mode 100644 tests/Integration/PrometheusMultiNodePushTest.php diff --git a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php index 6685ee6..1a2830e 100644 --- a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php +++ b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php @@ -12,6 +12,12 @@ class PrometheusMultiNodeHaProxyPushTest extends AbstractPrometheusPushGatewayTe /** @var string */ private $jobName = 'service_job'; + private $nodes = [ + 1 => 'prometheus:9091', + 2 => 'prometheus2:9092', + 3 => 'prometheus3:9093', + ]; + /** * @throws GuzzleException * @throws MetricsRegistrationException @@ -38,18 +44,18 @@ public function testPushesOneCounterMetric(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('haproxy:9090')->query( - [ + foreach($this->nodes as $node => $server) { + $response = static::buildPrometheusClient($server)->query([ 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); - - $this->assertCount(1, $results, 'Node 1 results invalid.'); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(5, $results[0]->getValue()); + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, sprintf('Node %s results invalid.', $node)); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(5, $results[0]->getValue()); + } } /** @@ -79,18 +85,18 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('haproxy:9090')->query( - [ + foreach($this->nodes as $node => $server) { + $response = static::buildPrometheusClient($server)->query([ 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); + ]); +// var_dump($response); + $results = $response->getData()->getResults(); - $this->assertCount(1, $results, 'Node 1 results invalid.'); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(5, $results[0]->getValue()); + $this->assertCount(1, $results, sprintf('Node %s results invalid.', $node)); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(5, $results[0]->getValue()); + } $counter = $pushGateway1->counter( $metricNamespace, @@ -101,17 +107,17 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = static::buildPrometheusClient('haproxy:9090')->query( - [ + foreach($this->nodes as $node => $server) { + $response = static::buildPrometheusClient($server)->query([ 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); - - $this->assertCount(1, $results, 'Node 1 results invalid.'); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(6, $results[0]->getValue()); + ]); +// var_dump($response); + $results = $response->getData()->getResults(); + + $this->assertCount(1, $results, sprintf('Node %s results invalid.', $node)); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(6, $results[0]->getValue()); + } } } \ No newline at end of file diff --git a/tests/Integration/PrometheusMultiNodePushTest.php b/tests/Integration/PrometheusMultiNodePushTest.php deleted file mode 100644 index aaa7677..0000000 --- a/tests/Integration/PrometheusMultiNodePushTest.php +++ /dev/null @@ -1,195 +0,0 @@ -flush(); - - $counter = $pushGateway1->getRegistry()->registerCounter( - $metricNamespace, - $metricName, - 'it increases', - ['type'] - ); - $counter->incBy(5, ['blue']); - $pushGateway1->push($this->jobName); - - sleep(2); // wait for Prometheus to pull the metrics from PushGateway - - $response = static::buildPrometheusClient('prometheus:9091')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); - - $this->assertCount(1, $results, 'Node 1 results invalid.'); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(5, $results[0]->getValue()); - - $response = static::buildPrometheusClient('prometheus2:9092')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results2 = $response->getData()->getResults(); - - $this->assertCount(1, $results2, 'Node 2 results invalid.'); - $this->assertEquals($metricFullName, $results2[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results2[0]->getMetric()['type']); - $this->assertEquals(5, $results2[0]->getValue()); - - $response = static::buildPrometheusClient('prometheus3:9093')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results3 = $response->getData()->getResults(); - - $this->assertCount(1, $results3, 'Node 3 results invalid.'); - $this->assertEquals($metricFullName, $results3[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results3[0]->getMetric()['type']); - $this->assertEquals(5, $results3[0]->getValue()); - } - - /** - * @throws GuzzleException - * @throws MetricNotFoundException - * @throws MetricsRegistrationException - * @throws StorageException - */ - public function testPushesCounterMetricAndIncreases(): void - { - $metricNamespace = 'test'; - $metricName = 'some_counter_2_'.date('YmdHis'); - $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); -// var_dump($metricFullName); - - $pushGateway1 = static::buildPushGatewayClient('pushgateway:9191'); - $pushGateway1->flush(); - - $counter = $pushGateway1->getRegistry()->registerCounter( - $metricNamespace, - $metricName, - 'it increases', - ['type'] - ); - $counter->incBy(5, ['blue']); - $pushGateway1->push($this->jobName.'_2'); - - sleep(2); // wait for Prometheus to pull the metrics from PushGateway - - $response = static::buildPrometheusClient('prometheus:9091')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); - - $this->assertCount(1, $results, 'Node 1 results invalid.'); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(5, $results[0]->getValue()); - - $response = static::buildPrometheusClient('prometheus2:9092')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results2 = $response->getData()->getResults(); - - $this->assertCount(1, $results2, 'Node 2 results invalid.'); - $this->assertEquals($metricFullName, $results2[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results2[0]->getMetric()['type']); - $this->assertEquals(5, $results2[0]->getValue()); - - $response = static::buildPrometheusClient('prometheus3:9093')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results3 = $response->getData()->getResults(); - - $this->assertCount(1, $results3, 'Node 3 results invalid.'); - $this->assertEquals($metricFullName, $results3[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results3[0]->getMetric()['type']); - $this->assertEquals(5, $results3[0]->getValue()); - - $counter = $pushGateway1->counter( - $metricNamespace, - $metricName - ); - $counter->inc(['blue']); - $pushGateway1->push($this->jobName.'_2'); - - sleep(2); // wait for Prometheus to pull the metrics from PushGateway - - $response = static::buildPrometheusClient('prometheus:9091')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); - - $this->assertCount(1, $results, 'Node 1 results invalid.'); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(6, $results[0]->getValue()); - - $response = static::buildPrometheusClient('prometheus2:9092')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results2 = $response->getData()->getResults(); - - $this->assertCount(1, $results2, 'Node 2 results invalid.'); - $this->assertEquals($metricFullName, $results2[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results2[0]->getMetric()['type']); - $this->assertEquals(6, $results2[0]->getValue()); - - $response = static::buildPrometheusClient('prometheus3:9093')->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results3 = $response->getData()->getResults(); - - $this->assertCount(1, $results3, 'Node 3 results invalid.'); - $this->assertEquals($metricFullName, $results3[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results3[0]->getMetric()['type']); - $this->assertEquals(6, $results3[0]->getValue()); - } -} \ No newline at end of file From 0f03d1e3f1d462e52c5b023d344bd1739f835cf0 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:32:09 +0200 Subject: [PATCH 54/83] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e91b9a5..00f5f7e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,6 @@ Teaching Morty how to count and sending the results to Prometheus. + High Availability Option -![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) -![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) - ## Requirements 1. `Redis` (the service & the PHP extension): to act as a buffer before push and avoid latency in the code @@ -29,6 +26,9 @@ Start `docker-compose up --remove-orphans -d --build` Tests `docker exec $(docker ps | grep _php | awk '{print $1}') vendor/bin/phpunit tests` +![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) +![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) + ## License MIT From 2bd14b96057e537158a81748d343bf53b5051a3d Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:33:19 +0200 Subject: [PATCH 55/83] update diagrams --- images/basic_prometheus_cluster_setup.png | Bin 69084 -> 69972 bytes images/diagram.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/images/basic_prometheus_cluster_setup.png b/images/basic_prometheus_cluster_setup.png index 6da5aef606731a61b022dd8b8709bfc5b63b532a..0f3a769c8322470a801726d5a10ddf5c265bbd3c 100644 GIT binary patch delta 41466 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 z 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 MtS^@SbNkW%0b-s{A^-pY delta 40566 zcma&NRa9I})GeBjCN!?W-61$3xO;GS2o@l?I~#X*cL^TcA-KDR;O_2zo9{p8jC)@0 zxTD{8*RHCibFNjjXL3PHX`tV2#=z;j=)A_M7fK7=@_dysPO5kmA#V^Ai7#_KGtAAx z?keA7I;SCCy3N>EB$KhPH=K4~|E8l;!jt=gW97#czq&@v1KmMo?o6+# zhj%EdVG4%h$pMitHz&-uKFYYvKM~w+N_zBOpTL8g_^oNya^#4(EEuQF$D``vr42j? zbOq2InIgb*>MZ^=hlO^>9FKIF=O$viXo|@{y7qk;Y!(ahK_@+YUJvXxx7(ZmFYYtS z@9Wp>)loqad?scgNic1dfY%~vW}z)Q;2#d04C}G8ZI#Oyx@B@Z +&++AA>pGdjp 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 diff --git a/images/diagram.py b/images/diagram.py index b063e70..14ff75f 100644 --- a/images/diagram.py +++ b/images/diagram.py @@ -69,7 +69,7 @@ app_redis ] - with Cluster("Prom"): + with Cluster("Prometheus"): push1 = ECS('pushgateway') prom1 = Prometheus('prometheus') From dec0ec15d36b853e086288414c2b98065c3ccbb2 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:35:01 +0200 Subject: [PATCH 56/83] update diagrams --- images/basic_prometheus_cluster_setup.png | Bin 69972 -> 70660 bytes images/diagram.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/images/basic_prometheus_cluster_setup.png b/images/basic_prometheus_cluster_setup.png index 0f3a769c8322470a801726d5a10ddf5c265bbd3c..de30edfbd3a5ed21920163078478e03ed2a079ad 100644 GIT binary patch delta 44972 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 diff --git a/images/diagram.py b/images/diagram.py index 14ff75f..355e17b 100644 --- a/images/diagram.py +++ b/images/diagram.py @@ -69,7 +69,7 @@ app_redis ] - with Cluster("Prometheus"): + with Cluster("Prometheus Cluster"): push1 = ECS('pushgateway') prom1 = Prometheus('prometheus') From 62cb3479671fc5c9b6ed4d34f92c6a60409e2868 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:40:51 +0200 Subject: [PATCH 57/83] readme update --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 00f5f7e..b6a3744 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # morty-counts -Teaching Morty how to count and sending the results to Prometheus. + High Availability Option +## Symfony Prometheus + PushGateway integration + +Teaching Morty how to count and sending the results to Prometheus. +High Availability Setup ## Requirements @@ -10,19 +12,23 @@ Teaching Morty how to count and sending the results to Prometheus. + High Availa ## How does it work? -### Single-node Prometheus + Pushgateway +### Single Node Prometheus + Pushgateway + + ![](./images/basic_prometheus_cluster_setup.png) -### Multi-node Prometheus + Pushgateway +### Multi-Node Prometheus + Pushgateway Cluster + -todo details ![](./images/advanced_prometheus_cluster_setup.png) ## Development -Start `docker-compose up --remove-orphans -d --build` +Start single node `docker-compose up -d` + +Or multi node `docker-compose up -f docker-compose.multi-node.yml -d` Tests `docker exec $(docker ps | grep _php | awk '{print $1}') vendor/bin/phpunit tests` From 142ebdfd4f7d7425f8ebf86bd8dcc1ff58179cc4 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:44:38 +0200 Subject: [PATCH 58/83] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b6a3744..bd49273 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,11 @@ Teaching Morty how to count and sending the results to Prometheus. +High Availab ### Single Node Prometheus + Pushgateway +Single node is pretty straightforward. +1. Use `PushGatewayClient` to create a metric. Metric is stored in `Redis`. +2. Use `PushGatewayClient` can be pushed manually or with a command. After push metrics stored in Redis are transported to the actual `PushGateway` service. +3. `Prometheus` periodically pulls in new metrics from `PushGateway`. ![](./images/basic_prometheus_cluster_setup.png) From 07456b6a4a927660a2bbd430993af67f763b1f80 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:48:49 +0200 Subject: [PATCH 59/83] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index bd49273..bea3336 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,11 @@ Single node is pretty straightforward. ### Multi-Node Prometheus + Pushgateway Cluster +Multi-node set up works with the basics described above, with a couple exceptions: +1. There's an `Haproxy` (or other load balancer) that decides which `PushGateway` will receive the `push`. +2. Each `Prometheus` in every node pulls from every `PushGateway`. That way each `Prometheus` has the latest metrics. +3. Each `Prometheus` pulls (federates) from another 2 `Prometheus` nodes but less often. This ensures data integrity (sort of replication). ![](./images/advanced_prometheus_cluster_setup.png) From 81030560e7f0a4e2caebf171c91c22512da28e6d Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 29 Apr 2020 16:49:03 +0200 Subject: [PATCH 60/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bea3336..95e55df 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# morty-counts +# Morty Counts! ## Symfony Prometheus + PushGateway integration From debcfb4ce2b8f817c8d501404a74b04106fb72ba Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 30 Apr 2020 10:17:25 +0200 Subject: [PATCH 61/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95e55df..c41ca16 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Single node is pretty straightforward. Multi-node set up works with the basics described above, with a couple exceptions: 1. There's an `Haproxy` (or other load balancer) that decides which `PushGateway` will receive the `push`. -2. Each `Prometheus` in every node pulls from every `PushGateway`. That way each `Prometheus` has the latest metrics. +2. Each `Prometheus` pulls from every `PushGateway` in every node. That way each `Prometheus` has the latest metrics. 3. Each `Prometheus` pulls (federates) from another 2 `Prometheus` nodes but less often. This ensures data integrity (sort of replication). ![](./images/advanced_prometheus_cluster_setup.png) From 68730971ff8f06340e1be58cd2e401d5b8ed4562 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 30 Apr 2020 10:18:43 +0200 Subject: [PATCH 62/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c41ca16..4bf219b 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Multi-node set up works with the basics described above, with a couple exception 1. There's an `Haproxy` (or other load balancer) that decides which `PushGateway` will receive the `push`. 2. Each `Prometheus` pulls from every `PushGateway` in every node. That way each `Prometheus` has the latest metrics. -3. Each `Prometheus` pulls (federates) from another 2 `Prometheus` nodes but less often. This ensures data integrity (sort of replication). +3. Each `Prometheus` pulls (federates) from other `Prometheus` nodes (all but itself) though less often. This ensures data integrity (sort of replication). ![](./images/advanced_prometheus_cluster_setup.png) From 8df4312fdc2ba969091856ba20e99871a00c9e68 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 30 Apr 2020 11:55:56 +0200 Subject: [PATCH 63/83] add jms serializer fallback --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1aafea7..926f487 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "endclothing/prometheus_client_php": "^1.0", "symfony/http-kernel": "^3.4|^4.4", "symfony/console": "^3.4|^4.4", - "jms/serializer": "^3.6" + "jms/serializer": "^3.0|^2.0" }, "require-dev": { "phpunit/phpunit": "^9.1" From 9b844b10018b4fe188e953172f0d5a4a121bb19d Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 30 Apr 2020 18:28:54 +0200 Subject: [PATCH 64/83] add dependancy injection config --- README.md | 21 ++++++ composer.json | 23 +++++-- ...undle.php => ComsaveMortyCountsBundle.php} | 2 +- .../DependencyInjection/.gitignore | 0 .../ComsaveMortyCountsExtension.php | 26 ++++++++ .../DependencyInjection/Configuration.php | 61 +++++++++++++++++ .../Factory/PushGatewayFactory.php | 13 ---- .../Factory/RedisStorageAdapterFactory.php | 5 +- .../Resources/config/services.yml | 28 ++++---- .../AbstractPrometheusPushGatewayTest.php | 8 +-- .../PrometheusMultiNodeHaProxyPushTest.php | 2 +- .../PrometheusSingleNodePushTest.php | 2 +- .../DependencyInjection/ConfigurationTest.php | 66 +++++++++++++++++++ ...st__testConfigurationNoCredentials__1.json | 14 ++++ ...nfigurationTest__testConfiguration__1.json | 14 ++++ tests/Unit/MetricSerializerTest.php | 2 +- 16 files changed, 241 insertions(+), 46 deletions(-) rename src/Comsave/MortyCountsBundle/{MortyCountsBundle.php => ComsaveMortyCountsBundle.php} (67%) delete mode 100644 src/Comsave/MortyCountsBundle/DependencyInjection/.gitignore create mode 100644 src/Comsave/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php create mode 100644 src/Comsave/MortyCountsBundle/DependencyInjection/Configuration.php delete mode 100644 src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php create mode 100644 tests/Unit/DependencyInjection/ConfigurationTest.php create mode 100644 tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json create mode 100644 tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json diff --git a/README.md b/README.md index 4bf219b..774594b 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,27 @@ Teaching Morty how to count and sending the results to Prometheus. +High Availab 2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway +## Configuration + +In your `services.yml` add: + +```yaml +comsave_morty_counts: + prometheus: + host: 'prometheus:9090' + username: 'admin' + password: 'v' + instance: 'moms_basement:6666' + jobs: + - 'metric_job_name' + - 'metric_job_name2' + pushgateway: + host: 'pushgateway:9191' + username: 'admin2' + password: 'duuude2' + redis: 'redis:6379' +``` + ## How does it work? ### Single Node Prometheus + Pushgateway diff --git a/composer.json b/composer.json index 926f487..9d36741 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,34 @@ { "name": "comsave/morty-counts", - "description": "Symfony integration to push Prometheus metrics", + "description": "Symfony integration to push metrics to Prometheus + PushGateway", "license": "MIT", "require": { - "ext-redis": "*", + "php": ">=7.3", "endclothing/prometheus_client_php": "^1.0", "symfony/http-kernel": "^3.4|^4.4", "symfony/console": "^3.4|^4.4", - "jms/serializer": "^3.0|^2.0" + "jms/serializer": "^3.0|^2.0", + "comsave/dependency-injection-config-to-parameters": "^0.1.0", + "symfony/config": "^3.4|^4.4" }, "require-dev": { - "phpunit/phpunit": "^9.1" + "phpunit/phpunit": "^8.0", + "spatie/phpunit-snapshot-assertions": "^3.0" }, "autoload": { "psr-4": { - "Comsave\\": "src/Comsave" + "Comsave\\MortyCountsBundle\\": "src/Comsave/MortyCountsBundle" } }, "autoload-dev": { "psr-4": { - "Comsave\\Tests\\": "tests" + "Comsave\\MortyCountsBundle\\Tests\\": "tests" } - } + }, + "authors": [ + { + "name": "Vaidas Bagdonas", + "email": "vaidas.bagdonas@comsave.com" + } + ] } diff --git a/src/Comsave/MortyCountsBundle/MortyCountsBundle.php b/src/Comsave/MortyCountsBundle/ComsaveMortyCountsBundle.php similarity index 67% rename from src/Comsave/MortyCountsBundle/MortyCountsBundle.php rename to src/Comsave/MortyCountsBundle/ComsaveMortyCountsBundle.php index 72f18c9..91401a0 100644 --- a/src/Comsave/MortyCountsBundle/MortyCountsBundle.php +++ b/src/Comsave/MortyCountsBundle/ComsaveMortyCountsBundle.php @@ -4,6 +4,6 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; -class MortyCountsBundle extends Bundle +class ComsaveMortyCountsBundle extends Bundle { } \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/DependencyInjection/.gitignore b/src/Comsave/MortyCountsBundle/DependencyInjection/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/Comsave/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php b/src/Comsave/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php new file mode 100644 index 0000000..c374310 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php @@ -0,0 +1,26 @@ +processConfiguration($configuration, $configs), + Configuration::$configurationTreeRoot + ); + + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/DependencyInjection/Configuration.php b/src/Comsave/MortyCountsBundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000..28d57c7 --- /dev/null +++ b/src/Comsave/MortyCountsBundle/DependencyInjection/Configuration.php @@ -0,0 +1,61 @@ +root(static::$configurationTreeRoot) + ->children() + ->arrayNode('prometheus') + ->children() + ->scalarNode('host') + ->example('localhost:9090') + ->isRequired() + ->end() + ->scalarNode('username') + ->defaultNull() + ->end() + ->scalarNode('password') + ->defaultNull() + ->end() + ->scalarNode('instance') + ->defaultValue('localhost') + ->isRequired() + ->end() +// ->arrayNode('jobs') +// ->end() + ->end() + ->end() + ->arrayNode('pushgateway') + ->children() + ->scalarNode('host') + ->example('localhost:9191') + ->isRequired() + ->end() + ->scalarNode('redis') + ->example('localhost:6379') + ->isRequired() + ->end() + ->scalarNode('username') + ->defaultNull() + ->end() + ->scalarNode('password') + ->defaultNull() + ->end() + ->end() + ->end() + ->end(); + + return $treeBuilder; + } +} \ No newline at end of file diff --git a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php b/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php deleted file mode 100644 index c2ba49c..0000000 --- a/src/Comsave/MortyCountsBundle/Factory/PushGatewayFactory.php +++ /dev/null @@ -1,13 +0,0 @@ - $redisHost, 'port' => $redisPort, - 'password' => $redisPassword ] ); } diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/Comsave/MortyCountsBundle/Resources/config/services.yml index 4554d71..82c209e 100644 --- a/src/Comsave/MortyCountsBundle/Resources/config/services.yml +++ b/src/Comsave/MortyCountsBundle/Resources/config/services.yml @@ -1,11 +1,4 @@ parameters: - morty_counts_prometheus_url: 'prometheus:9090' - morty_counts_pushgateway_url: 'pushgateway:9191' - morty_counts_prometheus_instance: 'my_custom_push_service_host_or_other_group_name' - morty_counts_prometheus_jobs: - - 'push_job' - morty_counts_redis_host: 'redis' - morty_counts_redis_port: 6379 services: _defaults: @@ -19,13 +12,10 @@ services: Prometheus\Storage\Redis: factory: ['Comsave\MortyCountsBundle\RedisStorageAdapterFactory', 'build'] - arguments: - $redisHost: '%morty_counts_redis_host%'] - $redisPort: '%morty_counts_redis_port%'] + arguments: ['%comsave_morty_counts.pushgateway.redis%'] Prometheus\CollectorRegistry: - arguments: - $adapter: Prometheus\Storage\Redis + arguments: [Prometheus\Storage\Redis] GuzzleHttp\Client: factory: ['@Comsave\MortyCountsBundle\GuzzleHttpClientFactory', 'build'] @@ -37,19 +27,25 @@ services: autowire: true autoconfigure: true arguments: - $prometheusJobNames: '%morty_counts_prometheus_jobs%' + $prometheusJobNames: '%comsave_morty_counts.prometheus.jobs%' Comsave\MortyCountsBundle\Services\PushGateway: factory: ['Comsave\MortyCountsBundle\PushGatewayFactory', 'build'] arguments: - $pushGatewayUrl: '%morty_counts_pushgateway_url%'] + - '%comsave_morty_counts.pushgateway.host%' + - '%comsave_morty_counts.pushgateway.username%' + - '%comsave_morty_counts.pushgateway.password%' Comsave\MortyCountsBundle\Services\PushGatewayClient: + public: true autowire: true arguments: - $prometheusInstanceName: '%morty_counts_prometheus_instance%' + $prometheusInstanceName: '%comsave_morty_counts.prometheus.instance%' Comsave\MortyCountsBundle\Services\PrometheusClient: + public: true autowire: true arguments: - $prometheusUrl: '%morty_counts_prometheus_url%' + $prometheusUrl: '%comsave_morty_counts.prometheus.host%' + $username: '%comsave_morty_counts.prometheus.username%' + $password: '%comsave_morty_counts.prometheus.password%' diff --git a/tests/Integration/AbstractPrometheusPushGatewayTest.php b/tests/Integration/AbstractPrometheusPushGatewayTest.php index de9b78e..e987a5e 100644 --- a/tests/Integration/AbstractPrometheusPushGatewayTest.php +++ b/tests/Integration/AbstractPrometheusPushGatewayTest.php @@ -1,12 +1,12 @@ [ + 'host' => 'prometheus:9090', + 'username' => 'admin', + 'password' => 'duuude', + 'instance' => 'moms_basement:6666', +// 'jobs' => [ +// 'intense_server', +// ], + // todo: fix jobs conf + ], + 'pushgateway' => [ + 'host' => 'pushgateway:9191', + 'username' => 'admin2', + 'password' => 'duuude2', + 'redis' => 'redis:6379', + ], + ]; + + $configuration = new Configuration(); + + $configNode = $configuration->getConfigTreeBuilder()->buildTree(); + $resultConfig = $configNode->finalize($configNode->normalize($inputOutput)); + + $this->assertMatchesJsonSnapshot($resultConfig); + } + + public function testConfigurationNoCredentials(): void + { + $inputOutput = [ + 'prometheus' => [ + 'host' => 'prometheus:9090', + 'instance' => 'moms_basement:6666', +// 'jobs' => [ +// 'intense_server', +// ], + // todo: fix jobs conf + ], + 'pushgateway' => [ + 'host' => 'pushgateway:9191', + 'redis' => 'redis:6379', + ], + ]; + + $configuration = new Configuration(); + + $configNode = $configuration->getConfigTreeBuilder()->buildTree(); + $resultConfig = $configNode->finalize($configNode->normalize($inputOutput)); + + $this->assertMatchesJsonSnapshot($resultConfig); + } +} \ No newline at end of file diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json new file mode 100644 index 0000000..e91a906 --- /dev/null +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json @@ -0,0 +1,14 @@ +{ + "prometheus": { + "host": "prometheus:9090", + "instance": "moms_basement:6666", + "username": null, + "password": null + }, + "pushgateway": { + "host": "pushgateway:9191", + "redis": "redis:6379", + "username": null, + "password": null + } +} diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json new file mode 100644 index 0000000..5088d12 --- /dev/null +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json @@ -0,0 +1,14 @@ +{ + "prometheus": { + "host": "prometheus:9090", + "username": "admin", + "password": "duuude", + "instance": "moms_basement:6666" + }, + "pushgateway": { + "host": "pushgateway:9191", + "username": "admin2", + "password": "duuude2", + "redis": "redis:6379" + } +} diff --git a/tests/Unit/MetricSerializerTest.php b/tests/Unit/MetricSerializerTest.php index c9fc182..a5b3a0e 100644 --- a/tests/Unit/MetricSerializerTest.php +++ b/tests/Unit/MetricSerializerTest.php @@ -1,6 +1,6 @@ Date: Thu, 30 Apr 2020 18:29:46 +0200 Subject: [PATCH 65/83] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 774594b..4bd7e8a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ comsave_morty_counts: prometheus: host: 'prometheus:9090' username: 'admin' - password: 'v' + password: 'duuude' instance: 'moms_basement:6666' jobs: - 'metric_job_name' From 9fc9dd567a5c3de55f2de4900a7e3bd41dbf26bd Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Thu, 30 Apr 2020 18:32:13 +0200 Subject: [PATCH 66/83] update readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4bd7e8a..0b9a85e 100644 --- a/README.md +++ b/README.md @@ -18,16 +18,16 @@ In your `services.yml` add: comsave_morty_counts: prometheus: host: 'prometheus:9090' - username: 'admin' - password: 'duuude' - instance: 'moms_basement:6666' + username: 'admin' # optional + password: 'duuude' # optional + instance: 'moms_basement:6666' # your server host/name/etc jobs: - 'metric_job_name' - 'metric_job_name2' pushgateway: host: 'pushgateway:9191' - username: 'admin2' - password: 'duuude2' + username: 'admin2' # optional + password: 'duuude2' # optional redis: 'redis:6379' ``` From 123da5e291654ce3d74872736d6e9087a43e43b4 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Fri, 1 May 2020 11:13:57 +0200 Subject: [PATCH 67/83] update autoload --- composer.json | 2 +- .../MortyCountsBundle/Command/PrometheusPushCommand.php | 0 .../MortyCountsBundle/ComsaveMortyCountsBundle.php | 0 .../DependencyInjection/ComsaveMortyCountsExtension.php | 0 .../MortyCountsBundle/DependencyInjection/Configuration.php | 0 .../Factory/HttpClientFactory.php} | 5 +++-- .../MortyCountsBundle/Factory/JmsSerializerFactory.php | 0 .../MortyCountsBundle/Factory/RedisStorageAdapterFactory.php | 0 .../MortyCountsBundle/Model/PrometheusResponse.php | 0 .../MortyCountsBundle/Model/PrometheusResponseData.php | 0 .../MortyCountsBundle/Model/PrometheusResponseDataResult.php | 0 .../MortyCountsBundle/Resources/config/services.yml | 0 .../MortyCountsBundle/Services/PrometheusClient.php | 0 src/{Comsave => }/MortyCountsBundle/Services/PushGateway.php | 0 .../MortyCountsBundle/Services/PushGatewayClient.php | 0 tests/Integration/AbstractPrometheusPushGatewayTest.php | 4 ++-- 16 files changed, 6 insertions(+), 5 deletions(-) rename src/{Comsave => }/MortyCountsBundle/Command/PrometheusPushCommand.php (100%) rename src/{Comsave => }/MortyCountsBundle/ComsaveMortyCountsBundle.php (100%) rename src/{Comsave => }/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php (100%) rename src/{Comsave => }/MortyCountsBundle/DependencyInjection/Configuration.php (100%) rename src/{Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php => MortyCountsBundle/Factory/HttpClientFactory.php} (50%) rename src/{Comsave => }/MortyCountsBundle/Factory/JmsSerializerFactory.php (100%) rename src/{Comsave => }/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php (100%) rename src/{Comsave => }/MortyCountsBundle/Model/PrometheusResponse.php (100%) rename src/{Comsave => }/MortyCountsBundle/Model/PrometheusResponseData.php (100%) rename src/{Comsave => }/MortyCountsBundle/Model/PrometheusResponseDataResult.php (100%) rename src/{Comsave => }/MortyCountsBundle/Resources/config/services.yml (100%) rename src/{Comsave => }/MortyCountsBundle/Services/PrometheusClient.php (100%) rename src/{Comsave => }/MortyCountsBundle/Services/PushGateway.php (100%) rename src/{Comsave => }/MortyCountsBundle/Services/PushGatewayClient.php (100%) diff --git a/composer.json b/composer.json index 9d36741..1619e5b 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ }, "autoload": { "psr-4": { - "Comsave\\MortyCountsBundle\\": "src/Comsave/MortyCountsBundle" + "Comsave\\MortyCountsBundle\\": "src/MortyCountsBundle" } }, "autoload-dev": { diff --git a/src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php b/src/MortyCountsBundle/Command/PrometheusPushCommand.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Command/PrometheusPushCommand.php rename to src/MortyCountsBundle/Command/PrometheusPushCommand.php diff --git a/src/Comsave/MortyCountsBundle/ComsaveMortyCountsBundle.php b/src/MortyCountsBundle/ComsaveMortyCountsBundle.php similarity index 100% rename from src/Comsave/MortyCountsBundle/ComsaveMortyCountsBundle.php rename to src/MortyCountsBundle/ComsaveMortyCountsBundle.php diff --git a/src/Comsave/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php b/src/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php similarity index 100% rename from src/Comsave/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php rename to src/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php diff --git a/src/Comsave/MortyCountsBundle/DependencyInjection/Configuration.php b/src/MortyCountsBundle/DependencyInjection/Configuration.php similarity index 100% rename from src/Comsave/MortyCountsBundle/DependencyInjection/Configuration.php rename to src/MortyCountsBundle/DependencyInjection/Configuration.php diff --git a/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php b/src/MortyCountsBundle/Factory/HttpClientFactory.php similarity index 50% rename from src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php rename to src/MortyCountsBundle/Factory/HttpClientFactory.php index 4dcf291..b5f979a 100644 --- a/src/Comsave/MortyCountsBundle/Factory/GuzzleHttpClientFactory.php +++ b/src/MortyCountsBundle/Factory/HttpClientFactory.php @@ -3,10 +3,11 @@ namespace Comsave\MortyCountsBundle\Factory; use GuzzleHttp\Client; +use GuzzleHttp\ClientInterface; -class GuzzleHttpClientFactory +class HttpClientFactory { - public static function build(array $options = []): Client + public static function build(array $options = []): ClientInterface { return new Client($options); } diff --git a/src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php b/src/MortyCountsBundle/Factory/JmsSerializerFactory.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Factory/JmsSerializerFactory.php rename to src/MortyCountsBundle/Factory/JmsSerializerFactory.php diff --git a/src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php b/src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php rename to src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponse.php b/src/MortyCountsBundle/Model/PrometheusResponse.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Model/PrometheusResponse.php rename to src/MortyCountsBundle/Model/PrometheusResponse.php diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php b/src/MortyCountsBundle/Model/PrometheusResponseData.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Model/PrometheusResponseData.php rename to src/MortyCountsBundle/Model/PrometheusResponseData.php diff --git a/src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php b/src/MortyCountsBundle/Model/PrometheusResponseDataResult.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Model/PrometheusResponseDataResult.php rename to src/MortyCountsBundle/Model/PrometheusResponseDataResult.php diff --git a/src/Comsave/MortyCountsBundle/Resources/config/services.yml b/src/MortyCountsBundle/Resources/config/services.yml similarity index 100% rename from src/Comsave/MortyCountsBundle/Resources/config/services.yml rename to src/MortyCountsBundle/Resources/config/services.yml diff --git a/src/Comsave/MortyCountsBundle/Services/PrometheusClient.php b/src/MortyCountsBundle/Services/PrometheusClient.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Services/PrometheusClient.php rename to src/MortyCountsBundle/Services/PrometheusClient.php diff --git a/src/Comsave/MortyCountsBundle/Services/PushGateway.php b/src/MortyCountsBundle/Services/PushGateway.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Services/PushGateway.php rename to src/MortyCountsBundle/Services/PushGateway.php diff --git a/src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php b/src/MortyCountsBundle/Services/PushGatewayClient.php similarity index 100% rename from src/Comsave/MortyCountsBundle/Services/PushGatewayClient.php rename to src/MortyCountsBundle/Services/PushGatewayClient.php diff --git a/tests/Integration/AbstractPrometheusPushGatewayTest.php b/tests/Integration/AbstractPrometheusPushGatewayTest.php index e987a5e..2f7ac3f 100644 --- a/tests/Integration/AbstractPrometheusPushGatewayTest.php +++ b/tests/Integration/AbstractPrometheusPushGatewayTest.php @@ -2,7 +2,7 @@ namespace Comsave\MortyCountsBundle\Tests\Integration; -use Comsave\MortyCountsBundle\Factory\GuzzleHttpClientFactory; +use Comsave\MortyCountsBundle\Factory\HttpClientFactory; use Comsave\MortyCountsBundle\Factory\JmsSerializerFactory; use Comsave\MortyCountsBundle\Factory\RedisStorageAdapterFactory; use Comsave\MortyCountsBundle\Services\PrometheusClient; @@ -18,7 +18,7 @@ public static function buildPrometheusClient(string $prometheusUrl): PrometheusC return new PrometheusClient( $prometheusUrl, JmsSerializerFactory::build(), - GuzzleHttpClientFactory::build() + HttpClientFactory::build() ); } From 7e265b6e3b5105f09ed05df7da901239efe12922 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Fri, 1 May 2020 11:14:58 +0200 Subject: [PATCH 68/83] update readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 0b9a85e..36960cd 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,11 @@ comsave_morty_counts: redis: 'redis:6379' ``` +Add the bundle to your Symfony kernel. +```php +new Comsave\MortyCountsBundle\ComsaveMortyCountsBundle(), +``` + ## How does it work? ### Single Node Prometheus + Pushgateway From 29f4ca4843c49e368baf1e511dd869a2986e75dc Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Fri, 1 May 2020 12:16:36 +0200 Subject: [PATCH 69/83] update configuration options & services --- .../ComsaveMortyCountsExtension.php | 10 ++++----- .../DependencyInjection/Configuration.php | 14 +++++++----- .../Resources/config/services.yml | 22 +++++++------------ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php b/src/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php index c374310..7c6da6b 100644 --- a/src/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php +++ b/src/MortyCountsBundle/DependencyInjection/ComsaveMortyCountsExtension.php @@ -10,17 +10,17 @@ class ComsaveMortyCountsExtension extends Extension { - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $containerBuilder) { - $configuration = new Configuration(); + $processedConfigs = $this->processConfiguration(new Configuration(), $configs); DependencyInjectionConfigsToParams::setupConfigurationParameters( - $container, - $this->processConfiguration($configuration, $configs), + $containerBuilder, + $processedConfigs, Configuration::$configurationTreeRoot ); - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader = new Loader\YamlFileLoader($containerBuilder, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); } } \ No newline at end of file diff --git a/src/MortyCountsBundle/DependencyInjection/Configuration.php b/src/MortyCountsBundle/DependencyInjection/Configuration.php index 28d57c7..659abf1 100644 --- a/src/MortyCountsBundle/DependencyInjection/Configuration.php +++ b/src/MortyCountsBundle/DependencyInjection/Configuration.php @@ -17,9 +17,10 @@ public function getConfigTreeBuilder() ->root(static::$configurationTreeRoot) ->children() ->arrayNode('prometheus') + ->addDefaultsIfNotSet() ->children() ->scalarNode('host') - ->example('localhost:9090') + ->defaultValue('localhost:9090') ->isRequired() ->end() ->scalarNode('username') @@ -32,18 +33,21 @@ public function getConfigTreeBuilder() ->defaultValue('localhost') ->isRequired() ->end() -// ->arrayNode('jobs') -// ->end() + ->arrayNode('jobs') + ->useAttributeAsKey('key', false) + ->prototype('scalar')->end() + ->end() ->end() ->end() ->arrayNode('pushgateway') + ->addDefaultsIfNotSet() ->children() ->scalarNode('host') - ->example('localhost:9191') + ->defaultValue('localhost:9191') ->isRequired() ->end() ->scalarNode('redis') - ->example('localhost:6379') + ->defaultValue('localhost:6379') ->isRequired() ->end() ->scalarNode('username') diff --git a/src/MortyCountsBundle/Resources/config/services.yml b/src/MortyCountsBundle/Resources/config/services.yml index 82c209e..3b03781 100644 --- a/src/MortyCountsBundle/Resources/config/services.yml +++ b/src/MortyCountsBundle/Resources/config/services.yml @@ -6,45 +6,39 @@ services: autoconfigure: true public: false - Comsave\: - resource: '../src/*' - exclude: '../src/**/{Enum,Kernel.php}' + Comsave\MortyCountsBundle\: + resource: '../../*' + exclude: '../../{DependencyInjection,Exception,Model,Kernel.php}' Prometheus\Storage\Redis: - factory: ['Comsave\MortyCountsBundle\RedisStorageAdapterFactory', 'build'] + factory: ['Comsave\MortyCountsBundle\Factory\RedisStorageAdapterFactory', 'build'] arguments: ['%comsave_morty_counts.pushgateway.redis%'] Prometheus\CollectorRegistry: - arguments: [Prometheus\Storage\Redis] + autowire: false + arguments: ['@Prometheus\Storage\Redis'] GuzzleHttp\Client: - factory: ['@Comsave\MortyCountsBundle\GuzzleHttpClientFactory', 'build'] + factory: ['Comsave\MortyCountsBundle\Factory\GuzzleHttpClientFactory', 'build'] JMS\Serializer\Serializer: - factory: ['@Comsave\MortyCountsBundle\JmsSerializerFactory', 'build'] + factory: ['Comsave\MortyCountsBundle\Factory\JmsSerializerFactory', 'build'] Comsave\MortyCountsBundle\Command\PrometheusPushCommand: - autowire: true - autoconfigure: true arguments: $prometheusJobNames: '%comsave_morty_counts.prometheus.jobs%' Comsave\MortyCountsBundle\Services\PushGateway: - factory: ['Comsave\MortyCountsBundle\PushGatewayFactory', 'build'] arguments: - '%comsave_morty_counts.pushgateway.host%' - '%comsave_morty_counts.pushgateway.username%' - '%comsave_morty_counts.pushgateway.password%' Comsave\MortyCountsBundle\Services\PushGatewayClient: - public: true - autowire: true arguments: $prometheusInstanceName: '%comsave_morty_counts.prometheus.instance%' Comsave\MortyCountsBundle\Services\PrometheusClient: - public: true - autowire: true arguments: $prometheusUrl: '%comsave_morty_counts.prometheus.host%' $username: '%comsave_morty_counts.prometheus.username%' From 2f6ee0943a49c6ce1245e62151e7fd323aaa962a Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Mon, 4 May 2020 11:23:44 +0200 Subject: [PATCH 70/83] cast redis port --- src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php b/src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php index 07fe137..a83ccde 100644 --- a/src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php +++ b/src/MortyCountsBundle/Factory/RedisStorageAdapterFactory.php @@ -13,7 +13,7 @@ public static function build(string $redisUrl): Redis return new Redis( [ 'host' => $redisHost, - 'port' => $redisPort, + 'port' => (int)$redisPort, ] ); } From 388b40f9a30ec5f09cc0ea572c856a382ebb1742 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Mon, 4 May 2020 13:18:29 +0200 Subject: [PATCH 71/83] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 36960cd..b2cb439 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Morty Counts! +# PrometheusPushGatewayBundle ## Symfony Prometheus + PushGateway integration -Teaching Morty how to count and sending the results to Prometheus. +High Availability Setup +Send metrics to Prometheus. +High Availability Setup ## Requirements @@ -15,7 +15,7 @@ Teaching Morty how to count and sending the results to Prometheus. +High Availab In your `services.yml` add: ```yaml -comsave_morty_counts: +comsave_prometheus_pushgateway: prometheus: host: 'prometheus:9090' username: 'admin' # optional @@ -33,7 +33,7 @@ comsave_morty_counts: Add the bundle to your Symfony kernel. ```php -new Comsave\MortyCountsBundle\ComsaveMortyCountsBundle(), +new Comsave\PrometheusPushGatewayBundle\ComsavePrometheusPushGatewayBundle(), ``` ## How does it work? From d9c7b8141ed6bc1f978bafe28ef4167402279edd Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Mon, 4 May 2020 13:23:40 +0200 Subject: [PATCH 72/83] update bundle name --- README.md | 9 +-- composer.json | 6 +- .../ComsaveMortyCountsBundle.php | 9 --- .../Resources/config/services.yml | 45 --------------- .../Command/PrometheusPushCommand.php | 4 +- .../ComsavePrometheusPushGatewayBundle.php | 9 +++ .../ComsaveMortyCountsExtension.php | 4 +- .../DependencyInjection/Configuration.php | 4 +- .../Factory/HttpClientFactory.php | 2 +- .../Factory/JmsSerializerFactory.php | 2 +- .../Factory/RedisStorageAdapterFactory.php | 2 +- .../Model/PrometheusResponse.php | 4 +- .../Model/PrometheusResponseData.php | 4 +- .../Model/PrometheusResponseDataResult.php | 2 +- .../Resources/config/services.yml | 45 +++++++++++++++ .../Services/PrometheusClient.php | 5 +- .../Services/PushGateway.php | 2 +- .../Services/PushGatewayClient.php | 32 +++++++++-- .../AbstractPrometheusPushGatewayTest.php | 17 +++--- .../PrometheusMultiNodeHaProxyPushTest.php | 6 +- .../PrometheusSingleNodePushTest.php | 57 +++++++++++++++++-- .../DependencyInjection/ConfigurationTest.php | 4 +- tests/Unit/MetricSerializerTest.php | 10 ++-- 23 files changed, 175 insertions(+), 109 deletions(-) delete mode 100644 src/MortyCountsBundle/ComsaveMortyCountsBundle.php delete mode 100644 src/MortyCountsBundle/Resources/config/services.yml rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Command/PrometheusPushCommand.php (93%) create mode 100644 src/PrometheusPushGatewayBundle/ComsavePrometheusPushGatewayBundle.php rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/DependencyInjection/ComsaveMortyCountsExtension.php (86%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/DependencyInjection/Configuration.php (93%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Factory/HttpClientFactory.php (79%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Factory/JmsSerializerFactory.php (80%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Factory/RedisStorageAdapterFactory.php (86%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Model/PrometheusResponse.php (81%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Model/PrometheusResponseData.php (81%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Model/PrometheusResponseDataResult.php (93%) create mode 100644 src/PrometheusPushGatewayBundle/Resources/config/services.yml rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Services/PrometheusClient.php (93%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Services/PushGateway.php (98%) rename src/{MortyCountsBundle => PrometheusPushGatewayBundle}/Services/PushGatewayClient.php (76%) diff --git a/README.md b/README.md index 36960cd..c8d8165 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ comsave_morty_counts: Add the bundle to your Symfony kernel. ```php -new Comsave\MortyCountsBundle\ComsaveMortyCountsBundle(), +new Comsave\PrometheusPushGatewayBundle\ComsavePrometheusPushGatewayBundle(), ``` ## How does it work? @@ -66,11 +66,6 @@ Or multi node `docker-compose up -f docker-compose.multi-node.yml -d` Tests `docker exec $(docker ps | grep _php | awk '{print $1}') vendor/bin/phpunit tests` -![](https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif) -![](https://media.giphy.com/media/RH1IFq2GT0Oau8NRWX/giphy.gif) - ## License -MIT - -![](https://media.giphy.com/media/e6tJpLvjY8jXa/giphy.gif) +MIT \ No newline at end of file diff --git a/composer.json b/composer.json index 1619e5b..2265d22 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "comsave/morty-counts", + "name": "comsave/prometheus-pushgateway-bundle", "description": "Symfony integration to push metrics to Prometheus + PushGateway", "license": "MIT", "require": { @@ -17,12 +17,12 @@ }, "autoload": { "psr-4": { - "Comsave\\MortyCountsBundle\\": "src/MortyCountsBundle" + "Comsave\\PrometheusPushGatewayBundle\\": "src/PrometheusPushGatewayBundle" } }, "autoload-dev": { "psr-4": { - "Comsave\\MortyCountsBundle\\Tests\\": "tests" + "Comsave\\PrometheusPushGatewayBundle\\Tests\\": "tests" } }, "authors": [ diff --git a/src/MortyCountsBundle/ComsaveMortyCountsBundle.php b/src/MortyCountsBundle/ComsaveMortyCountsBundle.php deleted file mode 100644 index 91401a0..0000000 --- a/src/MortyCountsBundle/ComsaveMortyCountsBundle.php +++ /dev/null @@ -1,9 +0,0 @@ -") + * @JMS\Type("array") */ private $results; diff --git a/src/MortyCountsBundle/Model/PrometheusResponseDataResult.php b/src/PrometheusPushGatewayBundle/Model/PrometheusResponseDataResult.php similarity index 93% rename from src/MortyCountsBundle/Model/PrometheusResponseDataResult.php rename to src/PrometheusPushGatewayBundle/Model/PrometheusResponseDataResult.php index 2c77722..e84e6f6 100644 --- a/src/MortyCountsBundle/Model/PrometheusResponseDataResult.php +++ b/src/PrometheusPushGatewayBundle/Model/PrometheusResponseDataResult.php @@ -1,6 +1,6 @@ password = $password; } - public function query(array $arguments): PrometheusResponse { $response = $this->httpClient->request( diff --git a/src/MortyCountsBundle/Services/PushGateway.php b/src/PrometheusPushGatewayBundle/Services/PushGateway.php similarity index 98% rename from src/MortyCountsBundle/Services/PushGateway.php rename to src/PrometheusPushGatewayBundle/Services/PushGateway.php index cdd5fff..f1ac02d 100644 --- a/src/MortyCountsBundle/Services/PushGateway.php +++ b/src/PrometheusPushGatewayBundle/Services/PushGateway.php @@ -1,6 +1,6 @@ registry = $registry; $this->registryStorageAdapter = $registryStorageAdapter; $this->pushGateway = $pushGateway; + $this->prometheusClient = $prometheusClient; $this->prometheusInstanceName = $prometheusInstanceName; } @@ -82,20 +88,33 @@ public function pushAll(array $prometheusJobNames): void /** * @throws MetricsRegistrationException */ - public function counter(string $namespace, string $name, ?string $help = null, array $labels = []): Counter + public function counter(string $namespace, string $name, ?string $help = null, array $labels = [], bool $fetchCurrent = false): Counter { try { $counter = $this->registry->getCounter($namespace, $name); } catch (MetricNotFoundException $ex) { - // todo: try to fetch from prometheus the initial value - $counter = $this->registry->registerCounter( $namespace, $name, $help, $labels ); + + if($fetchCurrent) { +// try { + $prometheusResponse = $this->prometheusClient->query( + [ + 'query' => sprintf('morty_%s_%s', $namespace, $name), + ] + ); + $existingValue = (int)$prometheusResponse->getData()->getResults()[0]->getValue(); + var_dump($existingValue); + $counter->incBy($existingValue); +// } catch (GuzzleException $ex) { +//// log a warning +// } + } } return $counter; @@ -128,6 +147,11 @@ public function histogram(string $namespace, string $name, ?string $help = null, ); } + public function getPrometheusClient(): PrometheusClient + { + return $this->prometheusClient; + } + /** * @throws StorageException */ diff --git a/tests/Integration/AbstractPrometheusPushGatewayTest.php b/tests/Integration/AbstractPrometheusPushGatewayTest.php index 2f7ac3f..d7b3a36 100644 --- a/tests/Integration/AbstractPrometheusPushGatewayTest.php +++ b/tests/Integration/AbstractPrometheusPushGatewayTest.php @@ -1,13 +1,13 @@ flush(); $counter = $pushGateway1->counter( @@ -71,7 +71,7 @@ public function testPushesCounterMetricAndIncreases(): void $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); // var_dump($metricFullName); - $pushGateway1 = static::buildPushGatewayClient('haproxy:9191'); + $pushGateway1 = static::buildPushGatewayClient('haproxy:9191', static::buildPrometheusClient('haproxy:9090')); $pushGateway1->flush(); $counter = $pushGateway1->counter( diff --git a/tests/Integration/PrometheusSingleNodePushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php index 71bd8b2..854c70a 100644 --- a/tests/Integration/PrometheusSingleNodePushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -1,9 +1,9 @@ prometheusClient = static::buildPrometheusClient('prometheus:9091'); - $this->pushGatewayClient = self::buildPushGatewayClient('pushgateway:9191'); + $this->prometheusClient = static::buildPrometheusClient('prometheus:9090'); + $this->pushGatewayClient = self::buildPushGatewayClient('pushgateway:9191', $this->prometheusClient); $this->pushGatewayClient->flush(); } @@ -119,4 +119,51 @@ public function testPushesCounterMetricAndIncreases(): void $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(6, $results[0]->getValue()); } + + /** + * @throws GuzzleException + * @throws MetricsRegistrationException + * @throws StorageException + */ + public function testPushesGetsExistingMetricFromPrometheusToIncrease(): void + { + $metricNamespace = 'test'; + $metricName = 'some_counter_3'; + $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); + + $counter = $this->pushGatewayClient->counter( + $metricNamespace, + $metricName, + 'it increases', + ['type'] + ); + $counter->incBy(5, ['blue']); + $this->pushGatewayClient->push($this->jobName); +// $this->pushGatewayClient->flush(); // <---- +// +// sleep(2); // wait for Prometheus to pull the metrics from PushGateway +// +// $counter = $this->pushGatewayClient->counter( +// $metricNamespace, +// $metricName, +// 'it increases', +// ['type'], +// true +// ); +// $counter->incBy(2, ['blue']); +// $this->pushGatewayClient->push($this->jobName); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway + + $results = $this->prometheusClient->query( + [ + 'query' => $metricFullName, + ] + )->getData()->getResults(); + + $this->assertCount(1, $results); + $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); + $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(7, $results[0]->getValue()); + } } \ No newline at end of file diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 9a26bff..6887c15 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -1,8 +1,8 @@ Date: Mon, 4 May 2020 13:48:26 +0200 Subject: [PATCH 73/83] rename extension --- ...ntsExtension.php => ComsavePrometheusPushGatewayExtension.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/PrometheusPushGatewayBundle/DependencyInjection/{ComsaveMortyCountsExtension.php => ComsavePrometheusPushGatewayExtension.php} (100%) diff --git a/src/PrometheusPushGatewayBundle/DependencyInjection/ComsaveMortyCountsExtension.php b/src/PrometheusPushGatewayBundle/DependencyInjection/ComsavePrometheusPushGatewayExtension.php similarity index 100% rename from src/PrometheusPushGatewayBundle/DependencyInjection/ComsaveMortyCountsExtension.php rename to src/PrometheusPushGatewayBundle/DependencyInjection/ComsavePrometheusPushGatewayExtension.php From 4cbe5e73bd0a93838e3a98a630a312e4a0e031a9 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Mon, 4 May 2020 14:17:10 +0200 Subject: [PATCH 74/83] update ConfigurationTest --- tests/.gitignore | 0 .../Unit/DependencyInjection/ConfigurationTest.php | 13 +++++-------- ...tionTest__testConfigurationNoCredentials__1.json | 3 ++- .../ConfigurationTest__testConfiguration__1.json | 5 ++++- 4 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 tests/.gitignore diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 6887c15..70d267e 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -18,10 +18,9 @@ public function testConfiguration(): void 'username' => 'admin', 'password' => 'duuude', 'instance' => 'moms_basement:6666', -// 'jobs' => [ -// 'intense_server', -// ], - // todo: fix jobs conf + 'jobs' => [ + 'intense_server', + ], ], 'pushgateway' => [ 'host' => 'pushgateway:9191', @@ -45,10 +44,8 @@ public function testConfigurationNoCredentials(): void 'prometheus' => [ 'host' => 'prometheus:9090', 'instance' => 'moms_basement:6666', -// 'jobs' => [ -// 'intense_server', -// ], - // todo: fix jobs conf + 'jobs' => [ + ], ], 'pushgateway' => [ 'host' => 'pushgateway:9191', diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json index e91a906..a72ff04 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json @@ -3,7 +3,8 @@ "host": "prometheus:9090", "instance": "moms_basement:6666", "username": null, - "password": null + "password": null, + "jobs": [] }, "pushgateway": { "host": "pushgateway:9191", diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json index 5088d12..bc35206 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json @@ -3,7 +3,10 @@ "host": "prometheus:9090", "username": "admin", "password": "duuude", - "instance": "moms_basement:6666" + "instance": "moms_basement:6666", + "jobs": [ + "intense_server" + ] }, "pushgateway": { "host": "pushgateway:9191", From 62aedb0e5c7ded63c7acd15f6f9ddb92dae27e1a Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 09:31:44 +0200 Subject: [PATCH 75/83] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f71be9..17cf95d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Send metrics to Prometheus. +High Availability Setup ## Requirements -1. `Redis` (the service & the PHP extension): to act as a buffer before push and avoid latency in the code +1. `Redis` (the service & the PHP extension): to act as a buffer before push and avoid latency in the code, and as a store for the current counter values. 2. `bin/console comsave:prometheus:push` cronjob: to push data periodically to Prometheus Pushgateway @@ -68,4 +68,4 @@ Tests `docker exec $(docker ps | grep _php | awk '{print $1}') vendor/bin/phpuni ## License -MIT \ No newline at end of file +MIT From f2ec78326dd9f1ce2c0fe8a3e134b421ed6dfe45 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 11:14:37 +0200 Subject: [PATCH 76/83] proper prom call for current val --- .../Resources/config/services.yml | 2 +- .../Services/PrometheusClient.php | 41 +++++++-- .../Services/PushGatewayClient.php | 34 ++----- .../PrometheusMultiNodeHaProxyPushTest.php | 18 +--- .../PrometheusSingleNodePushTest.php | 88 +++++++++---------- 5 files changed, 86 insertions(+), 97 deletions(-) diff --git a/src/PrometheusPushGatewayBundle/Resources/config/services.yml b/src/PrometheusPushGatewayBundle/Resources/config/services.yml index 15e4708..bcdbcfa 100644 --- a/src/PrometheusPushGatewayBundle/Resources/config/services.yml +++ b/src/PrometheusPushGatewayBundle/Resources/config/services.yml @@ -8,7 +8,7 @@ services: Comsave\PrometheusPushGatewayBundle\: resource: '../../*' - exclude: '../../{DependencyInjection,Exception,Model,Kernel.php}' + exclude: '../../{DependencyInjection,Event,Exception,Model,Kernel.php}' Prometheus\Storage\Redis: factory: ['Comsave\PrometheusPushGatewayBundle\Factory\RedisStorageAdapterFactory', 'build'] diff --git a/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php b/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php index e58e784..42b6b56 100644 --- a/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php +++ b/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php @@ -4,6 +4,7 @@ use Comsave\PrometheusPushGatewayBundle\Model\PrometheusResponse; use GuzzleHttp\ClientInterface; +use GuzzleHttp\Exception\ClientException; use JMS\Serializer\Serializer; // todo: move this out to a separate repo later @@ -46,17 +47,39 @@ public function __construct( $this->password = $password; } - public function query(array $arguments): PrometheusResponse + public function query(string $query): array { - $response = $this->httpClient->request( - 'POST', - sprintf('%s/api/v1/query', $this->prometheusUrl), - $this->buildRequestOptions([ - 'form_params' => $arguments, - ]) - ); + try { + $response = $this->httpClient->request( + 'POST', + sprintf('%s/api/v1/query', $this->prometheusUrl), + $this->buildRequestOptions( + [ + 'form_params' => [ + 'query' => $query, + ], +// 'content-type' => 'application/x-www-form-urlencoded', + // todo: include instance + ] + ) + ); + } + catch(ClientException $ex) { + // todo: + throw $ex; + } + + /** @var PrometheusResponse $response */ + $response = $this->jmsSerializer->deserialize((string)$response->getBody(), PrometheusResponse::class, 'json'); - return $this->jmsSerializer->deserialize((string)$response->getBody(), PrometheusResponse::class, 'json'); + return $response->getData()->getResults(); + } + + public function requireLabels(array $labels): string + { + return implode(',', array_map(function(string $label) { + return sprintf('%s=~".+"', $label); + }, $labels)); } private function buildRequestOptions(array $requestOptions): array diff --git a/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php b/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php index 4ce6640..b5a6112 100644 --- a/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php +++ b/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php @@ -90,34 +90,12 @@ public function pushAll(array $prometheusJobNames): void */ public function counter(string $namespace, string $name, ?string $help = null, array $labels = [], bool $fetchCurrent = false): Counter { - try { - $counter = $this->registry->getCounter($namespace, $name); - } - catch (MetricNotFoundException $ex) { - $counter = $this->registry->registerCounter( - $namespace, - $name, - $help, - $labels - ); - - if($fetchCurrent) { -// try { - $prometheusResponse = $this->prometheusClient->query( - [ - 'query' => sprintf('morty_%s_%s', $namespace, $name), - ] - ); - $existingValue = (int)$prometheusResponse->getData()->getResults()[0]->getValue(); - var_dump($existingValue); - $counter->incBy($existingValue); -// } catch (GuzzleException $ex) { -//// log a warning -// } - } - } - - return $counter; + return $this->registry->getOrRegisterCounter( + $namespace, + $name, + $help, + $labels + ); } /** diff --git a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php index 2aac9e5..11179ab 100644 --- a/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php +++ b/tests/Integration/PrometheusMultiNodeHaProxyPushTest.php @@ -45,11 +45,7 @@ public function testPushesOneCounterMetric(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway foreach($this->nodes as $node => $server) { - $response = static::buildPrometheusClient($server)->query([ - 'query' => $metricFullName, - ]); -// var_dump($response); - $results = $response->getData()->getResults(); + $results = static::buildPrometheusClient($server)->query($metricFullName); $this->assertCount(1, $results, sprintf('Node %s results invalid.', $node)); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -86,11 +82,7 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway foreach($this->nodes as $node => $server) { - $response = static::buildPrometheusClient($server)->query([ - 'query' => $metricFullName, - ]); -// var_dump($response); - $results = $response->getData()->getResults(); + $results = static::buildPrometheusClient($server)->query($metricFullName); $this->assertCount(1, $results, sprintf('Node %s results invalid.', $node)); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -108,11 +100,7 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway foreach($this->nodes as $node => $server) { - $response = static::buildPrometheusClient($server)->query([ - 'query' => $metricFullName, - ]); -// var_dump($response); - $results = $response->getData()->getResults(); + $results = static::buildPrometheusClient($server)->query($metricFullName); $this->assertCount(1, $results, sprintf('Node %s results invalid.', $node)); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); diff --git a/tests/Integration/PrometheusSingleNodePushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php index 854c70a..9b396b5 100644 --- a/tests/Integration/PrometheusSingleNodePushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -49,13 +49,7 @@ public function testPushesOneCounterMetric(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); + $results = $this->prometheusClient->query($metricFullName); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -86,13 +80,7 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $response = $this->prometheusClient->query( - [ - 'query' => $metricFullName, - ] - ); -// var_dump($response); - $results = $response->getData()->getResults(); + $results = $this->prometheusClient->query($metricFullName); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -108,11 +96,7 @@ public function testPushesCounterMetricAndIncreases(): void sleep(2); // wait for Prometheus to pull the metrics from PushGateway - $results = $this->prometheusClient->query( - [ - 'query' => $metricFullName, - ] - )->getData()->getResults(); + $results = $this->prometheusClient->query($metricFullName); $this->assertCount(1, $results); $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); @@ -128,42 +112,58 @@ public function testPushesCounterMetricAndIncreases(): void public function testPushesGetsExistingMetricFromPrometheusToIncrease(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_3'; + $metricName = 'some_counter_3_x'; +// $metricName = 'some_counter_3_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); - $counter = $this->pushGatewayClient->counter( - $metricNamespace, - $metricName, - 'it increases', - ['type'] - ); - $counter->incBy(5, ['blue']); - $this->pushGatewayClient->push($this->jobName); -// $this->pushGatewayClient->flush(); // <---- -// -// sleep(2); // wait for Prometheus to pull the metrics from PushGateway -// + $labels = ['order_id', 'user_id']; // $counter = $this->pushGatewayClient->counter( // $metricNamespace, // $metricName, // 'it increases', -// ['type'], -// true +// $labels // ); -// $counter->incBy(2, ['blue']); +// $counter->inc([md5(mt_rand()), 'user_id_1']); +// $counter->inc([md5(mt_rand()), 'user_id_2']); +// $counter->inc([md5(mt_rand()), 'user_id_2']); // $this->pushGatewayClient->push($this->jobName); - - sleep(2); // wait for Prometheus to pull the metrics from PushGateway +// $counter->inc([md5(mt_rand()), 'user_id_2']); +// $this->pushGatewayClient->push($this->jobName); +//// $this->pushGatewayClient->flush(); +// +// sleep(2); // wait for Prometheus to pull the metrics from PushGateway $results = $this->prometheusClient->query( - [ - 'query' => $metricFullName, - ] - )->getData()->getResults(); + sprintf('sum(%s{%s})', $metricFullName, $this->prometheusClient->requireLabels($labels)), + ); + var_dump($results); $this->assertCount(1, $results); - $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); - $this->assertEquals('blue', $results[0]->getMetric()['type']); - $this->assertEquals(7, $results[0]->getValue()); +// $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); +// $this->assertEquals('blue', $results[0]->getMetric()['type']); + $this->assertEquals(4, $results[0]->getValue()); + +// $counter2 = $this->pushGatewayClient->counter( +// $metricNamespace, +// $metricName, +// 'it increases', +// ['type'], +// true +// ); +// $counter2->incBy(2, ['blue']); +// $this->pushGatewayClient->push($this->jobName); +// +// sleep(2); // wait for Prometheus to pull the metrics frwom PushGateway +// +// $results = $this->prometheusClient->query( +// [ +// 'query' => $metricFullName, +// ] +// ); +// +// $this->assertCount(1, $results); +// $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); +// $this->assertEquals('blue', $results[0]->getMetric()['type']); +// $this->assertEquals(7, $results[0]->getValue()); } } \ No newline at end of file From de21556e8953aa5969581df2945a2417e253441c Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 12:23:06 +0200 Subject: [PATCH 77/83] update configuration --- README.md | 11 ++++-- .../DependencyInjection/Configuration.php | 23 +++++++++-- .../DependencyInjection/ConfigurationTest.php | 39 +++++++++++++++++-- ...st__testConfigurationNoCredentials__1.json | 2 +- ...Test__testConfigurationWithMetrics__1.json | 25 ++++++++++++ ...nfigurationTest__testConfiguration__1.json | 4 +- 6 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json diff --git a/README.md b/README.md index 17cf95d..5c09340 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,14 @@ comsave_prometheus_pushgateway: username: 'admin' # optional password: 'duuude' # optional instance: 'moms_basement:6666' # your server host/name/etc - jobs: - - 'metric_job_name' - - 'metric_job_name2' + metrics: + api: # metric namespace + - name: 'orders' + type: 'counter' + prefetch: true # prefetch current value from prometheus if missing in redis buffer; true by default + labels: + - 'order_id' + - 'user_id' pushgateway: host: 'pushgateway:9191' username: 'admin2' # optional diff --git a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php index 0c8186d..187948b 100644 --- a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php +++ b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php @@ -33,9 +33,26 @@ public function getConfigTreeBuilder() ->defaultValue('localhost') ->isRequired() ->end() - ->arrayNode('jobs') - ->useAttributeAsKey('key', false) - ->prototype('scalar')->end() + ->arrayNode('metrics') + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('type') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->booleanNode('prefetch') + ->defaultValue(true) + ->end() + ->arrayNode('labels') + ->useAttributeAsKey('key', false) + ->prototype('scalar')->end() + ->end() + ->end() + ->end() ->end() ->end() ->end() diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 70d267e..cbba8b7 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -18,9 +18,6 @@ public function testConfiguration(): void 'username' => 'admin', 'password' => 'duuude', 'instance' => 'moms_basement:6666', - 'jobs' => [ - 'intense_server', - ], ], 'pushgateway' => [ 'host' => 'pushgateway:9191', @@ -44,11 +41,45 @@ public function testConfigurationNoCredentials(): void 'prometheus' => [ 'host' => 'prometheus:9090', 'instance' => 'moms_basement:6666', - 'jobs' => [ + ], + 'pushgateway' => [ + 'host' => 'pushgateway:9191', + 'redis' => 'redis:6379', + ], + ]; + + $configuration = new Configuration(); + + $configNode = $configuration->getConfigTreeBuilder()->buildTree(); + $resultConfig = $configNode->finalize($configNode->normalize($inputOutput)); + + $this->assertMatchesJsonSnapshot($resultConfig); + } + + public function testConfigurationWithMetrics(): void + { + $inputOutput = [ + 'prometheus' => [ + 'host' => 'prometheus:9090', + 'username' => 'admin', + 'password' => 'duuude', + 'instance' => 'moms_basement:6666', + 'metrics' => [ + 'api' => [ + 'name' => 'orders', + 'type' => 'counter', + 'prefetch' => true, + 'labels' => [ + 'order_id', + 'user_id', + ], + ], ], ], 'pushgateway' => [ 'host' => 'pushgateway:9191', + 'username' => 'admin2', + 'password' => 'duuude2', 'redis' => 'redis:6379', ], ]; diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json index a72ff04..da24cfa 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json @@ -4,7 +4,7 @@ "instance": "moms_basement:6666", "username": null, "password": null, - "jobs": [] + "metrics": [] }, "pushgateway": { "host": "pushgateway:9191", diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json new file mode 100644 index 0000000..ac3bbf1 --- /dev/null +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json @@ -0,0 +1,25 @@ +{ + "prometheus": { + "host": "prometheus:9090", + "username": "admin", + "password": "duuude", + "instance": "moms_basement:6666", + "metrics": { + "api": { + "name": "orders", + "type": "counter", + "prefetch": true, + "labels": [ + "order_id", + "user_id" + ] + } + } + }, + "pushgateway": { + "host": "pushgateway:9191", + "username": "admin2", + "password": "duuude2", + "redis": "redis:6379" + } +} diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json index bc35206..8260d00 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json @@ -4,9 +4,7 @@ "username": "admin", "password": "duuude", "instance": "moms_basement:6666", - "jobs": [ - "intense_server" - ] + "metrics": [] }, "pushgateway": { "host": "pushgateway:9191", From dd94c48dfc6a55667065baaf074c2a8672526f03 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 12:23:46 +0200 Subject: [PATCH 78/83] update configuration --- .../DependencyInjection/Configuration.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php index 187948b..315b703 100644 --- a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php +++ b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php @@ -48,7 +48,6 @@ public function getConfigTreeBuilder() ->defaultValue(true) ->end() ->arrayNode('labels') - ->useAttributeAsKey('key', false) ->prototype('scalar')->end() ->end() ->end() From 53840efed74de6bcbac3147f92693c92fc73af90 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 12:26:10 +0200 Subject: [PATCH 79/83] update configuration --- README.md | 16 ++++---- .../DependencyInjection/Configuration.php | 40 +++++++++---------- .../DependencyInjection/ConfigurationTest.php | 22 +++++----- ...st__testConfigurationNoCredentials__1.json | 6 +-- ...Test__testConfigurationWithMetrics__1.json | 24 +++++------ ...nfigurationTest__testConfiguration__1.json | 6 +-- 6 files changed, 57 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 5c09340..411b3fc 100644 --- a/README.md +++ b/README.md @@ -21,19 +21,19 @@ comsave_prometheus_pushgateway: username: 'admin' # optional password: 'duuude' # optional instance: 'moms_basement:6666' # your server host/name/etc - metrics: - api: # metric namespace - - name: 'orders' - type: 'counter' - prefetch: true # prefetch current value from prometheus if missing in redis buffer; true by default - labels: - - 'order_id' - - 'user_id' pushgateway: host: 'pushgateway:9191' username: 'admin2' # optional password: 'duuude2' # optional redis: 'redis:6379' + metrics: + api: # metric namespace + - name: 'orders' + type: 'counter' + prefetch: true # prefetch current value from prometheus if missing in redis buffer; true by default + labels: + - 'order_id' + - 'user_id' ``` Add the bundle to your Symfony kernel. diff --git a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php index 315b703..9fb891f 100644 --- a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php +++ b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php @@ -33,26 +33,6 @@ public function getConfigTreeBuilder() ->defaultValue('localhost') ->isRequired() ->end() - ->arrayNode('metrics') - ->prototype('array') - ->children() - ->scalarNode('name') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->scalarNode('type') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->booleanNode('prefetch') - ->defaultValue(true) - ->end() - ->arrayNode('labels') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() ->end() ->end() ->arrayNode('pushgateway') @@ -74,6 +54,26 @@ public function getConfigTreeBuilder() ->end() ->end() ->end() + ->arrayNode('metrics') + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('type') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->booleanNode('prefetch') + ->defaultValue(true) + ->end() + ->arrayNode('labels') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() ->end(); return $treeBuilder; diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index cbba8b7..119f5f0 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -64,17 +64,6 @@ public function testConfigurationWithMetrics(): void 'username' => 'admin', 'password' => 'duuude', 'instance' => 'moms_basement:6666', - 'metrics' => [ - 'api' => [ - 'name' => 'orders', - 'type' => 'counter', - 'prefetch' => true, - 'labels' => [ - 'order_id', - 'user_id', - ], - ], - ], ], 'pushgateway' => [ 'host' => 'pushgateway:9191', @@ -82,6 +71,17 @@ public function testConfigurationWithMetrics(): void 'password' => 'duuude2', 'redis' => 'redis:6379', ], + 'metrics' => [ + 'api' => [ + 'name' => 'orders', + 'type' => 'counter', + 'prefetch' => true, + 'labels' => [ + 'order_id', + 'user_id', + ], + ], + ], ]; $configuration = new Configuration(); diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json index da24cfa..4a8288d 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationNoCredentials__1.json @@ -3,13 +3,13 @@ "host": "prometheus:9090", "instance": "moms_basement:6666", "username": null, - "password": null, - "metrics": [] + "password": null }, "pushgateway": { "host": "pushgateway:9191", "redis": "redis:6379", "username": null, "password": null - } + }, + "metrics": [] } diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json index ac3bbf1..1c6340b 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json @@ -3,23 +3,23 @@ "host": "prometheus:9090", "username": "admin", "password": "duuude", - "instance": "moms_basement:6666", - "metrics": { - "api": { - "name": "orders", - "type": "counter", - "prefetch": true, - "labels": [ - "order_id", - "user_id" - ] - } - } + "instance": "moms_basement:6666" }, "pushgateway": { "host": "pushgateway:9191", "username": "admin2", "password": "duuude2", "redis": "redis:6379" + }, + "metrics": { + "api": { + "name": "orders", + "type": "counter", + "prefetch": true, + "labels": [ + "order_id", + "user_id" + ] + } } } diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json index 8260d00..9c767fd 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfiguration__1.json @@ -3,13 +3,13 @@ "host": "prometheus:9090", "username": "admin", "password": "duuude", - "instance": "moms_basement:6666", - "metrics": [] + "instance": "moms_basement:6666" }, "pushgateway": { "host": "pushgateway:9191", "username": "admin2", "password": "duuude2", "redis": "redis:6379" - } + }, + "metrics": [] } From 6ba4392ae5769f74f8e8650b7c1538cd316ed802 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 12:44:43 +0200 Subject: [PATCH 80/83] update prometheus client dep --- composer.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 2265d22..e429947 100644 --- a/composer.json +++ b/composer.json @@ -4,12 +4,12 @@ "license": "MIT", "require": { "php": ">=7.3", - "endclothing/prometheus_client_php": "^1.0", - "symfony/http-kernel": "^3.4|^4.4", - "symfony/console": "^3.4|^4.4", - "jms/serializer": "^3.0|^2.0", "comsave/dependency-injection-config-to-parameters": "^0.1.0", - "symfony/config": "^3.4|^4.4" + "comsave/prometheus_client_php": "^1.0.3", + "jms/serializer": "^3.0|^2.0", + "symfony/config": "^3.4|^4.4", + "symfony/console": "^3.4|^4.4", + "symfony/http-kernel": "^3.4|^4.4" }, "require-dev": { "phpunit/phpunit": "^8.0", @@ -30,5 +30,8 @@ "name": "Vaidas Bagdonas", "email": "vaidas.bagdonas@comsave.com" } - ] + ], + "config": { + "sort-packages": true + } } From 514e112b3d0fa4cfbf0d8da291ca53b2cb36f118 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Tue, 5 May 2020 12:54:42 +0200 Subject: [PATCH 81/83] init collector registry override; add pre register event for a counter --- .../Event/CounterMetricEvent.php | 28 ++++++++++++++ .../EventSubscriber/MetricEventSubscriber.php | 21 ++++++++++ .../Prometheus/CollectorRegistry.php | 38 +++++++++++++++++++ .../Prometheus/Counter.php | 7 ++++ .../Resources/config/services.yml | 4 +- 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/PrometheusPushGatewayBundle/Event/CounterMetricEvent.php create mode 100644 src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php create mode 100644 src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php create mode 100644 src/PrometheusPushGatewayBundle/Prometheus/Counter.php diff --git a/src/PrometheusPushGatewayBundle/Event/CounterMetricEvent.php b/src/PrometheusPushGatewayBundle/Event/CounterMetricEvent.php new file mode 100644 index 0000000..b7f74fd --- /dev/null +++ b/src/PrometheusPushGatewayBundle/Event/CounterMetricEvent.php @@ -0,0 +1,28 @@ +counter = $counter; + } + + public function getCounter(): Counter + { + return $this->counter; + } +} \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php b/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php new file mode 100644 index 0000000..3865b15 --- /dev/null +++ b/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php @@ -0,0 +1,21 @@ + 'onCounterBeforeRegister', + ]; + } + + public function onCounterBeforeRegister(CounterMetricEvent $event): void + { + + } +} \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php b/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php new file mode 100644 index 0000000..e6d2d06 --- /dev/null +++ b/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php @@ -0,0 +1,38 @@ +eventDispatcher = $eventDispatcher; + } + + public function registerCounter($namespace, $name, $help, $labels = []): Counter + { + $counter = parent::registerCounter($namespace, $name, $help, $labels); + + // todo should prefetch? + if(true) { + $this->eventDispatcher->dispatch(new CounterMetricEvent($counter)); + } + + return $counter; + } +} \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/Prometheus/Counter.php b/src/PrometheusPushGatewayBundle/Prometheus/Counter.php new file mode 100644 index 0000000..d193f4a --- /dev/null +++ b/src/PrometheusPushGatewayBundle/Prometheus/Counter.php @@ -0,0 +1,7 @@ + Date: Tue, 5 May 2020 15:45:12 +0200 Subject: [PATCH 82/83] add current value fetching --- README.md | 3 +- composer.json | 2 +- .../ComsavePrometheusPushGatewayExtension.php | 47 +++++++++++- .../DependencyInjection/Configuration.php | 8 +- .../EventSubscriber/MetricEventSubscriber.php | 25 ++++++ .../Model/PrometheusResponseData.php | 6 ++ .../Prometheus/CollectorRegistry.php | 39 ++++++++-- .../Prometheus/Counter.php | 27 +++++++ .../Services/PrometheusClient.php | 6 ++ .../Services/PushGatewayClient.php | 9 +-- .../AbstractPrometheusPushGatewayTest.php | 9 ++- .../PrometheusSingleNodePushTest.php | 76 +++++++++---------- .../DependencyInjection/ConfigurationTest.php | 3 +- ...Test__testConfigurationWithMetrics__1.json | 3 +- 14 files changed, 199 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 411b3fc..9187233 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ comsave_prometheus_pushgateway: api: # metric namespace - name: 'orders' type: 'counter' - prefetch: true # prefetch current value from prometheus if missing in redis buffer; true by default + help: 'counts the number of orders' + prefetch_group_label: 'user_id' # optional & only available for the counter; prefetch current value from prometheus by grouping sum() query by this label and populate the counter if it's missing in redis cache labels: - 'order_id' - 'user_id' diff --git a/composer.json b/composer.json index e429947..f80562b 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "require": { "php": ">=7.3", "comsave/dependency-injection-config-to-parameters": "^0.1.0", - "comsave/prometheus_client_php": "^1.0.3", + "comsave/prometheus_client_php": "^1.0.5", "jms/serializer": "^3.0|^2.0", "symfony/config": "^3.4|^4.4", "symfony/console": "^3.4|^4.4", diff --git a/src/PrometheusPushGatewayBundle/DependencyInjection/ComsavePrometheusPushGatewayExtension.php b/src/PrometheusPushGatewayBundle/DependencyInjection/ComsavePrometheusPushGatewayExtension.php index 585126e..0657bdc 100644 --- a/src/PrometheusPushGatewayBundle/DependencyInjection/ComsavePrometheusPushGatewayExtension.php +++ b/src/PrometheusPushGatewayBundle/DependencyInjection/ComsavePrometheusPushGatewayExtension.php @@ -2,11 +2,13 @@ namespace Comsave\PrometheusPushGatewayBundle\DependencyInjection; +use Comsave\PrometheusPushGatewayBundle\Model\CounterPrefetchQuery; +use Comsave\PrometheusPushGatewayBundle\Prometheus\CollectorRegistry; use Comsave\Tools\DependencyInjectionConfigsToParams; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader; -use Symfony\Component\Config\FileLocator; class ComsavePrometheusPushGatewayExtension extends Extension { @@ -22,5 +24,48 @@ public function load(array $configs, ContainerBuilder $containerBuilder) $loader = new Loader\YamlFileLoader($containerBuilder, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); + + $this->registerMetrics($processedConfigs['metrics'], $containerBuilder); + } + + // todo: test this + public function registerMetrics(array $metricsConfig, ContainerBuilder $containerBuilder): void + { + /** @var CollectorRegistry $collectorRegistry */ + $collectorRegistry = $containerBuilder->get(CollectorRegistry::class); + + foreach ($metricsConfig as $namespace => $metricConfig) { + switch ($metricConfig['type']) { + case 'counter': + if($metricConfig['prefetch_query']) { + $collectorRegistry->addCounterPrefetchGroupLabel( + new CounterPrefetchQuery( + $namespace, + $metricConfig['name'], + $metricConfig['prefetch_query'] + ) + ); + } + + $collectorRegistry->registerCounter( + $namespace, + $metricConfig['name'], + $metricConfig['help'], + $metricConfig['labels'] + ); + break; + case 'gauge': + $collectorRegistry->registerGauge( + $namespace, + $metricConfig['name'], + $metricConfig['help'], + $metricConfig['labels'] + ); + break; + case 'histogram': // todo: add histogram + default: + break; + } + } } } \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php index 9fb891f..1cc8444 100644 --- a/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php +++ b/src/PrometheusPushGatewayBundle/DependencyInjection/Configuration.php @@ -65,8 +65,12 @@ public function getConfigTreeBuilder() ->isRequired() ->cannotBeEmpty() ->end() - ->booleanNode('prefetch') - ->defaultValue(true) + ->scalarNode('help') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('prefetch_group_label') + ->defaultNull() ->end() ->arrayNode('labels') ->prototype('scalar')->end() diff --git a/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php b/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php index 3865b15..77c00cd 100644 --- a/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php +++ b/src/PrometheusPushGatewayBundle/EventSubscriber/MetricEventSubscriber.php @@ -3,10 +3,23 @@ namespace Comsave\PrometheusPushGatewayBundle\EventSubscriber; use Comsave\PrometheusPushGatewayBundle\Event\CounterMetricEvent; +use Comsave\PrometheusPushGatewayBundle\Services\PrometheusClient; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class MetricEventSubscriber implements EventSubscriberInterface { + /** @var PrometheusClient */ + private $prometheusClient; + + /** + * @param PrometheusClient $prometheusClient + * @codeCoverageIgnore + */ + public function __construct(PrometheusClient $prometheusClient) + { + $this->prometheusClient = $prometheusClient; + } + public static function getSubscribedEvents(): array { return [ @@ -16,6 +29,18 @@ public static function getSubscribedEvents(): array public function onCounterBeforeRegister(CounterMetricEvent $event): void { + $counter = $event->getCounter(); + + if($counter->getPrefetchGroupLabel()) { + $results = $this->prometheusClient->query(vsprintf('sum(%s{%s}) by (%s)', [ + sprintf('%s_%s', $counter->getLabelNames()['namespace'], $counter->getName()), + $this->prometheusClient->requireLabels($counter->getLabelNames()), + $counter->getPrefetchGroupLabel() + ])); + if(count($results) > 0) { + $counter->setCurrentCount($results[0]->getValue()); + } + } } } \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/Model/PrometheusResponseData.php b/src/PrometheusPushGatewayBundle/Model/PrometheusResponseData.php index b8d8a20..d2751a1 100644 --- a/src/PrometheusPushGatewayBundle/Model/PrometheusResponseData.php +++ b/src/PrometheusPushGatewayBundle/Model/PrometheusResponseData.php @@ -29,11 +29,17 @@ public function setResultType(string $resultType): void $this->resultType = $resultType; } + /** + * @return array|PrometheusResponseDataResult[] + */ public function getResults(): array { return $this->results; } + /** + * @param array|PrometheusResponseDataResult[] $results + */ public function setResults(array $results): void { $this->results = $results; diff --git a/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php b/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php index e6d2d06..d0e5ef9 100644 --- a/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php +++ b/src/PrometheusPushGatewayBundle/Prometheus/CollectorRegistry.php @@ -3,18 +3,23 @@ namespace Comsave\PrometheusPushGatewayBundle\Prometheus; use Comsave\PrometheusPushGatewayBundle\Event\CounterMetricEvent; -use Prometheus\Counter; +use Comsave\PrometheusPushGatewayBundle\Model\CounterPrefetchQuery; +use Prometheus\Interfaces\CounterInterface; use Prometheus\Storage\Adapter; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class CollectorRegistry extends \Prometheus\CollectorRegistry { /** @var EventDispatcherInterface */ private $eventDispatcher; - protected static $classCounter = \Comsave\PrometheusPushGatewayBundle\Prometheus\Counter::class; + /** @var array */ + private $counterPrefetchGroupLabels; + + protected static $classCounter = Counter::class; /** + * @param Adapter $storageAdapter * @param EventDispatcherInterface $eventDispatcher * @codeCoverageIgnore */ @@ -24,15 +29,33 @@ public function __construct(Adapter $storageAdapter, EventDispatcherInterface $e $this->eventDispatcher = $eventDispatcher; } - public function registerCounter($namespace, $name, $help, $labels = []): Counter + public function registerCounter($namespace, $name, $help, $labels = []): CounterInterface { + /** @var Counter $counter */ $counter = parent::registerCounter($namespace, $name, $help, $labels); - // todo should prefetch? - if(true) { - $this->eventDispatcher->dispatch(new CounterMetricEvent($counter)); - } + $counter->setPrefetchGroupLabel($this->getCounterPrefetchGroupLabel($namespace, $name))); + + $this->eventDispatcher->dispatch(new CounterMetricEvent($counter), CounterMetricEvent::BEFORE_REGISTER); return $counter; } + + public function getCounterPrefetchGroupLabel(string $namespace, string $name): ?string + { + if(isset($this->counterPrefetchGroupLabels[$namespace]) && isset($this->counterPrefetchGroupLabels[$namespace][$name])) { + return $this->counterPrefetchGroupLabels[$namespace][$name]; + } + + return null; + } + + public function addCounterPrefetchGroupLabel(string $namespace, string $name, string $prefetchGroupLabel): void + { + if(!isset($this->counterPrefetchGroupLabels[$namespace])) { + $this->counterPrefetchGroupLabels[$namespace] = []; + } + + $this->counterPrefetchGroupLabels[$namespace][$name] = $prefetchGroupLabel; + } } \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/Prometheus/Counter.php b/src/PrometheusPushGatewayBundle/Prometheus/Counter.php index d193f4a..99bd5a3 100644 --- a/src/PrometheusPushGatewayBundle/Prometheus/Counter.php +++ b/src/PrometheusPushGatewayBundle/Prometheus/Counter.php @@ -4,4 +4,31 @@ class Counter extends \Prometheus\Counter { + /** @var string|null */ + private $prefetchGroupLabel; + + /** @var int */ + private $currentCount = 0; + + public function setPrefetchGroupLabel(?string $prefetchGroupLabel): void + { + $this->prefetchGroupLabel = $prefetchGroupLabel; + } + + public function getPrefetchGroupLabel(): ?string + { + return $this->prefetchGroupLabel; + } + + public function incBy($count, array $labels = []): void + { + $this->currentCount += $count; + + parent::incBy($this->currentCount, $labels); + } + + public function setCurrentCount(int $currentCount): void + { + $this->currentCount = $currentCount; + } } \ No newline at end of file diff --git a/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php b/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php index 42b6b56..6978267 100644 --- a/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php +++ b/src/PrometheusPushGatewayBundle/Services/PrometheusClient.php @@ -3,6 +3,7 @@ namespace Comsave\PrometheusPushGatewayBundle\Services; use Comsave\PrometheusPushGatewayBundle\Model\PrometheusResponse; +use Comsave\PrometheusPushGatewayBundle\Model\PrometheusResponseDataResult; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\ClientException; use JMS\Serializer\Serializer; @@ -47,6 +48,11 @@ public function __construct( $this->password = $password; } + /** + * @param string $query + * @return array|PrometheusResponseDataResult[] + * @throws \GuzzleHttp\Exception\GuzzleException + */ public function query(string $query): array { try { diff --git a/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php b/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php index b5a6112..3338b9d 100644 --- a/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php +++ b/src/PrometheusPushGatewayBundle/Services/PushGatewayClient.php @@ -4,12 +4,11 @@ use GuzzleHttp\Exception\GuzzleException; use Prometheus\CollectorRegistry; -use Prometheus\Counter; -use Prometheus\Exception\MetricNotFoundException; use Prometheus\Exception\MetricsRegistrationException; use Prometheus\Exception\StorageException; -use Prometheus\Gauge; use Prometheus\Histogram; +use Prometheus\Interfaces\CounterInterface; +use Prometheus\Interfaces\GaugeInterface; use Prometheus\Storage\Redis; class PushGatewayClient @@ -88,7 +87,7 @@ public function pushAll(array $prometheusJobNames): void /** * @throws MetricsRegistrationException */ - public function counter(string $namespace, string $name, ?string $help = null, array $labels = [], bool $fetchCurrent = false): Counter + public function counter(string $namespace, string $name, ?string $help = null, array $labels = [], bool $fetchCurrent = false): CounterInterface { return $this->registry->getOrRegisterCounter( $namespace, @@ -101,7 +100,7 @@ public function counter(string $namespace, string $name, ?string $help = null, a /** * @throws MetricsRegistrationException */ - public function gauge(string $namespace, string $name, ?string $help = null, array $labels = []): Gauge + public function gauge(string $namespace, string $name, ?string $help = null, array $labels = []): GaugeInterface { return $this->registry->getOrRegisterGauge( $namespace, diff --git a/tests/Integration/AbstractPrometheusPushGatewayTest.php b/tests/Integration/AbstractPrometheusPushGatewayTest.php index d7b3a36..5672ff9 100644 --- a/tests/Integration/AbstractPrometheusPushGatewayTest.php +++ b/tests/Integration/AbstractPrometheusPushGatewayTest.php @@ -2,14 +2,16 @@ namespace Comsave\PrometheusPushGatewayBundle\Tests\Integration; +use Comsave\PrometheusPushGatewayBundle\EventSubscriber\MetricEventSubscriber; use Comsave\PrometheusPushGatewayBundle\Factory\HttpClientFactory; use Comsave\PrometheusPushGatewayBundle\Factory\JmsSerializerFactory; use Comsave\PrometheusPushGatewayBundle\Factory\RedisStorageAdapterFactory; +use Comsave\PrometheusPushGatewayBundle\Prometheus\CollectorRegistry; use Comsave\PrometheusPushGatewayBundle\Services\PrometheusClient; use Comsave\PrometheusPushGatewayBundle\Services\PushGateway; use Comsave\PrometheusPushGatewayBundle\Services\PushGatewayClient; use PHPUnit\Framework\TestCase; -use Prometheus\CollectorRegistry; +use Symfony\Component\EventDispatcher\EventDispatcher; abstract class AbstractPrometheusPushGatewayTest extends TestCase { @@ -24,8 +26,11 @@ public static function buildPrometheusClient(string $prometheusUrl): PrometheusC public static function buildPushGatewayClient(string $pushGatewayUrl, PrometheusClient $prometheusClient): PushGatewayClient { + $eventDispatcher = new EventDispatcher(); + $eventDispatcher->addSubscriber(new MetricEventSubscriber()); + $registryStorageAdapter = RedisStorageAdapterFactory::build('redis:6379'); - $registry = new CollectorRegistry($registryStorageAdapter); + $registry = new CollectorRegistry($registryStorageAdapter, $eventDispatcher); return new PushGatewayClient( $registry, diff --git a/tests/Integration/PrometheusSingleNodePushTest.php b/tests/Integration/PrometheusSingleNodePushTest.php index 9b396b5..82e301e 100644 --- a/tests/Integration/PrometheusSingleNodePushTest.php +++ b/tests/Integration/PrometheusSingleNodePushTest.php @@ -112,58 +112,50 @@ public function testPushesCounterMetricAndIncreases(): void public function testPushesGetsExistingMetricFromPrometheusToIncrease(): void { $metricNamespace = 'test'; - $metricName = 'some_counter_3_x'; -// $metricName = 'some_counter_3_'.date('YmdHis'); + $metricName = 'some_counter_3_'.date('YmdHis'); $metricFullName = sprintf('%s_%s', $metricNamespace, $metricName); $labels = ['order_id', 'user_id']; -// $counter = $this->pushGatewayClient->counter( -// $metricNamespace, -// $metricName, -// 'it increases', -// $labels -// ); -// $counter->inc([md5(mt_rand()), 'user_id_1']); -// $counter->inc([md5(mt_rand()), 'user_id_2']); -// $counter->inc([md5(mt_rand()), 'user_id_2']); -// $this->pushGatewayClient->push($this->jobName); -// $counter->inc([md5(mt_rand()), 'user_id_2']); -// $this->pushGatewayClient->push($this->jobName); -//// $this->pushGatewayClient->flush(); -// -// sleep(2); // wait for Prometheus to pull the metrics from PushGateway + $counter = $this->pushGatewayClient->counter( + $metricNamespace, + $metricName, + 'it increases', + $labels + ); + $counter->inc([md5(mt_rand()), 'user_id_1']); + $counter->inc([md5(mt_rand()), 'user_id_2']); + $counter->inc([md5(mt_rand()), 'user_id_2']); + $this->pushGatewayClient->push($this->jobName); + $this->pushGatewayClient->flush(); + + sleep(2); // wait for Prometheus to pull the metrics from PushGateway $results = $this->prometheusClient->query( sprintf('sum(%s{%s})', $metricFullName, $this->prometheusClient->requireLabels($labels)), ); + var_dump($results); + $this->assertCount(1, $results); + $this->assertEquals(3, $results[0]->getValue()); + + $counter = $this->pushGatewayClient->counter( + $metricNamespace, + $metricName, + 'it increases', + $labels, + true + ); + $counter->inc([md5(mt_rand()), 'user_id_2']); + $this->pushGatewayClient->push($this->jobName); + + sleep(2); // wait for Prometheus to pull the metrics frwom PushGateway + + $results = $this->prometheusClient->query( + sprintf('sum(%s{%s})', $metricFullName, $this->prometheusClient->requireLabels($labels)), + ); var_dump($results); + $this->assertCount(1, $results); -// $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); -// $this->assertEquals('blue', $results[0]->getMetric()['type']); $this->assertEquals(4, $results[0]->getValue()); - -// $counter2 = $this->pushGatewayClient->counter( -// $metricNamespace, -// $metricName, -// 'it increases', -// ['type'], -// true -// ); -// $counter2->incBy(2, ['blue']); -// $this->pushGatewayClient->push($this->jobName); -// -// sleep(2); // wait for Prometheus to pull the metrics frwom PushGateway -// -// $results = $this->prometheusClient->query( -// [ -// 'query' => $metricFullName, -// ] -// ); -// -// $this->assertCount(1, $results); -// $this->assertEquals($metricFullName, $results[0]->getMetric()['__name__']); -// $this->assertEquals('blue', $results[0]->getMetric()['type']); -// $this->assertEquals(7, $results[0]->getValue()); } } \ No newline at end of file diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 119f5f0..a37df67 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -75,7 +75,8 @@ public function testConfigurationWithMetrics(): void 'api' => [ 'name' => 'orders', 'type' => 'counter', - 'prefetch' => true, + 'help' => 'counts number of orders', + 'prefetch_group_label' => 'user_id', 'labels' => [ 'order_id', 'user_id', diff --git a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json index 1c6340b..e137ae9 100644 --- a/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json +++ b/tests/Unit/DependencyInjection/__snapshots__/ConfigurationTest__testConfigurationWithMetrics__1.json @@ -15,7 +15,8 @@ "api": { "name": "orders", "type": "counter", - "prefetch": true, + "help": "counts number of orders", + "prefetch_group_label": "user_id", "labels": [ "order_id", "user_id" From 2b1b8fdb7fa3ed12a0a39cf5572308544d2da535 Mon Sep 17 00:00:00 2001 From: Vaidas Bagdonas Date: Wed, 6 May 2020 11:11:42 +0200 Subject: [PATCH 83/83] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9187233..2336eaf 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,10 @@ new Comsave\PrometheusPushGatewayBundle\ComsavePrometheusPushGatewayBundle(), ## How does it work? +### General Prometheus architecture overview + +![](https://camo.githubusercontent.com/78b3b29d22cea8eee673e34fd204818ea532c171/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f70726f6d6574686575732f70726f6d65746865757340633334323537643036396336333036383564613335626365663038343633326666643564363230392f646f63756d656e746174696f6e2f696d616765732f6172636869746563747572652e737667) + ### Single Node Prometheus + Pushgateway Single node is pretty straightforward.