|
| 1 | +"""Custom logger.""" |
| 2 | + |
| 3 | +import json |
| 4 | +from os import path |
| 5 | +from sys import stdout |
| 6 | + |
| 7 | +from loguru import logger |
| 8 | + |
| 9 | +from config import settings |
| 10 | + |
| 11 | + |
| 12 | +def json_formatter(record: dict) -> str: |
| 13 | + """ |
| 14 | + Pass raw log to be serialized. |
| 15 | +
|
| 16 | + :param dict record: Dictionary containing logged message with metadata. |
| 17 | +
|
| 18 | + :returns: str |
| 19 | + """ |
| 20 | + |
| 21 | + def serialize(log: dict) -> str: |
| 22 | + """ |
| 23 | + Parse log message into Datadog JSON format. |
| 24 | +
|
| 25 | + :param dict log: Dictionary containing logged message with metadata. |
| 26 | +
|
| 27 | + :returns: str |
| 28 | + """ |
| 29 | + subset = { |
| 30 | + "time": log["time"].strftime("%m/%d/%Y, %H:%M:%S"), |
| 31 | + "message": log["message"], |
| 32 | + "level": log["level"].name, |
| 33 | + "function": log.get("function"), |
| 34 | + "module": log.get("name"), |
| 35 | + } |
| 36 | + if log.get("exception", None): |
| 37 | + subset.update({"exception": log["exception"]}) |
| 38 | + return json.dumps(subset) |
| 39 | + |
| 40 | + record["extra"]["serialized"] = serialize(record) |
| 41 | + return "{extra[serialized]},\n" |
| 42 | + |
| 43 | + |
| 44 | +def log_formatter(record: dict) -> str: |
| 45 | + """ |
| 46 | + Formatter for .log records |
| 47 | +
|
| 48 | + :param dict record: Key/value object containing log message & metadata. |
| 49 | +
|
| 50 | + :returns: str |
| 51 | + """ |
| 52 | + if record["level"].name == "TRACE": |
| 53 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #d2eaff>{level}</fg #d2eaff>: <light-white>{message}</light-white>\n" |
| 54 | + if record["level"].name == "INFO": |
| 55 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #98bedf>{level}</fg #98bedf>: <light-white>{message}</light-white>\n" |
| 56 | + if record["level"].name == "WARNING": |
| 57 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #b09057>{level}</fg #b09057>: <light-white>{message}</light-white>\n" |
| 58 | + if record["level"].name == "SUCCESS": |
| 59 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #6dac77>{level}</fg #6dac77>: <light-white>{message}</light-white>\n" |
| 60 | + if record["level"].name == "ERROR": |
| 61 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #a35252>{level}</fg #a35252>: <light-white>{message}</light-white>\n" |
| 62 | + if record["level"].name == "CRITICAL": |
| 63 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #521010>{level}</fg #521010>: <light-white>{message}</light-white>\n" |
| 64 | + return "<fg #5278a3>{time:MM-DD-YYYY HH:mm:ss}</fg #5278a3> | <fg #98bedf>{level}</fg #98bedf>: <light-white>{message}</light-white>\n" |
| 65 | + |
| 66 | + |
| 67 | +def create_logger() -> logger: |
| 68 | + """ |
| 69 | + Configure custom logger. |
| 70 | +
|
| 71 | + :returns: logger |
| 72 | + """ |
| 73 | + logger.remove() |
| 74 | + logger.add( |
| 75 | + stdout, |
| 76 | + colorize=True, |
| 77 | + catch=True, |
| 78 | + level="TRACE", |
| 79 | + format=log_formatter, |
| 80 | + ) |
| 81 | + if settings.ENVIRONMENT == "production" and path.isdir(f"/var/log/{settings.APP_NAME}"): |
| 82 | + # Datadog JSON logs |
| 83 | + logger.add( |
| 84 | + f"/var/log/{settings.APP_NAME}/info.json", |
| 85 | + format=json_formatter, |
| 86 | + rotation="200 MB", |
| 87 | + level="TRACE", |
| 88 | + compression="zip", |
| 89 | + ) |
| 90 | + # Readable logs |
| 91 | + logger.add( |
| 92 | + f"/var/log/{settings.APP_NAME}/info.log", |
| 93 | + colorize=True, |
| 94 | + catch=True, |
| 95 | + level="TRACE", |
| 96 | + format=log_formatter, |
| 97 | + rotation="200 MB", |
| 98 | + compression="zip", |
| 99 | + ) |
| 100 | + else: |
| 101 | + logger.add( |
| 102 | + "./logs/error.log", |
| 103 | + colorize=True, |
| 104 | + catch=True, |
| 105 | + format=log_formatter, |
| 106 | + rotation="200 MB", |
| 107 | + compression="zip", |
| 108 | + level="ERROR", |
| 109 | + ) |
| 110 | + return logger |
| 111 | + |
| 112 | + |
| 113 | +# Custom logger |
| 114 | +LOGGER = create_logger() |
0 commit comments