Passing the module name to the FileHandler for inclusion in log file name

51 views Asked by At

I've written a custom logger as part of a Python automation project, but I waty to make the resulting .txt files even easier to identify by adding the name of the script that called the logger to the name of the resulting .txt file.

Currently my file handler is able to append the date & time to file name.

file_handler = logging.FileHandler(timeStamped('Test Log.txt'))

This results in a file name like this: 2023-12-11_10.44.33. - Test Log.txt But I want to be able to add the name of script that called it so it would look something like this. 2023-12-11_10.44.33. - level2 - Test Log.txt

I tried just adding %(module)s to the file handler but that just resulted in a file called 2023-12-08_16.12.21 - %(module)s - Test Log.txt

The full logger code below:

import os
import sys
import time
import datetime
import logging
from logging.handlers import QueueHandler, QueueListener
import queue
from token import NEWLINE
from collections import UserList

# Change the current working directory
os.chdir('C:\Git_Repo\pyautotest\AutoTest\OutputLogs')


def timeStamped(fname, fmt='%Y-%m-%d_%H.%M.%S. - {fname}'):
    return datetime.datetime.now().strftime(fmt).format(fname=fname)

#Records Current date & time and appends it to the file name of the txt log created at the end of this script.

# Standard Logging Levels
# DEBUG: Detailed information, typically of interest only when diagnosing problems.
# INFO: Confirmation that things are working as expected.
# WARNING: An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
# ERROR: Due to a more serious problem, the software has not been able to perform some function.
# CRITICAL: A serious error, indicating that the program itself may be unable to continue running.


stream_handler = logging.StreamHandler()
file_handler = logging.FileHandler(timeStamped('Test Log.txt'))

PrintLog = logging.getLogger(__name__)
PrintLog.setLevel(logging.DEBUG)
PrintLog.addHandler(stream_handler)
PrintLog.addHandler(file_handler)

class MyFormatter(logging.Formatter):

    # Custom formatters for the differnt levels of logging.
    debug_fmt  = "%(levelname)s: %(asctime)s: %(pathname)s: Line %(lineno)s:  %(message)s"
    info_fmt = "%(message)s"
    error_fmt = "%(levelname)s: %(asctime)s: %(pathname)s: Line %(lineno)s:  ERROR - %(message)s"
    
    file_fmt = "%(module)s"
    
    def __init__(self):
        super().__init__(fmt="%(levelno)d: %(module)s: %(msg)s", datefmt='%Y-%m-%d_%H.%M', style='%')  
    
    def format(self, record):

        # Save the original format configured by the user
        # when the logger formatter was instantiated
        format_orig = self._style._fmt

        # Replace the original format with one customized by logging level
        if record.levelno == logging.DEBUG:
            self._style._fmt = MyFormatter.debug_fmt

        elif record.levelno == logging.INFO:
            self._style._fmt = MyFormatter.info_fmt

        elif record.levelno == logging.ERROR:
            self._style._fmt = MyFormatter.error_fmt
            
        # Call the original formatter class to do the grunt work
        result = logging.Formatter.format(self, record)
        
        # Restore the original format configured by the user
        self._style._fmt = format_orig

        return result


fmt = MyFormatter()
PrintLog.propagate = False

stream = logging.Formatter('%(message)s')
stream_handler.setFormatter(stream)

file_handler.setFormatter(fmt)          


    
class ListFormatter(UserList):
    def __init__(self, iterable):
        super().__init__(str(item) for item in iterable)

    def __setitem__(self, index, item):
        self.data[index] = str(item),'\n'

    def insert(self, index, item):
        self.data.insert(index, str(item),'\n')

    def append(self, item):
        self.data.append(str(item))

    def extend(self, other):
        if isinstance(other, type(self)):
            self.data.extend(other)
        else:
            self.data.extend(str(item) for item in other)    
        

today = datetime.datetime.now()
date_time = today.strftime("%H:%M:%S, on %d/%m/%Y")          


class PrintAppended():
    def __init__(self):
        PrintLog.info(format(''.join(map(str, ListFormatter))))
        PrintLog.info('\n')     
        PrintLog.info('Testing concluded at ' + date_time +'.')
       

  

So my logger is formatting the content within the log file as I want it, I just want a way to modify the file name dependant on the script that called my logger.

0

There are 0 answers