🎨

Djangoでログの色を変える方法

2024/11/26に公開

Djangoのログって、nodeなどと比べて、一色でレベルがわかりづらくないですか?
ということで、ログをカラフルにしてみます。

LOGGING設定

settings.pyに直で書いても良いですが、長くなるので、今回はモジュールに分けます。
ちなみに、デフォルトのLOGGINGdjango.utils.logにあります。

(プロジェクト名)/(プロジェクト名)/logging_settings.py
from abc import ABCMeta, abstractmethod
import logging


LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse",
        },
        "require_debug_true": {
            "()": "django.utils.log.RequireDebugTrue",
        },
    },
    "formatters": {
        "django.server": {
            "()": "django.utils.log.ServerFormatter",
            "format": "[{server_time}] {message}",
            "style": "{",
        },
        "verbose": {
            "format": (
                "[%(asctime)s] %(levelname)s "  # cspell:disable-line
                "[%(name)s:%(lineno)s] %(message)s"
            ),
            "datefmt": "%d/%b/%Y %H:%M:%S",
        },
        "color_verbose": {
            "()": "lets_pirouette.logging_settings.ColorVerboseLogFormat",
            "datefmt": "%d/%b/%Y %H:%M:%S",
        },
        "lite": {
            "()": "lets_pirouette.logging_settings.LiteLogFormat",
            "datefmt": "%d/%b/%Y %H:%M:%S",
        },
    },
    "handlers": {
        "console": {
            "level": "INFO",
            # "filters": ["require_debug_false"],
            "class": "logging.StreamHandler",
            "formatter": "color_verbose",
        },
        "django.server": {
            "level": "INFO",
            "class": "logging.StreamHandler",
            "formatter": "django.server",
        },
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler",
        },
        "file": {
            "level": "DEBUG",
            "filters": ["require_debug_false"],
            "class": "logging.FileHandler",
            "filename": "log_file.log",
            "formatter": "lite",
        },
    },
    "loggers": {
        "django": {
            "handlers": [
                "console",
                "mail_admins",
                "file",
            ],
            "level": "DEBUG",
        },
        "django.server": {
            "handlers": [
                "console",
                "django.server",
                "file",
            ],
            "level": "DEBUG",
            "propagate": False,
        },
        "livereload.middleware": {
            "handlers": ["console", "django.server"],
            "level": "DEBUG",
            # "propagate": False,
        },
    },
}

class Test:
    @property
    def test1():
        return "hello"
    
    test2 = test1 + " world"

class AbstractColorLogFormat(logging.Formatter, metaclass=ABCMeta):

    blue = "\033[34m"
    cyan = "\033[36m"
    yellow = "\033[33m"
    magenta = "\033[35m"
    red = "\033[31m"
    reset = "\033[0m"
    # format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"

    @property
    @abstractmethod
    def formatStr(self) -> str:
        return "[%(name)s:%(lineno)s](%(levelname)s) %(message)s"

    @property
    def FORMATS(self):
        return {
            logging.DEBUG: self.blue + self.formatStr + self.reset,
            logging.INFO: self.cyan + self.formatStr + self.reset,
            logging.WARNING: self.yellow + self.formatStr + self.reset,
            logging.ERROR: self.magenta + self.formatStr + self.reset,
            logging.CRITICAL: self.red + self.formatStr + self.reset,
        }

    def format(self, record):
        log_fmt = self.FORMATS.get(record.levelno)
        formatter = logging.Formatter(log_fmt)
        return formatter.format(record)


class ColorVerboseLogFormat(AbstractColorLogFormat):
    @property
    def formatStr(self) -> str:
        return (
            "[%(asctime)s](%(levelname)s) "  # cspell:disable-line
            "[%(name)s:%(lineno)s] %(message)s"
        )


class LiteLogFormat:
    @property
    def formatStr(self) -> str:
        return "[%(name)s:%(lineno)s](%(levelname)s) %(message)s"  # cspell:disable-line
(プロジェクト名)/(プロジェクト名)/settings.py
from (プロジェクト名) import logging_settings


LOGGING = logging_settings.LOGGING
...

djangoでなくpythonのloggingでする方法
https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output

Discussion