From 348fb52db9da8337cee5965cb5cc710e12d70861 Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Mon, 31 Mar 2025 18:17:05 +0300 Subject: [PATCH 1/5] feat(metrics): add metrics module types - Create `MetricsResponse` types to handle API responses - Add support for retrieving system metrics (CPU, memory, disk, network) - Add support for Typesense-specific memory metrics - Ensure compatibility with Python 3.11+ and earlier versions --- src/typesense/metrics.py | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/typesense/metrics.py diff --git a/src/typesense/metrics.py b/src/typesense/metrics.py new file mode 100644 index 0000000..a368cb2 --- /dev/null +++ b/src/typesense/metrics.py @@ -0,0 +1,97 @@ +""" +This module provides functionality for retrieving metrics from the Typesense API. + +It contains the Metrics class, which handles API operations for retrieving +system and Typesense metrics such as CPU, memory, disk, and network usage. + +Classes: + MetricsResponse: Type definition for metrics response. + Metrics: Manages retrieving metrics from the Typesense API. + +Dependencies: + - typesense.api_call: Provides the ApiCall class for making API requests. + +Note: This module uses conditional imports to support both Python 3.11+ and earlier versions. +""" + +import sys + +if sys.version_info >= (3, 11): + import typing +else: + import typing_extensions as typing + +from typesense.api_call import ApiCall + + +class MetricsResponseBase(typing.TypedDict): + """ + Response schema for metrics retrieval. + + This TypedDict includes system metrics like CPU, memory, disk, and network usage, + as well as Typesense-specific memory metrics. + + Attributes: + system_cpu_active_percentage (str): Overall CPU active percentage. + system_disk_total_bytes (str): Total disk space in bytes. + system_disk_used_bytes (str): Used disk space in bytes. + system_memory_total_bytes (str): Total system memory in bytes. + system_memory_used_bytes (str): Used system memory in bytes. + system_network_received_bytes (str): Total network bytes received. + system_network_sent_bytes (str): Total network bytes sent. + typesense_memory_active_bytes (str): Active memory used by Typesense. + typesense_memory_allocated_bytes (str): Allocated memory for Typesense. + typesense_memory_fragmentation_ratio (str): Memory fragmentation ratio. + typesense_memory_mapped_bytes (str): Mapped memory in bytes. + typesense_memory_metadata_bytes (str): Memory used for metadata. + typesense_memory_resident_bytes (str): Resident memory in bytes. + typesense_memory_retained_bytes (str): Retained memory in bytes. + """ + + system_cpu_active_percentage: str + system_disk_total_bytes: str + system_disk_used_bytes: str + system_memory_total_bytes: str + system_memory_used_bytes: str + system_network_received_bytes: str + system_network_sent_bytes: str + typesense_memory_active_bytes: str + typesense_memory_allocated_bytes: str + typesense_memory_fragmentation_ratio: str + typesense_memory_mapped_bytes: str + typesense_memory_metadata_bytes: str + typesense_memory_resident_bytes: str + typesense_memory_retained_bytes: str + + +class MetricsResponse(MetricsResponseBase): + """Extended MetricsResponse with optional per-CPU core metrics.""" + + system_memory_total_swap_bytes: str + system_memory_used_swap_bytes: str + system_cpu1_active_percentage: typing.Optional[str] + system_cpu2_active_percentage: typing.Optional[str] + system_cpu3_active_percentage: typing.Optional[str] + system_cpu4_active_percentage: typing.Optional[str] + system_cpu5_active_percentage: typing.Optional[str] + system_cpu6_active_percentage: typing.Optional[str] + system_cpu7_active_percentage: typing.Optional[str] + system_cpu8_active_percentage: typing.Optional[str] + system_cpu9_active_percentage: typing.Optional[str] + system_cpu10_active_percentage: typing.Optional[str] + system_cpu11_active_percentage: typing.Optional[str] + system_cpu12_active_percentage: typing.Optional[str] + system_cpu13_active_percentage: typing.Optional[str] + system_cpu14_active_percentage: typing.Optional[str] + system_cpu15_active_percentage: typing.Optional[str] + system_cpu16_active_percentage: typing.Optional[str] + system_cpu17_active_percentage: typing.Optional[str] + system_cpu18_active_percentage: typing.Optional[str] + system_cpu19_active_percentage: typing.Optional[str] + system_cpu20_active_percentage: typing.Optional[str] + system_cpu21_active_percentage: typing.Optional[str] + system_cpu22_active_percentage: typing.Optional[str] + system_cpu23_active_percentage: typing.Optional[str] + system_cpu24_active_percentage: typing.Optional[str] + + From 3b8da2f03105591a9db8c3f02b03a06c693fb4bf Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Mon, 31 Mar 2025 18:17:36 +0300 Subject: [PATCH 2/5] feat(metrics): implement metrics retrieval class - Add `Metrics` class with API integration - Create method to retrieve system and Typesense metrics - Define endpoint path for metrics retrieval - Connect with existing `MetricsResponse` type --- src/typesense/metrics.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/typesense/metrics.py b/src/typesense/metrics.py index a368cb2..3b48899 100644 --- a/src/typesense/metrics.py +++ b/src/typesense/metrics.py @@ -95,3 +95,39 @@ class MetricsResponse(MetricsResponseBase): system_cpu24_active_percentage: typing.Optional[str] +class Metrics: + """ + Manages metrics retrieval from the Typesense API. + + This class provides methods to retrieve system and Typesense metrics + such as CPU, memory, disk, and network usage. + + Attributes: + resource_path (str): The base path for metrics endpoint. + api_call (ApiCall): The ApiCall instance for making API requests. + """ + + resource_path: typing.Final[str] = "/metrics.json" + + def __init__(self, api_call: ApiCall): + """ + Initialize the Metrics instance. + + Args: + api_call (ApiCall): The ApiCall instance for making API requests. + """ + self.api_call = api_call + + def retrieve(self) -> MetricsResponse: + """ + Retrieve metrics from the Typesense API. + + Returns: + MetricsResponse: A dictionary containing system and Typesense metrics. + """ + response: MetricsResponse = self.api_call.get( + Metrics.resource_path, + as_json=True, + entity_type=MetricsResponse, + ) + return response From e4f3b2bcca9591160c92fb59010d4874cd988036 Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Mon, 31 Mar 2025 18:17:50 +0300 Subject: [PATCH 3/5] feat(client): integrate metrics module with client - Import `Metrics` class in `client.py` - Add `metrics` attribute to `Client` class documentation - Initialize `metrics` instance in `Client` constructor - Update module documentation to reference metrics dependency --- src/typesense/client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/typesense/client.py b/src/typesense/client.py index dc7d09b..cde957b 100644 --- a/src/typesense/client.py +++ b/src/typesense/client.py @@ -17,6 +17,7 @@ - typesense.conversations_models: Provides the ConversationsModels class. - typesense.debug: Provides the Debug class. - typesense.keys: Provides the Keys class. + - typesense.metrics: Provides the Metrics class. - typesense.multi_search: Provides the MultiSearch class. - typesense.operations: Provides the Operations class. - typesense.stopwords: Provides the Stopwords class. @@ -43,6 +44,7 @@ from typesense.conversations_models import ConversationsModels from typesense.debug import Debug from typesense.keys import Keys +from typesense.metrics import Metrics from typesense.multi_search import MultiSearch from typesense.operations import Operations from typesense.stemming import Stemming @@ -72,6 +74,7 @@ class Client: operations (Operations): Instance for various Typesense operations. debug (Debug): Instance for debug operations. stopwords (Stopwords): Instance for managing stopwords. + metrics (Metrics): Instance for retrieving system and Typesense metrics. conversations_models (ConversationsModels): Instance for managing conversation models. """ @@ -102,6 +105,7 @@ def __init__(self, config_dict: ConfigDict) -> None: self.operations = Operations(self.api_call) self.debug = Debug(self.api_call) self.stopwords = Stopwords(self.api_call) + self.metrics = Metrics(self.api_call) self.conversations_models = ConversationsModels(self.api_call) def typed_collection( From cc039f3915a31d5a0fc8bf00500180c6004a4c58 Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Mon, 31 Mar 2025 18:18:02 +0300 Subject: [PATCH 4/5] test(metrics): add test fixtures for metrics module - Create `metrics_fixtures.py` with pytest fixture - Set up fixture to return a `Metrics` object with actual API call - Configure fixture with function scope for isolated testing --- tests/fixtures/metrics_fixtures.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/fixtures/metrics_fixtures.py diff --git a/tests/fixtures/metrics_fixtures.py b/tests/fixtures/metrics_fixtures.py new file mode 100644 index 0000000..7da5bc2 --- /dev/null +++ b/tests/fixtures/metrics_fixtures.py @@ -0,0 +1,12 @@ +"""Fixtures for the Metrics class tests.""" + +import pytest + +from typesense.api_call import ApiCall +from typesense.metrics import Metrics + + +@pytest.fixture(scope="function", name="actual_metrics") +def actual_debug_fixture(actual_api_call: ApiCall) -> Metrics: + """Return a Debug object using a real API.""" + return Metrics(actual_api_call) From 50ac673299a0f15eeaf4e4d25a8fe8fce25b9cf2 Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Mon, 31 Mar 2025 18:18:13 +0300 Subject: [PATCH 5/5] test(metrics): add integration tests for metrics retrieval - Create `metrics_test.py` to test the `Metrics` class - Implement test for the `retrieve()` method - Verify all expected system metrics fields are p --- tests/metrics_test.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/metrics_test.py diff --git a/tests/metrics_test.py b/tests/metrics_test.py new file mode 100644 index 0000000..1e1ea47 --- /dev/null +++ b/tests/metrics_test.py @@ -0,0 +1,26 @@ +"""Tests for the Debug class.""" + +from __future__ import annotations + +from typesense.metrics import Metrics + + +def test_actual_retrieve(actual_metrics: Metrics) -> None: + """Test that the Debug object can retrieve a debug on Typesense server and verify response structure.""" + response = actual_metrics.retrieve() + + assert "system_cpu_active_percentage" in response + assert "system_disk_total_bytes" in response + assert "system_disk_used_bytes" in response + assert "system_memory_total_bytes" in response + assert "system_memory_used_bytes" in response + assert "system_network_received_bytes" in response + assert "system_network_sent_bytes" in response + assert "typesense_memory_active_bytes" in response + assert "typesense_memory_allocated_bytes" in response + assert "typesense_memory_fragmentation_ratio" in response + + assert "typesense_memory_mapped_bytes" in response + assert "typesense_memory_metadata_bytes" in response + assert "typesense_memory_resident_bytes" in response + assert "typesense_memory_retained_bytes" in response \ No newline at end of file