Skip to content

Instantly share code, notes, and snippets.

@Tapanhaz
Last active May 7, 2024 08:08
Show Gist options
  • Save Tapanhaz/85bc7e2f0955d59f193364618e7dc1bc to your computer and use it in GitHub Desktop.
Save Tapanhaz/85bc7e2f0955d59f193364618e7dc1bc to your computer and use it in GitHub Desktop.
Custom logging formatter with colored console outputs and logging to file.
import logging
logger = logging.getLogger(__name__)
def func1():
logger.warning("This is a warning message")
logger.info("This is a info message")
import sys
import logging
import platform
from datetime import datetime
from pathlib import Path
if platform.system() == "Windows":
import ctypes
handle = ctypes.windll.kernel32.GetStdHandle(-11)
mode = ctypes.c_ulong()
ctypes.windll.kernel32.GetConsoleMode(handle, ctypes.byref(mode))
mode.value |= 4
ctypes.windll.kernel32.SetConsoleMode(handle, mode)
class StdOutLogFormatter(logging.Formatter):
grey = '\x1b[38;21m'
blue = '\x1b[38;5;39m'
yellow = '\x1b[38;5;226m'
red = '\x1b[38;5;196m'
bold_red = '\x1b[31;1m'
reset = '\x1b[0m'
green = '\x1b[38;5;46m'
magenta = '\x1b[38;5;196m'
myblue = '\x1b[38;5;14m'
brick = '\x1b[38;5;208m'
def __init__(self, fmt=None, datefmt=None):
super().__init__(fmt)
def format(self, record):
asctime = getattr(record, 'asctime', None)
if asctime is None:
asctime = datetime.fromtimestamp(record.created).astimezone().strftime('%d-%m-%Y %H:%M:%S.%f')
if record.levelno == logging.DEBUG:
record.msg = f"{self.yellow} {asctime}: [{record.levelname}] - [{record.name}]- {record.msg} {self.reset}"
elif record.levelno == logging.INFO:
record.msg = f"{self.green} {asctime}: [{record.levelname}] - [{record.name}]- {record.msg} {self.reset}"
elif record.levelno == logging.WARNING:
record.msg = f"{self.myblue} {asctime}: [{record.levelname}] - [{record.name}]- {record.msg} {self.reset}"
elif record.levelno == logging.ERROR:
record.msg = f"{self.brick} {asctime}: [{record.levelname}] - [{record.name}]- {record.msg} {self.reset}"
elif record.levelno == logging.CRITICAL:
record.msg = f"{self.bold_red} {asctime}: [{record.levelname}] - [{record.name}]- {record.msg} {self.reset}"
return super().format(record)
def formatTime(self, record, datefmt=None):
if not datefmt:
return super().formatTime(record, datefmt=datefmt)
return datetime.fromtimestamp(record.created).astimezone().strftime(datefmt)
class FileLogFormatter(logging.Formatter):
def formatTime(self, record, datefmt=None):
if not datefmt:
return super().formatTime(record, datefmt=datefmt)
return datetime.fromtimestamp(record.created).astimezone().strftime(datefmt)
class FormattedLogger:
def __init__(
self,
handler =["stream_handler", "file_handler"],
main_loglevel = logging.DEBUG,
additional_modules = [],
additional_modules_loglevel = logging.DEBUG,
other_modules_loglevel = logging.DEBUG,
log_directory='Logs',
colored_terminal = True
):
self.logger = logging.getLogger()
self.logger.setLevel(main_loglevel)
for name, module in sys.modules.items():
if hasattr(module, '__file__') and not name.startswith('_'):
#print(module, "***", name)
child_logger = self.logger.getChild(str(name))
if name in additional_modules:
child_logger.setLevel(additional_modules_loglevel)
else:
child_logger.setLevel(other_modules_loglevel)
if "file_handler" in handler:
script_dir = Path(__file__).resolve().parent
self.log_directory = script_dir / log_directory
if not self.log_directory.is_dir():
self.log_directory.mkdir(parents=True)
current_datetime_string = datetime.now().strftime("%d_%m_%Y_%H_%M_%S")
self.fh_formatter = FileLogFormatter(
'%(asctime)s: [%(levelname)s] - [%(name)s] - %(message)s',
datefmt='%d-%m-%Y %H:%M:%S.%f'
)
self.fh = logging.FileHandler(f'{self.log_directory}/{current_datetime_string}.log')
self.fh.setFormatter(self.fh_formatter)
self.fh.setLevel(logging.DEBUG)
self.logger.addHandler(self.fh)
if "stream_handler" in handler:
if colored_terminal:
self.sh_formatter = StdOutLogFormatter()
else:
self.sh_formatter = FileLogFormatter(
'%(asctime)s: [%(levelname)s] - [%(name)s] - %(message)s',
datefmt='%d-%m-%Y %H:%M:%S.%f'
)
self.sh = logging.StreamHandler(sys.stdout)
self.sh.setFormatter(self.sh_formatter)
self.sh.setLevel(logging.DEBUG)
self.logger.addHandler(self.sh)
def info(self, message):
self.logger.info(message)
def debug(self, message):
self.logger.debug(message)
def warning(self, message):
self.logger.warning(message)
def error(self, message):
self.logger.error(message)
def critical(self, message):
self.logger.critical(message)
import logging
from logging_module import FormattedLogger
import httpx
from abcd import *
logger = FormattedLogger(
main_loglevel= logging.DEBUG,
additional_modules= ["abcd"],
additional_modules_loglevel= logging.WARNING,
other_modules_loglevel= logging.ERROR,
colored_terminal= False
)
func1()
client = httpx.Client()
client.get("https://www.example.com")
logger.info("Completed")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment