From d49af6fd37547eef7acd4ac7f6f990903a29d6d4 Mon Sep 17 00:00:00 2001 From: Simon Hornby Date: Thu, 25 Jul 2024 17:24:37 +0200 Subject: [PATCH] feat: add metrics metadata (#317) --- UnleashClient/api/register.py | 12 ++++-- UnleashClient/periodic_tasks/send_metrics.py | 7 +++- tests/unit_tests/api/test_register.py | 28 +++++++++++++- .../test_aggregate_and_send_metrics.py | 37 ++++++++++++++++++- 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/UnleashClient/api/register.py b/UnleashClient/api/register.py index 19f365da..dc153067 100644 --- a/UnleashClient/api/register.py +++ b/UnleashClient/api/register.py @@ -1,11 +1,13 @@ import json from datetime import datetime, timezone +from platform import python_implementation, python_version import requests from requests.exceptions import InvalidHeader, InvalidSchema, InvalidURL, MissingSchema from UnleashClient.constants import ( APPLICATION_HEADERS, + CLIENT_SPEC_VERSION, REGISTER_URL, SDK_NAME, SDK_VERSION, @@ -41,22 +43,26 @@ def register_client( :param request_timeout: :return: true if registration successful, false if registration unsuccessful or exception. """ - registation_request = { + registration_request = { "appName": app_name, "instanceId": instance_id, "sdkVersion": f"{SDK_NAME}:{SDK_VERSION}", "strategies": [*supported_strategies], "started": datetime.now(timezone.utc).isoformat(), "interval": metrics_interval, + "platformName": python_implementation(), + "platformVersion": python_version(), + "yggdrasilVersion": None, + "specVersion": CLIENT_SPEC_VERSION, } try: LOGGER.info("Registering unleash client with unleash @ %s", url) - LOGGER.info("Registration request information: %s", registation_request) + LOGGER.info("Registration request information: %s", registration_request) resp = requests.post( url + REGISTER_URL, - data=json.dumps(registation_request), + data=json.dumps(registration_request), headers={**custom_headers, **APPLICATION_HEADERS}, timeout=request_timeout, **custom_options, diff --git a/UnleashClient/periodic_tasks/send_metrics.py b/UnleashClient/periodic_tasks/send_metrics.py index b1634e79..e6076c49 100644 --- a/UnleashClient/periodic_tasks/send_metrics.py +++ b/UnleashClient/periodic_tasks/send_metrics.py @@ -1,9 +1,10 @@ from collections import ChainMap from datetime import datetime, timezone +from platform import python_implementation, python_version from UnleashClient.api import send_metrics from UnleashClient.cache import BaseCache -from UnleashClient.constants import METRIC_LAST_SENT_TIME +from UnleashClient.constants import CLIENT_SPEC_VERSION, METRIC_LAST_SENT_TIME from UnleashClient.utils import LOGGER @@ -52,6 +53,10 @@ def aggregate_and_send_metrics( "stop": datetime.now(timezone.utc).isoformat(), "toggles": feature_stats_dict, }, + "platformName": python_implementation(), + "platformVersion": python_version(), + "yggdrasilVersion": None, + "specVersion": CLIENT_SPEC_VERSION, } if feature_stats_dict: diff --git a/tests/unit_tests/api/test_register.py b/tests/unit_tests/api/test_register.py index 7ee670a6..6f5cf4e1 100644 --- a/tests/unit_tests/api/test_register.py +++ b/tests/unit_tests/api/test_register.py @@ -1,3 +1,5 @@ +import json + import responses from pytest import mark, param from requests import ConnectionError @@ -13,7 +15,7 @@ URL, ) from UnleashClient.api import register_client -from UnleashClient.constants import REGISTER_URL +from UnleashClient.constants import CLIENT_SPEC_VERSION, REGISTER_URL FULL_REGISTER_URL = URL + REGISTER_URL @@ -48,3 +50,27 @@ def test_register_client(payload, status, expected): assert len(responses.calls) == 1 assert result is expected + + +@responses.activate +def test_register_includes_metadata(): + responses.add(responses.POST, FULL_REGISTER_URL, json={}, status=202) + + register_client( + URL, + APP_NAME, + INSTANCE_ID, + METRICS_INTERVAL, + CUSTOM_HEADERS, + CUSTOM_OPTIONS, + DEFAULT_STRATEGY_MAPPING, + REQUEST_TIMEOUT, + ) + + assert len(responses.calls) == 1 + request = json.loads(responses.calls[0].request.body) + + assert request["yggdrasilVersion"] is None + assert request["specVersion"] == CLIENT_SPEC_VERSION + assert request["platformName"] is not None + assert request["platformVersion"] is not None diff --git a/tests/unit_tests/periodic/test_aggregate_and_send_metrics.py b/tests/unit_tests/periodic/test_aggregate_and_send_metrics.py index 25dd36dd..edb67e7a 100644 --- a/tests/unit_tests/periodic/test_aggregate_and_send_metrics.py +++ b/tests/unit_tests/periodic/test_aggregate_and_send_metrics.py @@ -14,7 +14,11 @@ URL, ) from UnleashClient.cache import FileCache -from UnleashClient.constants import METRIC_LAST_SENT_TIME, METRICS_URL +from UnleashClient.constants import ( + CLIENT_SPEC_VERSION, + METRIC_LAST_SENT_TIME, + METRICS_URL, +) from UnleashClient.features import Feature from UnleashClient.periodic_tasks import aggregate_and_send_metrics from UnleashClient.strategies import Default, RemoteAddress @@ -107,3 +111,34 @@ def test_no_metrics(): ) assert len(responses.calls) == 0 + + +@responses.activate +def test_metrics_metadata_is_sent(): + responses.add(responses.POST, FULL_METRICS_URL, json={}, status=200) + + cache = FileCache("TestCache") + + to_make_sure_metrics_fires = Feature("My Feature1", True, None) + to_make_sure_metrics_fires.yes_count = 1 + + features = {"Something": to_make_sure_metrics_fires} + + aggregate_and_send_metrics( + URL, + APP_NAME, + INSTANCE_ID, + CUSTOM_HEADERS, + CUSTOM_OPTIONS, + features, + cache, + REQUEST_TIMEOUT, + ) + + assert len(responses.calls) == 1 + request = json.loads(responses.calls[0].request.body) + + assert request["yggdrasilVersion"] is None + assert request["specVersion"] == CLIENT_SPEC_VERSION + assert request["platformName"] is not None + assert request["platformVersion"] is not None