feature: Simplest utilities for logging

This commit is contained in:
Arbion Halili
2025-07-02 22:13:42 +01:00
parent 40793f1d86
commit 7dd8a979d2
3 changed files with 39 additions and 17 deletions

View File

@@ -1,21 +1,48 @@
import logging
import logging.handlers
from collections.abc import Sequence
from collections.abc import Sequence, Set
from enum import Enum
from queue import Queue
from pydantic import BaseModel
from rich.logging import RichHandler
class LogEntryType(str, Enum):
telemetry = "telemetry"
metrics = "metrics"
cluster = "cluster"
class LogEntry(BaseModel):
event_type: Set[LogEntryType]
class LogFilterByType(logging.Filter):
def __init__(self, log_types: Set[LogEntryType]):
super().__init__()
self.log_types = log_types
def filter(self, record: logging.LogRecord) -> bool:
message = record.getMessage()
LogEntry.model_validate_json(message)
return True
def configure_logger(
logger_name: str,
log_level: int = logging.INFO,
effect_handlers: Sequence[logging.Handler] | None = None,
) -> logging.Logger:
existing_logger = logging.Logger.manager.loggerDict.get(logger_name)
if existing_logger is not None:
raise RuntimeError(f"Logger with name '{logger_name}' already exists.")
logger = logging.getLogger(logger_name)
logger.setLevel(log_level)
logger.propagate = False
logging.raiseExceptions = True
# If the named logger already has handlers, we assume it has been configured.
if logger.hasHandlers():
return logger
@@ -33,13 +60,20 @@ def configure_logger(
return logger
def attach_to_queue(logger: logging.Logger, queue: Queue[logging.LogRecord]) -> None:
logger.addHandler(logging.handlers.QueueHandler(queue))
def attach_to_queue(
logger: logging.Logger,
filter_with: Sequence[logging.Filter],
queue: Queue[logging.LogRecord],
) -> None:
handler = logging.handlers.QueueHandler(queue)
for log_filter in filter_with:
handler.addFilter(log_filter)
logger.addHandler(handler)
def create_queue_listener(
log_queue: Queue[logging.LogRecord],
effect_handlers: list[logging.Handler],
effect_handlers: Sequence[logging.Handler],
) -> logging.handlers.QueueListener:
listener = logging.handlers.QueueListener(
log_queue, *effect_handlers, respect_handler_level=True

View File

@@ -10,7 +10,6 @@ dependencies = [
"protobuf>=6.31.1",
"pydantic>=2.11.7",
"rich>=14.0.0",
"structlog>=25.4.0",
]
[build-system]

11
uv.lock generated
View File

@@ -141,7 +141,6 @@ dependencies = [
{ name = "protobuf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
{ name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
{ name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
{ name = "structlog", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
]
[package.dev-dependencies]
@@ -156,7 +155,6 @@ requires-dist = [
{ name = "protobuf", specifier = ">=6.31.1" },
{ name = "pydantic", specifier = ">=2.11.7" },
{ name = "rich", specifier = ">=14.0.0" },
{ name = "structlog", specifier = ">=25.4.0" },
]
[package.metadata.requires-dev]
@@ -488,15 +486,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
]
[[package]]
name = "structlog"
version = "25.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/79/b9/6e672db4fec07349e7a8a8172c1a6ae235c58679ca29c3f86a61b5e59ff3/structlog-25.4.0.tar.gz", hash = "sha256:186cd1b0a8ae762e29417095664adf1d6a31702160a46dacb7796ea82f7409e4", size = 1369138, upload-time = "2025-06-02T08:21:12.971Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a0/4a/97ee6973e3a73c74c8120d59829c3861ea52210667ec3e7a16045c62b64d/structlog-25.4.0-py3-none-any.whl", hash = "sha256:fe809ff5c27e557d14e613f45ca441aabda051d119ee5a0102aaba6ce40eed2c", size = 68720, upload-time = "2025-06-02T08:21:11.43Z" },
]
[[package]]
name = "tqdm"
version = "4.67.1"