agency.logger

 1import json
 2import logging
 3import os
 4import traceback
 5
 6import colorlog
 7from colorlog.escape_codes import escape_codes
 8from pygments import highlight
 9from pygments.formatters import Terminal256Formatter
10from pygments.lexers import get_lexer_by_name
11
12_LOGLEVELS = {
13    'CRITICAL': 50,
14    'ERROR': 40,
15    'WARNING': 30,
16    'INFO': 20,
17    'DEBUG': 10,
18    'NOTSET': 0
19}
20
21_env_loglevel = os.environ.get('LOGLEVEL', 'WARNING').upper()
22_LOGLEVEL = _LOGLEVELS[_env_loglevel]
23_LOGFORMAT = '%(asctime_color)s%(asctime)s%(reset_color)s - %(levelname_color)s%(levelname)s%(reset_color)s - %(message_color)s%(message)s%(reset_color)s%(object_color)s%(object)s%(reset_color)s'
24_LOG_PYGMENTS_STYLE = os.environ.get('LOG_PYGMENTS_STYLE', 'monokai')
25
26
27class CustomColoredFormatter(colorlog.ColoredFormatter):
28    def format(self, record):
29        record.reset_color = escape_codes['reset']
30        record.asctime_color = escape_codes['light_black']
31        record.levelname_color = escape_codes[self.log_colors[record.levelname]]
32        record.message_color = escape_codes['reset']
33        record.object_color = escape_codes['reset']
34
35        return super().format(record)
36
37
38_logger = logging.getLogger("agency")
39_logger.setLevel(_LOGLEVEL)
40_handler = logging.StreamHandler()
41_handler.setLevel(_LOGLEVEL)
42
43_formatter = CustomColoredFormatter(
44    _LOGFORMAT,
45    log_colors={
46        'CRITICAL': 'bold_red',
47        'ERROR': 'red',
48        'WARNING': 'yellow',
49        'INFO': 'green',
50        'DEBUG': 'cyan',
51    }
52)
53
54_handler.setFormatter(_formatter)
55_logger.addHandler(_handler)
56
57
58class _CustomEncoder(json.JSONEncoder):
59    def default(self, obj):
60        try:
61            return super().default(obj)
62        except TypeError:
63            return str(obj)
64
65
66def log(level: str, message: str, object=None):
67    pretty_object: str = ""
68    if object != None:
69        try:
70            if isinstance(object, Exception):
71                pretty_object = "\n" + "".join(traceback.format_exception(
72                    etype=type(object), value=object, tb=object.__traceback__))
73            else:
74                json_str = json.dumps(object, indent=2, cls=_CustomEncoder)
75                pretty_object = "\n" + \
76                    highlight(json_str, get_lexer_by_name('json'),
77                              Terminal256Formatter(style=_LOG_PYGMENTS_STYLE))
78        except:
79            pass
80
81    numeric_level = _LOGLEVELS.get(level.upper())
82    if numeric_level is not None:
83        _logger.log(numeric_level, message, extra={'object': pretty_object})
84    else:
85        raise ValueError(f"Invalid log level: {level}")
class CustomColoredFormatter(colorlog.formatter.ColoredFormatter):
28class CustomColoredFormatter(colorlog.ColoredFormatter):
29    def format(self, record):
30        record.reset_color = escape_codes['reset']
31        record.asctime_color = escape_codes['light_black']
32        record.levelname_color = escape_codes[self.log_colors[record.levelname]]
33        record.message_color = escape_codes['reset']
34        record.object_color = escape_codes['reset']
35
36        return super().format(record)

A formatter that allows colors to be placed in the format string.

Intended to help in creating more readable logging output.

def format(self, record):
29    def format(self, record):
30        record.reset_color = escape_codes['reset']
31        record.asctime_color = escape_codes['light_black']
32        record.levelname_color = escape_codes[self.log_colors[record.levelname]]
33        record.message_color = escape_codes['reset']
34        record.object_color = escape_codes['reset']
35
36        return super().format(record)

Format the specified record as text.

The record's attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Inherited Members
colorlog.formatter.ColoredFormatter
ColoredFormatter
log_colors
secondary_log_colors
reset
stream
no_color
force_color
formatMessage
logging.Formatter
converter
datefmt
default_time_format
default_msec_format
formatTime
formatException
usesTime
formatStack
def log(level: str, message: str, object=None):
67def log(level: str, message: str, object=None):
68    pretty_object: str = ""
69    if object != None:
70        try:
71            if isinstance(object, Exception):
72                pretty_object = "\n" + "".join(traceback.format_exception(
73                    etype=type(object), value=object, tb=object.__traceback__))
74            else:
75                json_str = json.dumps(object, indent=2, cls=_CustomEncoder)
76                pretty_object = "\n" + \
77                    highlight(json_str, get_lexer_by_name('json'),
78                              Terminal256Formatter(style=_LOG_PYGMENTS_STYLE))
79        except:
80            pass
81
82    numeric_level = _LOGLEVELS.get(level.upper())
83    if numeric_level is not None:
84        _logger.log(numeric_level, message, extra={'object': pretty_object})
85    else:
86        raise ValueError(f"Invalid log level: {level}")