From 08343609612327745cbcc0b077bcf8039938d535 Mon Sep 17 00:00:00 2001 From: nhnn Date: Mon, 8 Jul 2024 18:18:07 +0300 Subject: [PATCH] feat: add memory and cpu metrics --- selfprivacy_api/graphql/queries/monitoring.py | 8 +- selfprivacy_api/utils/prometheus.py | 27 ++ tests/test_graphql/test_api_monitoring.py | 292 +++++++++--------- 3 files changed, 183 insertions(+), 144 deletions(-) diff --git a/selfprivacy_api/graphql/queries/monitoring.py b/selfprivacy_api/graphql/queries/monitoring.py index 45290e7..7efab49 100644 --- a/selfprivacy_api/graphql/queries/monitoring.py +++ b/selfprivacy_api/graphql/queries/monitoring.py @@ -6,8 +6,12 @@ from selfprivacy_api.utils.prometheus import PrometheusQueries @strawberry.type class Monitoring: @strawberry.field - def disks_usage(): - return PrometheusQueries.disks_usage() + def disk_usage(): + return PrometheusQueries.disk_usage() + + @strawberry.field + def memory_usage(): + return PrometheusQueries.memory_usage() @strawberry.field def cpu_usage(): diff --git a/selfprivacy_api/utils/prometheus.py b/selfprivacy_api/utils/prometheus.py index da057ee..a62b93f 100644 --- a/selfprivacy_api/utils/prometheus.py +++ b/selfprivacy_api/utils/prometheus.py @@ -67,6 +67,33 @@ class PrometheusQueries: return PrometheusQueries._send_query(query, start, end, step) + @staticmethod + def memory_usage( + start: Optional[int] = None, + end: Optional[int] = None, + step: int = 60, # seconds + ) -> PrometheusQueryResult: + """ + Get memory usage. + + Args: + start (int, optional): Unix timestamp indicating the start time. + Defaults to 20 minutes ago if not provided. + end (int, optional): Unix timestamp indicating the end time. + Defaults to current time if not provided. + step (int): Interval in seconds for querying memory usage data. + """ + + if not start: + start = int((datetime.now() - timedelta(minutes=20)).timestamp()) + + if not end: + end = int(datetime.now().timestamp()) + + query = "100 - (100 * (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))" + + return PrometheusQueries._send_query(query, start, end, step) + @staticmethod def disk_usage( start: Optional[int] = None, diff --git a/tests/test_graphql/test_api_monitoring.py b/tests/test_graphql/test_api_monitoring.py index b57434b..27590e9 100644 --- a/tests/test_graphql/test_api_monitoring.py +++ b/tests/test_graphql/test_api_monitoring.py @@ -10,146 +10,69 @@ from tests.test_graphql.common import ( ) -MOCK_CPU_USAGE_RESPONSE = { - "data": { - "monitoring": { - "cpu_usage": { - "resultType": "matrix", - "result": [ - { - "metric": {"instance": "127.0.0.1:9002"}, - "values": [ - [1720135748, "3.75"], - [1720135808, "4.525000000139698"], - [1720135868, "4.541666666433841"], - [1720135928, "4.574999999798209"], - [1720135988, "4.579166666759804"], - [1720136048, "3.8791666664959195"], - [1720136108, "4.5458333333954215"], - [1720136168, "4.566666666651145"], - [1720136228, "4.791666666666671"], - [1720136288, "4.720833333364382"], - [1720136348, "3.9624999999068677"], - [1720136408, "4.6875"], - [1720136468, "4.404166666790843"], - [1720136528, "4.31666666680637"], - [1720136588, "4.358333333317816"], - [1720136648, "3.7083333334885538"], - [1720136708, "4.558333333116025"], - [1720136768, "4.729166666511446"], - [1720136828, "4.75416666672875"], - [1720136888, "4.624999999844775"], - [1720136948, "3.9041666667132375"], - ], - } - ], +def generate_mock_metrics(name: str): + return { + "data": { + "monitoring": { + f"{name}": { + "resultType": "matrix", + "result": [ + { + "metric": {"instance": "127.0.0.1:9002"}, + "values": [ + [1720135748, "3.75"], + [1720135808, "4.525000000139698"], + [1720135868, "4.541666666433841"], + [1720135928, "4.574999999798209"], + [1720135988, "4.579166666759804"], + [1720136048, "3.8791666664959195"], + [1720136108, "4.5458333333954215"], + [1720136168, "4.566666666651145"], + [1720136228, "4.791666666666671"], + [1720136288, "4.720833333364382"], + [1720136348, "3.9624999999068677"], + [1720136408, "4.6875"], + [1720136468, "4.404166666790843"], + [1720136528, "4.31666666680637"], + [1720136588, "4.358333333317816"], + [1720136648, "3.7083333334885538"], + [1720136708, "4.558333333116025"], + [1720136768, "4.729166666511446"], + [1720136828, "4.75416666672875"], + [1720136888, "4.624999999844775"], + [1720136948, "3.9041666667132375"], + ], + } + ], + } } } } -} -MOCK_DISKS_USAGE_RESPONSE = { - "data": { - "monitoring": { - "filesystem_usage": { - "resultType": "matrix", - "result": [ - { - "metric": { - "device": "/dev/sda1", - "fstype": "ext4", - "instance": "127.0.0.1:9002", - "job": "node-exporter", - "mountpoint": "/", - }, - "values": [ - [1720135748, "58.96622455596515"], - [1720135808, "58.96624522725708"], - [1720135868, "58.96628656984096"], - [1720135928, "58.96632791242483"], - [1720135988, "58.96634858371677"], - [1720136048, "58.96638992630064"], - [1720136108, "58.96641059759258"], - [1720136168, "58.966451940176455"], - [1720136228, "58.96649328276033"], - [1720136288, "58.96651395405226"], - [1720136348, "58.966555296636145"], - [1720136408, "58.966596639220015"], - [1720136468, "58.96661731051196"], - [1720136528, "58.96665865309583"], - [1720136588, "58.9666999956797"], - [1720136648, "58.96672066697164"], - [1720136708, "58.96676200955551"], - [1720136768, "58.966782680847444"], - [1720136828, "58.96682402343132"], - [1720136888, "58.9668653660152"], - [1720136948, "58.966886037307134"], - ], - } - ], - } - } - } -} - -MOCK_MEMORY_USAGE_RESPONSE = { - "data": { - "monitoring": { - "memory_usage": { - "resultType": "matrix", - "result": [ - { - "metric": { - "instance": "127.0.0.1:9002", - "job": "node-exporter", - }, - "values": [ - [1720135748, "36.7520332586628"], - [1720135808, "36.75183144638857"], - [1720135868, "36.744969829065"], - [1720135928, "36.74456620451656"], - [1720135988, "36.74436439224233"], - [1720136048, "36.74396076769389"], - [1720136108, "36.73689733809611"], - [1720136168, "36.73669552582189"], - [1720136228, "36.93507699138262"], - [1720136288, "36.941131359609294"], - [1720136348, "36.93104074589817"], - [1720136408, "36.936691489576404"], - [1720136468, "36.93003168452705"], - [1720136528, "36.91994107081593"], - [1720136588, "36.91307945349236"], - [1720136648, "36.90964864483058"], - [1720136708, "36.90238340295857"], - [1720136768, "36.89592541018345"], - [1720136828, "36.89148554015055"], - [1720136888, "36.88462392282699"], - [1720136948, "36.626102399547946"], - ], - } - ], - } - } - } -} +MOCK_CPU_USAGE_RESPONSE = generate_mock_metrics("cpu_usage") +MOCK_DISK_USAGE_RESPONSE = generate_mock_metrics("disk_usage") +MOCK_MEMORY_USAGE_RESPONSE = generate_mock_metrics("memory_usage") -DISKS_USAGE = """ -query TestDisksUsage { - monitoring { - disks_usage - } -} -""" +def generate_mock_query(name): + return f""" + query Query {{ + monitoring {{ + {name} + }} + }} + """ -DISKS_USAGE_WITH_OPTIONS = """ -query TestDisksUsageWithOptions($start: int, $end: int, $step: int) { - monitoring { - disks_usage(start: $start, end: $end, step: $step) - } -} -""" + +def generate_mock_query_with_options(name): + return f""" + query Query($start: int, $end: int, $step: int) {{ + monitoring {{ + {name}(start: $start, end: $end, step: $step) + }} + }} + """ @pytest.fixture @@ -162,32 +85,41 @@ def mock_cpu_usage(mocker): @pytest.fixture -def mock_disk_usage(mocker): +def mock_memory_usage(mocker): mock = mocker.patch( "selfprivacy_api.utils.PrometheusQueries._sent_query", - return_value=MOCK_DISKS_USAGE_RESPONSE["data"]["monitoring"]["disk_usage"], + return_value=MOCK_MEMORY_USAGE_RESPONSE["data"]["monitoring"]["memory_usage"], ) return mock -def test_graphql_get_disks_usage(client, authorized_client, mock_disk_usage): +@pytest.fixture +def mock_disk_usage(mocker): + mock = mocker.patch( + "selfprivacy_api.utils.PrometheusQueries._sent_query", + return_value=MOCK_DISK_USAGE_RESPONSE["data"]["monitoring"]["disk_usage"], + ) + return mock + + +def test_graphql_get_disk_usage(client, authorized_client, mock_disk_usage): response = authorized_client.post( "/graphql", - json={"query": DISKS_USAGE}, + json={"query": generate_mock_query("disk_usage")}, ) data = get_data(response) assert_ok(data) - assert data["data"] == MOCK_DISKS_USAGE_RESPONSE["data"] + assert data["data"] == MOCK_DISK_USAGE_RESPONSE["data"] -def test_graphql_get_disks_usage_with_options( +def test_graphql_get_disk_usage_with_options( client, authorized_client, mock_disk_usage ): response = authorized_client.post( "/graphql", json={ - "query": DISKS_USAGE_WITH_OPTIONS, + "query": generate_mock_query_with_options("disk_usage"), "variables": { "start": 1720136108, "end": 1720137319, @@ -198,12 +130,88 @@ def test_graphql_get_disks_usage_with_options( data = get_data(response) assert_ok(data) - assert data["data"] == MOCK_DISKS_USAGE_RESPONSE["data"] + assert data["data"] == MOCK_DISK_USAGE_RESPONSE["data"] -def test_graphql_get_disks_usage_unauthorized(client): +def test_graphql_get_disk_usage_unauthorized(client): response = client.post( "/graphql", - json={"query": DISKS_USAGE}, + json={"query": generate_mock_query("disk_usage")}, + ) + assert_empty(response) + + +def test_graphql_get_memory_usage(client, authorized_client, mock_memory_usage): + response = authorized_client.post( + "/graphql", + json={"query": generate_mock_query("memory_usage")}, + ) + + data = get_data(response) + assert_ok(data) + assert data["data"] == MOCK_MEMORY_USAGE_RESPONSE["data"] + + +def test_graphql_get_memory_usage_with_options( + client, authorized_client, mock_memory_usage +): + response = authorized_client.post( + "/graphql", + json={ + "query": generate_mock_query_with_options("memory_usage"), + "variables": { + "start": 1720136108, + "end": 1720137319, + "step": 90, + }, + }, + ) + + data = get_data(response) + assert_ok(data) + assert data["data"] == MOCK_MEMORY_USAGE_RESPONSE["data"] + + +def test_graphql_get_memory_usage_unauthorized(client): + response = client.post( + "/graphql", + json={"query": generate_mock_query("memory_usage")}, + ) + assert_empty(response) + + +def test_graphql_get_cpu_usage(client, authorized_client, mock_cpu_usage): + response = authorized_client.post( + "/graphql", + json={"query": generate_mock_query("cpu_usage")}, + ) + + data = get_data(response) + assert_ok(data) + assert data["data"] == MOCK_CPU_USAGE_RESPONSE["data"] + + +def test_graphql_get_cpu_usage_with_options(client, authorized_client, mock_cpu_usage): + response = authorized_client.post( + "/graphql", + json={ + "query": generate_mock_query_with_options("cpu_usage"), + "variables": { + "start": 1720136108, + "end": 1720137319, + "step": 90, + }, + }, + ) + + data = get_data(response) + assert_ok(data) + assert data["data"] == MOCK_CPU_USAGE_RESPONSE["data"] + + +def test_graphql_get_cpu_usage_unauthorized(client): + response = client.post( + "/graphql", + json={"query": generate_mock_query("cpu_usage")}, ) assert_empty(response)