From 2c451693abd886cee180828513fead5726c51ad5 Mon Sep 17 00:00:00 2001 From: Juro Oravec Date: Wed, 17 Apr 2024 11:17:06 +0200 Subject: [PATCH] refactor: add TRACE log level --- src/django_components/logger.py | 64 +++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/src/django_components/logger.py b/src/django_components/logger.py index 9c4d547d..4dfdb56d 100644 --- a/src/django_components/logger.py +++ b/src/django_components/logger.py @@ -1,7 +1,64 @@ import logging -from typing import Literal, Optional +import sys +from typing import Any, Dict, Literal, Optional + +DEFAULT_TRACE_LEVEL_NUM = 5 # NOTE: MUST be lower than DEBUG which is 10 logger = logging.getLogger("django_components") +actual_trace_level_num = -1 + + +def setup_logging() -> None: + # Check if "TRACE" level was already defined. And if so, use its log level. + # See https://docs.python.org/3/howto/logging.html#custom-levels + global actual_trace_level_num + log_levels = _get_log_levels() + + if "TRACE" in log_levels: + actual_trace_level_num = log_levels["TRACE"] + else: + actual_trace_level_num = DEFAULT_TRACE_LEVEL_NUM + logging.addLevelName(actual_trace_level_num, "TRACE") + + +def _get_log_levels() -> Dict[str, int]: + # Use official API if possible + if sys.version_info >= (3, 11): + return logging.getLevelNamesMapping() + else: + return logging._nameToLevel.copy() + + +def trace(logger: logging.Logger, message: str, *args: Any, **kwargs: Any) -> None: + """ + TRACE level logger. + + To display TRACE logs, set the logging level to 5. + + Example: + ```py + LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "stream": sys.stdout, + }, + }, + "loggers": { + "django_components": { + "level": 5, + "handlers": ["console"], + }, + }, + } + ``` + """ + if actual_trace_level_num == -1: + setup_logging() + if logger.isEnabledFor(actual_trace_level_num): + logger.log(actual_trace_level_num, message, *args, **kwargs) def trace_msg( @@ -13,7 +70,8 @@ def trace_msg( component_id: Optional[str] = None, ) -> None: """ - Log a tracing statement to `logger.debug` like so: + TRACE level logger with opinionated format for tracing interaction of components, + nodes, and slots. Formats messages like so: `"ASSOC SLOT test_slot ID 0088 TO COMP 0087"` """ @@ -32,4 +90,4 @@ def trace_msg( # NOTE: When debugging tests during development, it may be easier to change # this to `print()` - logger.debug(full_msg) + trace(logger, full_msg)