refactor(logging): reformat log output, adjust stacklevel and field widths

- Change logging stacklevel from 3 to 4 in all log helper functions
  (create_module_logger, log_debug, log_info, log_warn, log_error) to
  correctly attribute the caller location in stack output.

- Reduce level_field_width from 9 to 5 (e.g. ERROR→5 chars) and set
  source_field_width to 0 so source column auto-sizes to its content.

- Add MESSAGE color (cyan) for log message highlighting in colored output.

- Extract four helper methods from ColoredFormatter.format:
  _display_logger_name  — strips the 'azlogs.' namespace prefix
  _display_level_name   — normalises WARNING → WARN for compact display
  _format_time          — builds HH:MM:SS.mmm timestamps
  _color_level          — applies bold+color to the level token

- Simplify format() to assemble [HH:MM:SS.mmm] LVL (logger:line): message
  with the new helpers applied inline.
This commit is contained in:
Dariusz L
2026-05-19 06:44:00 +02:00
parent 0584dc819f
commit 367a6d208a
2 changed files with 38 additions and 24 deletions
+5 -5
View File
@@ -199,7 +199,7 @@ def create_module_logger(module_name=None):
def log_debug(*args, **kwargs):
module_name = _resolve_module_name(stack_depth=2)
if _initialized:
kwargs.setdefault("stacklevel", 3)
kwargs.setdefault("stacklevel", 4)
debug(module_name, *args, **kwargs)
else:
print(f"[DEBUG] [{module_name}]", *args)
@@ -208,7 +208,7 @@ def log_debug(*args, **kwargs):
def log_info(*args, **kwargs):
module_name = _resolve_module_name(stack_depth=2)
if _initialized:
kwargs.setdefault("stacklevel", 3)
kwargs.setdefault("stacklevel", 4)
info(module_name, *args, **kwargs)
else:
print(f"[INFO] [{module_name}]", *args)
@@ -217,7 +217,7 @@ def log_info(*args, **kwargs):
def log_warn(*args, **kwargs):
module_name = _resolve_module_name(stack_depth=2)
if _initialized:
kwargs.setdefault("stacklevel", 3)
kwargs.setdefault("stacklevel", 4)
warn(module_name, *args, **kwargs)
else:
print(f"[WARN] [{module_name}]", *args)
@@ -226,7 +226,7 @@ def log_warn(*args, **kwargs):
def log_error(*args, **kwargs):
module_name = _resolve_module_name(stack_depth=2)
if _initialized:
kwargs.setdefault("stacklevel", 3)
kwargs.setdefault("stacklevel", 4)
error(module_name, *args, **kwargs)
else:
print(f"[ERROR] [{module_name}]", *args)
@@ -235,7 +235,7 @@ def log_error(*args, **kwargs):
def log_exception(*args):
module_name = _resolve_module_name(stack_depth=2)
if _initialized:
exception(module_name, *args, stacklevel=3)
exception(module_name, *args, stacklevel=4)
else:
print(f"[ERROR] [{module_name}]", *args)
traceback.print_exc()
+33 -19
View File
@@ -17,6 +17,7 @@ import sys
import json
import re
import logging
import time
from enum import IntEnum
from logging.handlers import RotatingFileHandler
import traceback
@@ -46,6 +47,7 @@ COLORS = {
LogLevel.INFO: "\033[94m", # Blue
LogLevel.WARN: "\033[93m", # Yellow
LogLevel.ERROR: "\033[91m", # Red
"MESSAGE": "\033[96m", # Cyan
"RESET": "\033[0m", # Reset
}
@@ -59,8 +61,8 @@ DEFAULT_CONFIG = {
"max_file_size_mb": 10,
"backup_count": 5,
"timestamp_format": "%H:%M:%S",
"level_field_width": 9,
"source_field_width": 72,
"level_field_width": 5,
"source_field_width": 0,
}
@@ -86,25 +88,18 @@ class ColoredFormatter(logging.Formatter):
if record.exc_info:
message += "\n" + self.formatException(record.exc_info)
levelname = record.levelname
level = f"[{levelname}]".center(self.level_field_width)
source = f"[{record.name}:{record.lineno}]".ljust(self.source_field_width)
levelname = self._display_level_name(record.levelname)
level = levelname.ljust(self.level_field_width)
logger_name = self._display_logger_name(record.name)
source = f"({logger_name}:{record.lineno})"
if self.source_field_width:
source = source.ljust(self.source_field_width)
# Build the log prefix
prefix = "[{}] {} {}".format(
self.formatTime(record, self.datefmt),
level,
source,
)
if self.use_colors:
level = self._color_level(levelname, level)
message = f"{COLORS['MESSAGE']}{message}{COLORS['RESET']}"
# Apply color and bold styling to the prefix
if self.use_colors and hasattr(LogLevel, levelname):
level_enum = getattr(LogLevel, levelname)
if level_enum in COLORS:
# Apply bold (\033[1m) and color, then reset
prefix = f"\033[1m{COLORS[level_enum]}{prefix}{COLORS['RESET']}"
return f"{prefix} {message}"
return f"[{self._format_time(record)}] {level} {source}: {message}"
def _field_width(self, value):
try:
@@ -112,6 +107,25 @@ class ColoredFormatter(logging.Formatter):
except (TypeError, ValueError):
return 0
def _display_logger_name(self, name):
return str(name or "").removeprefix("azlogs.")
def _display_level_name(self, levelname):
return "WARN" if levelname == "WARNING" else str(levelname or "")
def _format_time(self, record):
timestamp = time.strftime(
self.datefmt or "%H:%M:%S", self.converter(record.created)
)
return f"{timestamp}.{int(record.msecs):03d}"
def _color_level(self, levelname, text):
level_enum = getattr(LogLevel, levelname, None)
color = COLORS.get(level_enum)
if not color:
return text
return f"\033[1m{color}{text}{COLORS['RESET']}"
class AzLogsLogger:
"""Main logger class for AzLogs"""