Skip to content

Instantly share code, notes, and snippets.

@kmondesir
Created November 9, 2024 02:22
Show Gist options
  • Save kmondesir/0b146477b87f4ef7f3934c2a0b1be89a to your computer and use it in GitHub Desktop.
Save kmondesir/0b146477b87f4ef7f3934c2a0b1be89a to your computer and use it in GitHub Desktop.
import logging
import json
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
from time import gmtime
class JSONFormatter(logging.Formatter):
def __init__(self, fmt: dict, datefmt: str):
super().__init__(fmt, datefmt)
def format(self, record):
"""
Takes the json entry, converts it to a dictionary, appends the extra variable
and then converts it back to json
"""
record.message = record.getMessage()
data = record.__dict__
extra = data.get('extra')
if self.usesTime():
record.asctime = self.formatTime(record, self.datefmt)
s = self.formatMessage(record)
if record.exc_info:
# Cache the traceback text to avoid converting it multiple times
# (it's constant anyway)
if not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
if record.exc_text:
if s[-1:] != "\n":
s = s + "\n"
s = s + record.exc_text
if record.stack_info:
if s[-1:] != "\n":
s = s + "\n"
s = s + self.formatStack(record.stack_info)
if extra:
entry = json.loads(s)
entry['extra'] = extra
s = json.dumps(entry)
return s
class JSONLogger(logging.Logger):
def __init__(self,
name: str,
level: logging = logging.NOTSET,
timestampformat: str = r"%Y-%b-%d %H:%M:%S",
fmt: dict = {
"timestamp": "%(asctime)s",
"module": "%(module)s",
"level": "%(levelname)s",
"linenumber": "%(lineno)d",
"message": "%(message)s"},
)->None:
super().__init__(name, level)
self.timestampformat = timestampformat
# create formatter
self.formatter = JSONFormatter(json.dumps(fmt), timestampformat)
self.formatter.converter = gmtime
# create handler
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(self.formatter)
# add handlers to logger
self.addHandler(stream_handler)
def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
func=None, extra=None, sinfo=None)->dict:
"""
Overrides makeRecord method and appends extra dictionary to log record.
"""
record = super().makeRecord(name, level, fn, lno, msg, args, exc_info, extra)
if extra:
record.__dict__['extra'] = extra
return record
class RotatingFileLogger(JSONLogger):
def __init__(self,
name: str,
level: logging,
timestampformat: str = None,
filename: str = r"C:\Temp\test.log",
mode: str = "a",
maxsize: int = 25,
backupCount: int = 5,
encoding: str = "ASCII",
delay: bool = False):
super().__init__(name, level, timestampformat)
maxBytes = maxsize * 1024 * 1024
file_handler = RotatingFileHandler(
filename=filename,
mode="a",
maxBytes=maxBytes,
backupCount=backupCount,
encoding="ASCII",
delay=delay
)
file_handler.setFormatter(self.formatter)
self.addHandler(file_handler)
class TimedRotatingFileLogger(JSONLogger):
def __init__(self,
name: str,
level: logging,
timestampformat: str = None,
filename: str = r"C:\Temp\test.log",
when='D',
interval: int =1,
backupCount: int =5,
encoding: str ="ASCII",
delay: bool =False,
utc=False):
super().__init__(name, level, timestampformat)
file_handler = TimedRotatingFileHandler(
filename=filename,
when=when,
interval=interval,
backupCount=backupCount,
encoding=encoding,
delay=delay,
utc=utc
)
file_handler.setFormatter(self.formatter)
self.addHandler(file_handler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment