Logging
Standard / Custom logging
# -*- coding: utf-8 -*-
import os
import sys
from datetime import datetime,timedelta
import logging
from functools import wraps
from time import time
"""
LOGGING LEVEL PRIORITY
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
"""
LOG_FOLDER = 'logs'
LOG_LEVEL = logging.INFO
TODAY = datetime.now().strftime("%Y%m%d")
LOG_FORMAT = '%(asctime)s|{}.py|%(levelname)s|%(message)s'
PARIS_TIME_ZONE = "Europe/Paris"
DEFAULT_TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
def datetime2Utc(dt:datetime, timeformat:str=DEFAULT_TIME_FORMAT)->str:
"""
Receive a datetime object and return utc time with string format
"""
return dt.astimezone(timezone('utc')).strftime(timeformat)
def datetime2Paris(dt:datetime, timeformat:str=DEFAULT_TIME_FORMAT)->str:
"""
Receive a datetime object and return Paris time with string format
"""
return dt.astimezone(timezone(PARIS_TIME_ZONE)).strftime(timeformat)
class funcLogging:
"""
Create a logger object and check if it has a filehandle attached, if not add one, Singleton design pattern.
"""
def __init__(self,filename:str)->None:
self.folderPath = f"{LOG_FOLDER}"
self.completePath = f"./{LOG_FOLDER}/{TODAY}.log"
if not os.path.exists(self.folderPath):
os.makedirs(self.folderPath)
self.logger = logging.getLogger()
self.logger.setLevel(LOG_LEVEL)
self.fileHandler = logging.FileHandler(self.completePath, 'a')
self.fileHandler.setFormatter(logging.Formatter(LOG_FORMAT.format(filename)))
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(funcLogging, cls).__new__(cls)
return cls.instance
def critical(self, msg:str)->None:
self.logger.critical(msg)
def error(self, msg:str)->None:
self.logger.error(msg)
def warning(self, msg:str)->None:
self.logger.warning(msg)
def info(self, msg:str)->None:
self.logger.info(msg)
def debug(self, msg:str)->None:
self.logger.debug(msg)
class customLogging:
def __init__(self, filename:str)->None:
self.fileName = filename
self.folderPath = f"{LOG_FOLDER}"
self.completePath = f"./{LOG_FOLDER}/{TODAY}.log"
if not os.path.exists(self.folderPath):
os.makedirs(self.folderPath)
self.format ="{0}|{1}.py|{2}|{3}"
self.dateTimeFormat = '%Y-%m-%d %H:%M:%S'
def write(self, msg)->None:
today = datetime.now().strftime("%Y%m%d")
self.completePath = f"./{LOG_FOLDER}/{today}.log"
with open(self.completePath,encoding='utf-8', mode='a') as file:
file.write(str(msg)+'\n')
sys.stdout.write(str(msg)+'\n')
def getDateTimeNow(self)->str:
return datetime.now()
def critical(self, msg:str)->None:
msg = self.format.format(datetime2Paris(self.getDateTimeNow()), self.fileName, "CRITICAL", msg)
self.write(msg)
def error(self, msg:str)->None:
msg = self.format.format(datetime2Paris(self.getDateTimeNow()), self.fileName, "ERROR", msg)
self.write(msg)
def warning(self, msg:str)->None:
msg = self.format.format(datetime2Paris(self.getDateTimeNow()), self.fileName, "WARNING", msg)
self.write(msg)
def info(self, msg:str)->None:
msg = self.format.format(datetime2Paris(self.getDateTimeNow()), self.fileName, "INFO", msg)
self.write(msg)
def debug(self, msg:str)->None:
msg = self.format.format(datetime2Paris(self.getDateTimeNow()), self.fileName, "DEBUG", msg)
self.write(msg)
def timer(self, f):
@wraps(f)
def wrap(*args, **kw):
ts = time()
result = f(*args, **kw)
te = time()
fctAndDuration = str({"functionName":str(f.__name__),"duration":f"{str(timedelta(seconds=te-ts))}"})
msg = self.format.format(self.getDateTimeNow(), self.fileName, "INFO", fctAndDuration)
self.write(msg)
return result
return wrap
Basic use:
from pathlib import Path
log = customLogging(Path(__file__).stem)
log.info("info message")
try:
foo()
except Excepction as e:
log.error({'comment':'K8s worker is down','error':e})
Last updated