From e698d124baa8dc5b6724a8af8eef5011aa973d9b Mon Sep 17 00:00:00 2001 From: Martyn Inglis Date: Fri, 25 Nov 2016 13:27:36 +0000 Subject: [PATCH] Statsd counter for user agents. We want to log the usage of the various API clients we have so that we understand when they can be cycled. To this end we are going to count usage in statsd. All notify clients have a suer agent, of the format: NOTIFY-API-{LANGUAGE}-CLIENT/version.number For example, NOTIFY-API-PYTHON-CLIENT/3.0.0 We convert that into a statsd/graphite friendly string of the format: notify-api-python-client.3-0-0 So we can subdivide on client and client version on our dashboards. Present but unknown User agents are records as "non-notify-user-agent" Missing are presented as "unknown" --- app/__init__.py | 17 +++++++++++++++++ tests/app/test_user_agent_processing.py | 13 +++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/app/test_user_agent_processing.py diff --git a/app/__init__.py b/app/__init__.py index 73082d14e..9051620a3 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -114,12 +114,17 @@ def init_app(app): url_for('status.show_delivery_status'), url_for('spec.get_spec') ] + if request.path not in no_auth_req: from app.authentication import auth error = auth.requires_auth() if error: return error + @app.before_request + def record_user_agent(): + statsd_client.incr("user-agent.{}".format(process_user_agent(request.headers.get('User-Agent', None)))) + @app.before_request def record_request_details(): g.start = monotonic() @@ -141,3 +146,15 @@ def init_app(app): def create_uuid(): return str(uuid.uuid4()) + + +def process_user_agent(user_agent_string): + if user_agent_string and user_agent_string.lower().startswith("notify"): + components = user_agent_string.split("/") + client_name = components[0].lower() + client_version = components[1].replace(".", "-") + return "{}.{}".format(client_name, client_version) + elif user_agent_string and not user_agent_string.lower().startswith("notify"): + return "non-notify-user-agent" + else: + return "unknown" diff --git a/tests/app/test_user_agent_processing.py b/tests/app/test_user_agent_processing.py new file mode 100644 index 000000000..161b0e475 --- /dev/null +++ b/tests/app/test_user_agent_processing.py @@ -0,0 +1,13 @@ +from app import process_user_agent + + +def test_can_process_notify_api_user_agent(): + assert "notify-api-python-client.3-0-0" == process_user_agent("NOTIFY-API-PYTHON-CLIENT/3.0.0") + + +def test_can_handle_non_notify_api_user_agent(): + assert "non-notify-user-agent" == process_user_agent("Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405") # noqa + + +def test_handles_null_user_agent(): + assert "unknown" == process_user_agent(None)