From 2abcdab8b649ff954ce4b94857ceb4ba3fc66451 Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Sun, 9 Mar 2025 04:42:01 +0200 Subject: [PATCH] generate process identifier for child proocesses --- src/ahriman/core/log/http_log_handler.py | 3 ++ src/ahriman/models/log_record_id.py | 36 ++++++++++++++++--- tests/ahriman/core/status/test_web_client.py | 4 +-- tests/ahriman/models/test_log_record_id.py | 19 ++++++++++ .../v2/packages/test_view_v2_packages_logs.py | 8 +++-- 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/ahriman/core/log/http_log_handler.py b/src/ahriman/core/log/http_log_handler.py index 18b67d83..bb90f1a8 100644 --- a/src/ahriman/core/log/http_log_handler.py +++ b/src/ahriman/core/log/http_log_handler.py @@ -19,12 +19,14 @@ # import atexit import logging +import uuid from typing import Self from ahriman.core.configuration import Configuration from ahriman.core.status import Client from ahriman.models.log_record import LogRecord +from ahriman.models.log_record_id import LogRecordId from ahriman.models.repository_id import RepositoryId @@ -80,6 +82,7 @@ class HttpLogHandler(logging.Handler): handler = cls(repository_id, configuration, report=report, suppress_errors=suppress_errors) root.addHandler(handler) + LogRecordId.DEFAULT_PROCESS_ID = str(uuid.uuid4()) # assign default process identifier for log records atexit.register(handler.rotate) return handler diff --git a/src/ahriman/models/log_record_id.py b/src/ahriman/models/log_record_id.py index c7399ef8..d4917c4f 100644 --- a/src/ahriman/models/log_record_id.py +++ b/src/ahriman/models/log_record_id.py @@ -19,7 +19,8 @@ # import uuid -from dataclasses import dataclass, field +from dataclasses import dataclass +from typing import Any, ClassVar @dataclass(frozen=True) @@ -30,12 +31,37 @@ class LogRecordId: Attributes: package_base(str): package base for which log record belongs version(str): package version for which log record belongs - process_id(str, optional): unique process identifier + _process_id(str | None, optional): unique process identifier """ package_base: str version: str + _process_id: str | None = None - # this is not mistake, this value is kind of global identifier, which is generated - # upon the process start - process_id: str = field(default=str(uuid.uuid4())) + DEFAULT_PROCESS_ID: ClassVar[str] = str(uuid.uuid4()) + + @property + def process_id(self) -> str: + """ + unique process identifier + + Returns: + str: process identifier as set + """ + return self._process_id or self.DEFAULT_PROCESS_ID + + def __eq__(self, other: Any) -> bool: + """ + check if other is the same object + + Args: + other(Any): other object instance + + Returns: + bool: ``True`` if the other object is the same and ``False`` otherwise + """ + if not isinstance(other, LogRecordId): + return False + return self.package_base == other.package_base \ + and self.version == other.version \ + and self.process_id == other.process_id diff --git a/tests/ahriman/core/status/test_web_client.py b/tests/ahriman/core/status/test_web_client.py index f2110464..f925049a 100644 --- a/tests/ahriman/core/status/test_web_client.py +++ b/tests/ahriman/core/status/test_web_client.py @@ -603,7 +603,7 @@ def test_package_logs_add(web_client: WebClient, log_record: logging.LogRecord, payload = { "created": log_record.created, "message": log_record.getMessage(), - "process_id": LogRecordId.process_id, + "process_id": LogRecordId.DEFAULT_PROCESS_ID, "version": package_ahriman.version, } record = LogRecord(LogRecordId(package_ahriman.base, package_ahriman.version), @@ -650,7 +650,7 @@ def test_package_logs_get(web_client: WebClient, package_ahriman: Package, mocke "created": 42.0, "message": "log", "version": package_ahriman.version, - "process_id": LogRecordId.process_id, + "process_id": LogRecordId.DEFAULT_PROCESS_ID, } response_obj = requests.Response() response_obj._content = json.dumps([message]).encode("utf8") diff --git a/tests/ahriman/models/test_log_record_id.py b/tests/ahriman/models/test_log_record_id.py index e69de29b..47680699 100644 --- a/tests/ahriman/models/test_log_record_id.py +++ b/tests/ahriman/models/test_log_record_id.py @@ -0,0 +1,19 @@ +from ahriman.models.log_record_id import LogRecordId + + +def test_eq() -> None: + """ + must compare two log record identifiers + """ + record1 = LogRecordId("1", "1", "1") + assert record1 == record1 + + record2 = LogRecordId("1", "1") + assert record1 != record2 + + +def test_eq_other() -> None: + """ + must return False in case if object is not an instance of event + """ + assert LogRecordId("1", "1") != 42 diff --git a/tests/ahriman/web/views/v2/packages/test_view_v2_packages_logs.py b/tests/ahriman/web/views/v2/packages/test_view_v2_packages_logs.py index 8726fde4..4a3cb949 100644 --- a/tests/ahriman/web/views/v2/packages/test_view_v2_packages_logs.py +++ b/tests/ahriman/web/views/v2/packages/test_view_v2_packages_logs.py @@ -50,13 +50,13 @@ async def test_get(client: TestClient, package_ahriman: Package) -> None: "created": 42.0, "message": "message 1", "version": "42", - "process_id": LogRecordId.process_id, + "process_id": LogRecordId.DEFAULT_PROCESS_ID, }, { "created": 43.0, "message": "message 2", "version": "42", - "process_id": LogRecordId.process_id, + "process_id": LogRecordId.DEFAULT_PROCESS_ID, }, ] @@ -81,7 +81,9 @@ async def test_get_with_pagination(client: TestClient, package_ahriman: Package) logs = await response.json() assert not response_schema.validate(logs) - assert logs == [{"created": 42.0, "message": "message 1", "version": "42", "process_id": LogRecordId.process_id}] + assert logs == [ + {"created": 42.0, "message": "message 1", "version": "42", "process_id": LogRecordId.DEFAULT_PROCESS_ID}, + ] async def test_get_bad_request(client: TestClient, package_ahriman: Package) -> None: