generate process identifier for child proocesses

This commit is contained in:
Evgenii Alekseev 2025-03-09 04:42:01 +02:00
parent 631e572d60
commit 2abcdab8b6
5 changed files with 60 additions and 10 deletions

View File

@ -19,12 +19,14 @@
# #
import atexit import atexit
import logging import logging
import uuid
from typing import Self from typing import Self
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.status import Client from ahriman.core.status import Client
from ahriman.models.log_record import LogRecord from ahriman.models.log_record import LogRecord
from ahriman.models.log_record_id import LogRecordId
from ahriman.models.repository_id import RepositoryId 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) handler = cls(repository_id, configuration, report=report, suppress_errors=suppress_errors)
root.addHandler(handler) root.addHandler(handler)
LogRecordId.DEFAULT_PROCESS_ID = str(uuid.uuid4()) # assign default process identifier for log records
atexit.register(handler.rotate) atexit.register(handler.rotate)
return handler return handler

View File

@ -19,7 +19,8 @@
# #
import uuid import uuid
from dataclasses import dataclass, field from dataclasses import dataclass
from typing import Any, ClassVar
@dataclass(frozen=True) @dataclass(frozen=True)
@ -30,12 +31,37 @@ class LogRecordId:
Attributes: Attributes:
package_base(str): package base for which log record belongs package_base(str): package base for which log record belongs
version(str): package version 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 package_base: str
version: str version: str
_process_id: str | None = None
# this is not mistake, this value is kind of global identifier, which is generated DEFAULT_PROCESS_ID: ClassVar[str] = str(uuid.uuid4())
# upon the process start
process_id: str = field(default=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

View File

@ -603,7 +603,7 @@ def test_package_logs_add(web_client: WebClient, log_record: logging.LogRecord,
payload = { payload = {
"created": log_record.created, "created": log_record.created,
"message": log_record.getMessage(), "message": log_record.getMessage(),
"process_id": LogRecordId.process_id, "process_id": LogRecordId.DEFAULT_PROCESS_ID,
"version": package_ahriman.version, "version": package_ahriman.version,
} }
record = LogRecord(LogRecordId(package_ahriman.base, 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, "created": 42.0,
"message": "log", "message": "log",
"version": package_ahriman.version, "version": package_ahriman.version,
"process_id": LogRecordId.process_id, "process_id": LogRecordId.DEFAULT_PROCESS_ID,
} }
response_obj = requests.Response() response_obj = requests.Response()
response_obj._content = json.dumps([message]).encode("utf8") response_obj._content = json.dumps([message]).encode("utf8")

View File

@ -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

View File

@ -50,13 +50,13 @@ async def test_get(client: TestClient, package_ahriman: Package) -> None:
"created": 42.0, "created": 42.0,
"message": "message 1", "message": "message 1",
"version": "42", "version": "42",
"process_id": LogRecordId.process_id, "process_id": LogRecordId.DEFAULT_PROCESS_ID,
}, },
{ {
"created": 43.0, "created": 43.0,
"message": "message 2", "message": "message 2",
"version": "42", "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() logs = await response.json()
assert not response_schema.validate(logs) 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: async def test_get_bad_request(client: TestClient, package_ahriman: Package) -> None: