My Note / Zeliang YAO
  • Zeliang's Note
  • Dremio
    • Custom Class
  • 💕Python
    • Design Pattern
      • Creational
        • Abstract Factory
        • Factory Method
        • Singleton
        • Builder / Director
      • Structural
        • Adapter
    • Boto3
    • Typing
    • String
    • Requests
    • Iterator & Iterable
      • Consuming iterator manually
      • Lazy Iterable
    • Genrators
    • itertools
    • Collections
    • Customization
      • Customize built-in
      • Logging
      • Hdf5
      • Sqlite3 & Df
    • Pandas
      • Basic
      • Data cleaning
      • Merge, Join, Concat
      • Useful tricks
      • Simple model
      • Pandas acceleration
    • Pandas time series
      • Date Range
      • Datetime Index
      • Holidays
      • Function_to_date_time
      • Period
      • Time zone
    • *args and**kwargs
    • Context Manager
    • Lambda
    • SHA
    • Multithreading
      • Threading
      • Speed Up
    • Email
    • Improvement
    • Useful functions
    • Python OOP
      • Basic
      • @static / @class method
      • attrs module
      • Dataclasses
      • Dataclasses example
      • Others
    • Design patterns
      • Creational Patterns
      • Structural Patterns
      • Behavioral Patterns
  • 🐣Git/Github
    • Commands
  • K8s
    • Useful commands
  • Linux
    • Chmod
Powered by GitBook
On this page

Was this helpful?

  1. Python
  2. Customization

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})
PreviousCustomize built-inNextHdf5

Last updated 3 years ago

Was this helpful?

💕