Coverage for functions \ flipdare \ util \ app_log_formatter.py: 100%

0 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-05-08 12:22 +1000

1#!/usr/bin/env python 

2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved. 

3# 

4# This file is part of Flipdare's proprietary software and contains 

5# confidential and copyrighted material. Unauthorised copying, 

6# modification, distribution, or use of this file is strictly 

7# prohibited without prior written permission from Flipdare Pty Ltd. 

8# 

9# This software includes third-party components licensed under MIT, 

10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details. 

11# 

12 

13 

14import logging 

15from typing import override 

16from pathlib import Path 

17from flipdare.util.ansi_codes import AnsiCodes 

18 

19_LOG_FORMAT = "[%(levelname)5s %(asctime)s] %(relpath)s:%(lineno)d:%(funcName)s - %(message)s" 

20 

21_DATE_FORMAT = "%M:%S" 

22 

23_C = AnsiCodes 

24 

25# 5 - TRACE, 10 - DEBUG, 20 - INFO, 30 - WARNING, 40 - ERROR, 50 - CRITICAL 

26TRACE_LEVEL = 5 # Custom log level for trace, below DEBUG (10) 

27PERFORMANCE_LEVEL = 60 # Custom log level for performance (60), since important... 

28 

29 

30class AppLogFormatter(logging.Formatter): # pragma: no cover 

31 

32 def __init__(self) -> None: 

33 

34 super().__init__(fmt=_LOG_FORMAT, datefmt=_DATE_FORMAT) 

35 # Pre-create formatters for each level to ensure thread safety 

36 self.project_root = Path.cwd() 

37 self.formatters = { 

38 logging.DEBUG: logging.Formatter( 

39 _C.LIGHT_BLUE + _LOG_FORMAT + _C.RESET_COLOR, 

40 _DATE_FORMAT, 

41 ), 

42 logging.INFO: logging.Formatter( 

43 _C.LIGHT_GREEN + _LOG_FORMAT + _C.RESET_COLOR, 

44 _DATE_FORMAT, 

45 ), 

46 logging.WARNING: logging.Formatter( 

47 _C.ORANGE + _LOG_FORMAT + _C.RESET_COLOR, 

48 _DATE_FORMAT, 

49 ), 

50 logging.ERROR: logging.Formatter(_C.RED + _LOG_FORMAT + _C.RESET_COLOR, _DATE_FORMAT), 

51 logging.CRITICAL: logging.Formatter( 

52 _C.LIGHT_PURPLE + _LOG_FORMAT + _C.RESET_COLOR, 

53 _DATE_FORMAT, 

54 ), 

55 TRACE_LEVEL: logging.Formatter( 

56 _C.GRAY + _LOG_FORMAT + _C.RESET_COLOR, 

57 _DATE_FORMAT, 

58 ), 

59 PERFORMANCE_LEVEL: logging.Formatter( 

60 _C.YELLOW + _LOG_FORMAT + _C.RESET_COLOR, 

61 _DATE_FORMAT, 

62 ), 

63 } 

64 

65 # @override 

66 # def formatException(self, ei: Any) -> str: 

67 # # Get the standard formatted traceback string 

68 # result = super().formatException(ei) 

69 # # Wrap it in your custom markers 

70 # return f"\n---Begin Stack Trace---\n{result}\n---End Stack Trace ---\n\n" 

71 

72 @override 

73 def format(self, record: logging.LogRecord) -> str: 

74 # 1. Tweak level names directly on the record before formatting 

75 # This is safer than string replacement on the final message 

76 if record.levelname == "WARNING": 

77 record.levelname = " WARN" 

78 

79 rel_path = Path(record.pathname).relative_to(self.project_root) 

80 # record.relpath = f"./{rel_path}" if not str(rel_path).startswith(".") else str(rel_path) 

81 record.relpath = rel_path 

82 # 2. Select the pre-configured formatter 

83 formatter = self.formatters.get(record.levelno, self) 

84 

85 # 3. Use the selected formatter to get the final string 

86 return formatter.format(record)