diff --git a/.gitignore b/.gitignore index e484e18c253b9bd16ef338e92f95bf5eb0bda35f..081dcadec860f6fdfa82d6cff7189500a81d3dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,19 @@ -docker-compose.override.yml -api_vidjil.py -vidjil/ + __pycache__ .env +api_vidjil.py -volumes*/ -volumes_dev/ - -certs/*.pem # WARNING; If you need to add real password, add them here and use dev docker compose file # ln -s docker-compose.dev.yml docker-compose.override.yml -metrics/conf_dev.py \ No newline at end of file +docker-compose.override.yml + +certs/*.pem + +metrics/conf_dev.py +metrics/.coverage + +vidjil/ + +volumes*/ +volumes_dev/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f65577ed6516d063363c074ea2ae760051ceab5..4ea688b62461639adde8ba162d21b41516401ebd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,24 @@ # Metrics stages : + - tests - publish_release + +test_metrics: + image: python:3.12-slim + stage: tests + script: + - apt-get update && apt-get install -y --no-install-recommends make git + - make -C metrics init + - make -C metrics unit + artifacts: + reports: + junit: tools/tests/should.xml + expire_in: 7 day + when: always + tags: + - cidocker - deploy_docker: stage: publish_release image: docker:latest @@ -25,6 +40,6 @@ deploy_docker: - docker tag $TAG "vidjil/metrics:latest" - docker push "vidjil/metrics:latest" - docker rmi $TAG "vidjil/metrics:latest" - # when: manual + when: manual tags: - cidocker diff --git a/doc/dev-metrics.md b/doc/dev-metrics.md index 28ecabf93cb308870ec3e611efa4881c172e4874..97086b86d4ef5b16d67b7204e69375d49fee5b79 100644 --- a/doc/dev-metrics.md +++ b/doc/dev-metrics.md @@ -4,73 +4,78 @@ The goal of this part is to be able to display different metrics from Vidjil to ``` mermaid graph LR - A[Serveur Vidil] -->|json| B[Metrics Instance]; + A[Vidjil server] -->|json| B[Metrics Instance]; B -->|query| A; B --> C[Prometheus]; C --> B; C --> D[Grafana]; ``` -##Â Metrics instance +## Metrics instance -Metrics instance uses `Flask` to create the web application. The `main` file create the `/metrics` Flask route where is displayed the metrics scraped with prometheus. These metrics are taken from the sql database and initialized in Vidjil in the `matrics.py` file using `pydale` queries. They are then called in the Metrics server and converted into Prometheus metrics. To access the metrics, a user has to be in the metrics group, we then added a new user in the database. To log as this user when launching a new metrics instance, we stored the variables `METRICS_USER_PASSWORD` and `METRICS_USER_EMAIL` in an .env file in Metrics instance. These variables are the login keys for the metrics user and taken as parameters for the login function in the main file. +Metrics instance uses `Flask` to create the web application. The `main` file create the `/metrics` Flask route where is displayed the metrics scraped with prometheus. These metrics are taken from the sql database and initialized in Vidjil in the `metrics.py` file using `pydal` queries. They are then called in the Metrics server and converted into Prometheus metrics. To access the metrics, a user has to be in the metrics group, we then added a new user in the database. To log as this user when launching a new metrics instance, we stored the variables `METRICS_USER_PASSWORD` and `METRICS_USER_EMAIL` in an .env file in Metrics instance. These variables are the login keys for the metrics user and taken as parameters for the login function in the main file. - -This software allow to use `API` to ask server some metrics that will be modifiy locally and exploited by `prometheus` service. +This software allow to use `API` to ask server some metrics that will be modify locally and exploited by `prometheus` service. The project is a simple flask application that use vidjil API to connect as admin to a server. -The API script is embeded to vidjil/tools; include here as a submodule. - +The API script is embedded to vidjil/tools; include here as a submodule. ## How to use 1. Install Docker and clone this repository. -1. First, you need to build docker image: - ``` +1. First, you need to build docker image: + + ```bash docker build . --tag vidjil/metrics-app ``` -1. Get server certificat as described in vidjil api documentation. + +1. Get server certificate as described in vidjil api documentation: + ```bash SERVERNAME=localhost # adapt it to your need echo -n | openssl s_client -connect $SERVERNAME:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ./cert_$SERVERNAME.pem - ``` + ``` + 1. Modify some environnement values: - * VIDJIL_USER: Admin user account to use to get metrics. Need to be created on the interogated server (metrics@vidjil.org) - * VIDJIL_PWD: Password of the acocunt; The usage of a docker secret can be made + * VIDJIL_USER: Admin user account to use to get metrics. Need to be created on the interrogated server (<metrics@vidjil.org>) + * VIDJIL_PWD: Password of the account; The usage of a docker secret can be made * SERVICE_NAME: Name of the docker service - * SERVER_URL: URL of server to interogate. - * SERVER_CHAIN: Local downloaded certificate from interogated server (server chain `.pem` file) -1. Then you should just run the container: -``` + * SERVER_URL: URL of server to interrogate. + * SERVER_CHAIN: Local downloaded certificate from interrogated server (server chain `.pem` file) + +1. Then you should just run the container: + +```bash docker-compose up -d -``` +``` + **Note:** do not forget to change port in all places(in Dockerfile, in your app and when starting container) if you are changing it. -1. After that your app should be accessible via http://127.0.0.1:5000/ and you should see "Hello World!" there: +1. After that your app should be accessible via <http://127.0.0.1:5000/> and you should see "Hello World!" there: +```html <details>  <summary>Hello world page</summary> </details> +``` +## Metrics retrieved +Metrics retrieved may vary from one server to another. These metrics is in Prometheus format and will be use into Grafana vidjil dashboard (see ). +Once server is launched, you should get metrics accessible at <https://localhost:5000/metrics>. -##Â Metrics getted - -Metrics getted may vary from one server to another. These metrics is in Prometheus format and will be use into Grafana vidjil dashboard (see ). - -Once server is launched, you should get metrics accessible at https://localhost:5000/metrics. - - +```html <details>  <summary>Metrics page</summary> </details> +``` ## Metrics server -Metrics server launches the Grafana, Prometheus, BlackBox and Node exporter servers using `docker images`. +Metrics server launches the Grafana, Prometheus and Node exporter servers using `docker images`. ## Grafana @@ -79,14 +84,13 @@ Once we collected metrics with prometheus, we use Grafana to display them. Grafa username : `unicorn` password : `UnicornExists!` -Then, head to the `Vidjil dashboard` to see the metrics scraped by prometheus. +Then, head to the `Vidjil dashboard` to see the metrics scraped by prometheus. -#### New Panel +### New Panel To create a new panel to display a metric, click on `add`, `visualization`. with Prometheus as the data source you can then select a metric to display in a new query and optionally add `label filters` and/or `operations` to make it more specific. To have a better representation, you can change the graph type and modify the legend to make it mor clear. -#### New Alert +### New Alert If you want to be alerted when a change (exceeds a threshold for example) happens on this new metrics, you can create a `new alert rule` in the Alert tab of your panel. -To set the alert condition of your choice, modify the `Expressions` (`Reduce` is mandatory to change the time series to a single value). Chose a folder and an evaluation group. To send a notification when the alert is firing, select a `contact point` or create a new one. You can also add other optional features to suit your needs. - +To set the alert condition of your choice, modify the `Expressions` (`Reduce` is mandatory to change the time series to a single value). Chose a folder and an evaluation group. To send a notification when the alert is firing, select a `contact point` or create a new one. You can also add other optional features to suit your needs. diff --git a/metrics/Makefile b/metrics/Makefile index cd6143b6f0ef4508d64515c0faa5e08119831483..59fa6481bd4b3015b746c112d11db28c0ed5c542 100644 --- a/metrics/Makefile +++ b/metrics/Makefile @@ -1,14 +1,14 @@ + init_submodule: git submodule init git submodule update --remote -build_metrics: - docker compose build vidjil - init: python3 -m pip install -U pip python3 -m pip install --no-cache -r requirements.txt -unit: - #python3 -m pytest --cov=./ --cov-report html:cov.html -v -s . - python3 -m unittest test_main.py \ No newline at end of file +unit: + python3 -m pytest --cov=./*.py --cov-report html:cov.html -v -s ./tests + +build_metrics: + docker compose build vidjil diff --git a/metrics/conf.py b/metrics/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..b624b5b740c9d96e505426ec5316afa6b30dc95b --- /dev/null +++ b/metrics/conf.py @@ -0,0 +1,14 @@ +# +# Config file. +# You can set here list of server to follow by giving their url and certificat file name as present in certs directory +# + + +vidjil_servers = [ + { + "url": "https://localhost/vidjil/", + "certificat": "./certs/cert_localhost.pem", + "user":"metrics@vidjil.org", + "password": "foobartest" + } +] diff --git a/metrics/entrypoints/flask-entrypoint.sh b/metrics/entrypoints/flask-entrypoint.sh index 1c191606e212fd659f0ef20210d9405c9fa04347..44f5cf9ecc8ef9fc6d8af737dbe12c9842196235 100644 --- a/metrics/entrypoints/flask-entrypoint.sh +++ b/metrics/entrypoints/flask-entrypoint.sh @@ -1,13 +1,14 @@ #!/bin/bash echo -e "\e[34m===============================\e[0m" echo -e "\e[34m=== Start service flask metrics\e[0m" -echo -e "\e[34m=== `date +'%Y/%m/%d; %H:%M'`\e[0m"; echo +echo -e "\e[34m=== `date +'%Y/%m/%d; %H:%M'`\e[0m" +echo -echo Variables: -echo -e user = $VIDJIL_USER -echo -e password = $VIDJIL_PWD -echo -e url_server = $SERVER_URL -echo -e certificat = $SERVER_CHAIN +# echo Variables: +# echo -e user = $VIDJIL_USER +# echo -e password = $VIDJIL_PWD +# echo -e url_server = $SERVER_URL +# echo -e certificat = $SERVER_CHAIN echo " ======= main.py" python main.py diff --git a/metrics/requirements.txt b/metrics/requirements.txt index 97f923afbdcb850e76c81ccc5dd0e6c3272104d6..1f9eb2e216ee122feb91702f4c96c88b5a784f87 100644 --- a/metrics/requirements.txt +++ b/metrics/requirements.txt @@ -5,4 +5,6 @@ tabulate requests requests-toolbelt urllib3 -setuptools \ No newline at end of file +setuptools +pytest +pytest-cov diff --git a/metrics/tests/test_main.py b/metrics/tests/test_main.py new file mode 100644 index 0000000000000000000000000000000000000000..e93ea8a5aa8153fda0f1849e98162130c706ca72 --- /dev/null +++ b/metrics/tests/test_main.py @@ -0,0 +1,40 @@ +import unittest +import main + +class TestMain(unittest.TestCase): + + def test_convert_login_count(self): + url_server = "https://localhost/vidjil/" + data = [{'_extra': {'COUNT(`auth_event`.`id`)': 3}, 'auth_event': {'description': 'User 1 Logged-in', 'user_id': 1}, 'auth_user': {'email': 'plop@plop.com'}}, {'_extra': {'COUNT(`auth_event`.`id`)': 1275}, 'auth_event': {'description': 'User 2 Logged-in', 'user_id': 2}, 'auth_user': {'email': 'metrics@vidjil.org'}}, {'_extra': {'COUNT(`auth_event`.`id`)': 14}, 'auth_event': {'description': 'User 3 Logged-in', 'user_id': 3}, 'auth_user': {'email': 'user1@test.com'}}, {'_extra': {'COUNT(`auth_event`.`id`)': 18}, 'auth_event': {'description': 'User 4 Logged-in', 'user_id': 4}, 'auth_user': {'email': 'user2@test.com'}}, {'_extra': {'COUNT(`auth_event`.`id`)': 8}, 'auth_event': {'description': 'User 5 Logged-in', 'user_id': 5}, 'auth_user': {'email': 'user3@test.com'}}, {'_extra': {'COUNT(`auth_event`.`id`)': 22}, 'auth_event': {'description': 'User 6 Logged-in', 'user_id': 6}, 'auth_user': {'email': 'user4@test.com'}}, {'_extra': {'COUNT(`auth_event`.`id`)': 15}, 'auth_event': {'description': 'User 7 Logged-in', 'user_id': 7}, 'auth_user': {'email': 'user5@test.com'}}] + result = main.convert_login_count('login_count', {'description': '', 'type' : ''}, data, url_server) + print(result) + self.assertEqual(result, '# HELP vidjil_api_request_login_count \n# TYPE vidjil_api_request_login_count \nvidjil_api_request_login_count{user_id="1", user_email="plop@plop.com", server="https://localhost/vidjil/"} 3\nvidjil_api_request_login_count{user_id="3", user_email="user1@test.com", server="https://localhost/vidjil/"} 14\nvidjil_api_request_login_count{user_id="4", user_email="user2@test.com", server="https://localhost/vidjil/"} 18\nvidjil_api_request_login_count{user_id="5", user_email="user3@test.com", server="https://localhost/vidjil/"} 8\nvidjil_api_request_login_count{user_id="6", user_email="user4@test.com", server="https://localhost/vidjil/"} 22\nvidjil_api_request_login_count{user_id="7", user_email="user5@test.com", server="https://localhost/vidjil/"} 15\n') + + def test_convert_login_count_2(self): + url_server = "https://localhost/vidjil/" + data = [{'_extra': {'COUNT(`auth_event`.`id`)': 3}, 'auth_event': {'description': 'User 1 Logged-in', 'user_id': 1}, 'auth_user': {'email': 'plop@plop.com'}}] + result = main.convert_login_count('login_count', {'description': '', 'type' : ''}, data, url_server) + print(result) + self.assertEqual(result, '# HELP vidjil_api_request_login_count \n# TYPE vidjil_api_request_login_count \nvidjil_api_request_login_count{user_id="1", user_email="plop@plop.com", server="https://localhost/vidjil/"} 3\n') + + def test_convert_login_count_3(self): + url_server = "https://localhost/vidjil/" + data = [{'_extra': {'COUNT(`auth_event`.`id`)': 0}, 'auth_event': {'description': 'User 1 Logged-in', 'user_id': 1}, 'auth_user': {'email': 'plop@plop.com'}}] + result = main.convert_login_count('login_count', {'description': '', 'type' : ''}, data, url_server) + print(result) + self.assertEqual(result, '# HELP vidjil_api_request_login_count \n# TYPE vidjil_api_request_login_count \nvidjil_api_request_login_count{user_id="1", user_email="plop@plop.com", server="https://localhost/vidjil/"} 0\n') + + def test_convert_configs_analysis(self): + url_server = "https://localhost/vidjil/" + data = [{'_extra': {'COUNT(`results_file`.`id`)': 64}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 15}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 13}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 18}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 11}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}] + result = main.convert_configs_analysis('config_analysis', {'description': '', 'type' : ''}, data, url_server) + print(result) + self.assertEqual(result, '# HELP vidjil_api_request_config_analysis \n# TYPE vidjil_api_request_config_analysis \nvidjil_api_request_config_analysis{config_name="default _ extract reads", config_program="vidjil", config_id="1", server="https://localhost/vidjil/"} 64\nvidjil_api_request_config_analysis{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", server="https://localhost/vidjil/"} 15\nvidjil_api_request_config_analysis{config_name="multi_inc", config_program="vidjil", config_id="3", server="https://localhost/vidjil/"} 13\nvidjil_api_request_config_analysis{config_name="multi", config_program="vidjil", config_id="4", server="https://localhost/vidjil/"} 18\nvidjil_api_request_config_analysis{config_name="TRG", config_program="vidjil", config_id="5", server="https://localhost/vidjil/"} 11\n') + + def test_convert_configs_analysis_by_groups(self): + url_server = "https://localhost/vidjil:8000/" + data = [{'_extra': {'COUNT(`results_file`.`id`)': 15}, 'auth_group': {'role': 'admin'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 15}, 'auth_group': {'role': 'user_0001'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 130}, 'auth_group': {'role': 'public'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 25}, 'auth_group': {'role': 'user_0003'}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 23}, 'auth_group': {'role': 'user_0003'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 22}, 'auth_group': {'role': 'user_0003'}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 21}, 'auth_group': {'role': 'user_0003'}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 25}, 'auth_group': {'role': 'user_0003'}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}, {'_extra': {'COUNT(`results_file`.`id`)': 138}, 'auth_group': {'role': 'public'}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 128}, 'auth_group': {'role': 'public'}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 111}, 'auth_group': {'role': 'public'}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 125}, 'auth_group': {'role': 'public'}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}, {'_extra': {'COUNT(`results_file`.`id`)': 34}, 'auth_group': {'role': 'user_0004'}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 27}, 'auth_group': {'role': 'user_0004'}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}, {'_extra': {'COUNT(`results_file`.`id`)': 33}, 'auth_group': {'role': 'user_0004'}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 22}, 'auth_group': {'role': 'user_0004'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 25}, 'auth_group': {'role': 'user_0004'}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 28}, 'auth_group': {'role': 'user_0005'}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}, {'_extra': {'COUNT(`results_file`.`id`)': 25}, 'auth_group': {'role': 'user_0005'}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 31}, 'auth_group': {'role': 'user_0005'}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 26}, 'auth_group': {'role': 'user_0005'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 21}, 'auth_group': {'role': 'user_0005'}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 21}, 'auth_group': {'role': 'user_0006'}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 27}, 'auth_group': {'role': 'user_0006'}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}, {'_extra': {'COUNT(`results_file`.`id`)': 25}, 'auth_group': {'role': 'user_0006'}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 25}, 'auth_group': {'role': 'user_0006'}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 14}, 'auth_group': {'role': 'user_0006'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}, {'_extra': {'COUNT(`results_file`.`id`)': 22}, 'auth_group': {'role': 'user_0007'}, 'config': {'name': 'multi', 'program': 'vidjil'}, 'results_file': {'config_id': 4}}, {'_extra': {'COUNT(`results_file`.`id`)': 18}, 'auth_group': {'role': 'user_0007'}, 'config': {'name': 'TRG', 'program': 'vidjil'}, 'results_file': {'config_id': 5}}, {'_extra': {'COUNT(`results_file`.`id`)': 23}, 'auth_group': {'role': 'user_0007'}, 'config': {'name': 'multi+inc', 'program': 'vidjil'}, 'results_file': {'config_id': 3}}, {'_extra': {'COUNT(`results_file`.`id`)': 24}, 'auth_group': {'role': 'user_0007'}, 'config': {'name': 'multi+inc+xxx', 'program': 'vidjil'}, 'results_file': {'config_id': 2}}, {'_extra': {'COUNT(`results_file`.`id`)': 30}, 'auth_group': {'role': 'user_0007'}, 'config': {'name': 'default + extract reads', 'program': 'vidjil'}, 'results_file': {'config_id': 1}}] + result = main.convert_configs_analysis('config_analysis', {'description': '', 'type' : ''}, data, url_server) + print(result) + self.assertEqual(result, '# HELP vidjil_api_request_config_analysis_by_groups configs_analysis.\n# TYPE vidjil_api_request_config_analysis_by_groups gauge\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="admin", server="https://localhost:8000/vidjil/"} 15\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="user_0001", server="https://localhost:8000/vidjil/"} 15\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="public", server="https://localhost:8000/vidjil/"} 130\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", group="user_0003", server="https://localhost:8000/vidjil/"} 25\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="user_0003", server="https://localhost:8000/vidjil/"} 23\nvidjil_api_request_config_analysis_by_groups{config_name="multi", config_program="vidjil", config_id="4", group="user_0003", server="https://localhost:8000/vidjil/"} 22\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc", config_program="vidjil", config_id="3", group="user_0003", server="https://localhost:8000/vidjil/"} 21\nvidjil_api_request_config_analysis_by_groups{config_name="TRG", config_program="vidjil", config_id="5", group="user_0003", server="https://localhost:8000/vidjil/"} 25\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", group="public", server="https://localhost:8000/vidjil/"} 138\nvidjil_api_request_config_analysis_by_groups{config_name="multi", config_program="vidjil", config_id="4", group="public", server="https://localhost:8000/vidjil/"} 128\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc", config_program="vidjil", config_id="3", group="public", server="https://localhost:8000/vidjil/"} 111\nvidjil_api_request_config_analysis_by_groups{config_name="TRG", config_program="vidjil", config_id="5", group="public", server="https://localhost:8000/vidjil/"} 125\nvidjil_api_request_config_analysis_by_groups{config_name="multi", config_program="vidjil", config_id="4", group="user_0004", server="https://localhost:8000/vidjil/"} 34\nvidjil_api_request_config_analysis_by_groups{config_name="TRG", config_program="vidjil", config_id="5", group="user_0004", server="https://localhost:8000/vidjil/"} 27\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", group="user_0004", server="https://localhost:8000/vidjil/"} 33\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="user_0004", server="https://localhost:8000/vidjil/"} 22\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc", config_program="vidjil", config_id="3", group="user_0004", server="https://localhost:8000/vidjil/"} 25\nvidjil_api_request_config_analysis_by_groups{config_name="TRG", config_program="vidjil", config_id="5", group="user_0005", server="https://localhost:8000/vidjil/"} 28\nvidjil_api_request_config_analysis_by_groups{config_name="multi", config_program="vidjil", config_id="4", group="user_0005", server="https://localhost:8000/vidjil/"} 25\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", group="user_0005", server="https://localhost:8000/vidjil/"} 31\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="user_0005", server="https://localhost:8000/vidjil/"} 26\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc", config_program="vidjil", config_id="3", group="user_0005", server="https://localhost:8000/vidjil/"} 21\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc", config_program="vidjil", config_id="3", group="user_0006", server="https://localhost:8000/vidjil/"} 21\nvidjil_api_request_config_analysis_by_groups{config_name="TRG", config_program="vidjil", config_id="5", group="user_0006", server="https://localhost:8000/vidjil/"} 27\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", group="user_0006", server="https://localhost:8000/vidjil/"} 25\nvidjil_api_request_config_analysis_by_groups{config_name="multi", config_program="vidjil", config_id="4", group="user_0006", server="https://localhost:8000/vidjil/"} 25\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="user_0006", server="https://localhost:8000/vidjil/"} 14\nvidjil_api_request_config_analysis_by_groups{config_name="multi", config_program="vidjil", config_id="4", group="user_0007", server="https://localhost:8000/vidjil/"} 22\nvidjil_api_request_config_analysis_by_groups{config_name="TRG", config_program="vidjil", config_id="5", group="user_0007", server="https://localhost:8000/vidjil/"} 18\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc", config_program="vidjil", config_id="3", group="user_0007", server="https://localhost:8000/vidjil/"} 23\nvidjil_api_request_config_analysis_by_groups{config_name="multi_inc_xxx", config_program="vidjil", config_id="2", group="user_0007", server="https://localhost:8000/vidjil/"} 24\nvidjil_api_request_config_analysis_by_groups{config_name="default _ extract reads", config_program="vidjil", config_id="1", group="user_0007", server="https://localhost:8000/vidjil/"} 30\n') +