diff --git a/app/__init__.py b/app/__init__.py index aa106d4b3..2524bace0 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -7,6 +7,7 @@ from flask import _request_ctx_stack, request, g, jsonify, make_response from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy from flask_marshmallow import Marshmallow from flask_migrate import Migrate +from gds_metrics import GDSMetrics from time import monotonic from notifications_utils.clients.zendesk.zendesk_client import ZendeskClient from notifications_utils.clients.statsd.statsd_client import StatsdClient @@ -54,6 +55,7 @@ statsd_client = StatsdClient() redis_store = RedisClient() performance_platform_client = PerformancePlatformClient() document_download_client = DocumentDownloadClient() +metrics = GDSMetrics() clients = Clients() @@ -86,6 +88,7 @@ def create_app(application): performance_platform_client.init_app(application) document_download_client.init_app(application) clients.init_app(sms_clients=[firetext_client, mmg_client], email_clients=[aws_ses_client]) + metrics.init_app(application) register_blueprint(application) register_v2_blueprints(application) diff --git a/gunicorn_config.py b/gunicorn_config.py index 979bc9f5f..d32eaba2d 100644 --- a/gunicorn_config.py +++ b/gunicorn_config.py @@ -3,6 +3,8 @@ import sys import traceback import gunicorn +from gds_metrics.gunicorn import child_exit # noqa + workers = 4 worker_class = "eventlet" worker_connections = 256 diff --git a/manifest.yml.j2 b/manifest.yml.j2 index 8424f56d8..da9f67be7 100644 --- a/manifest.yml.j2 +++ b/manifest.yml.j2 @@ -65,6 +65,9 @@ applications: services: - notify-db - logit-ssl-syslog-drain + {% if CF_APP == 'notify-api' %} + - notify-prometheus + {% endif %} env: NOTIFY_APP_NAME: {{ app.get('NOTIFY_APP_NAME', CF_APP.replace('notify-', '')) }} diff --git a/requirements-app.txt b/requirements-app.txt index 819a2f1cd..d48a5fc17 100644 --- a/requirements-app.txt +++ b/requirements-app.txt @@ -27,3 +27,5 @@ notifications-python-client==5.5.1 awscli-cwlogs>=1.4,<1.5 git+https://github.com/alphagov/notifications-utils.git@37.0.1#egg=notifications-utils==37.0.1 + +gds-metrics==0.2.0 diff --git a/requirements.txt b/requirements.txt index 4c63a7fa6..bc0f4972d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,18 +30,21 @@ awscli-cwlogs>=1.4,<1.5 git+https://github.com/alphagov/notifications-utils.git@37.0.1#egg=notifications-utils==37.0.1 +gds-metrics==0.2.0 + ## The following requirements were added by pip freeze: alembic==1.4.2 amqp==1.4.9 anyjson==0.3.3 attrs==19.3.0 -awscli==1.18.40 +awscli==1.18.41 bcrypt==3.1.7 billiard==3.3.0.23 bleach==3.1.4 +blinker==1.4 boto==2.49.0 boto3==1.10.38 -botocore==1.15.40 +botocore==1.15.41 certifi==2020.4.5.1 chardet==3.0.4 click==7.1.1 @@ -62,6 +65,7 @@ mistune==0.8.4 monotonic==1.5 orderedset==2.0.1 phonenumbers==8.11.2 +prometheus-client==0.2.0 pyasn1==0.4.8 pycparser==2.20 PyPDF2==1.26.0 diff --git a/tests/app/test_route_authentication.py b/tests/app/test_route_authentication.py index 18bb7bbc2..e8ed40583 100644 --- a/tests/app/test_route_authentication.py +++ b/tests/app/test_route_authentication.py @@ -6,7 +6,11 @@ def test_all_routes_have_authentication(client): blueprint_names = set(client.application.blueprints.keys()) assert blueprint_names == before_req_funcs + routes_blueprint_names = set([x.split('.')[0] for x in client.application.view_functions.keys()]) + # The static route is always available by default for a Flask app to serve anything in the static folder. - routes_blueprint_names = set( - [x.split('.')[0] for x in client.application.view_functions.keys() if x.split('.')[0] != 'static']) + routes_blueprint_names.remove('static') + + # The metrics route is not protected by auth as it's available to be scraped by Prometheus + routes_blueprint_names.remove('metrics') assert sorted(blueprint_names) == sorted(routes_blueprint_names)