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:
@@ -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
@@ -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"""
|
||||
|
||||
Reference in New Issue
Block a user