2

I have been given a requirement to log a python application that runs continuously, to a logfile on an SMB share.

The issue is if there is ever a reason for that SMB share to go offline (patching/network issue etc) whilst the python app is still running, a stream error is raised (due to the file being missing), the filehandler does not recover once the file becomes available once again, therefore no further logs are written.

Error trace

--- Logging error ---
Traceback (most recent call last):
  File "C:\Program Files (x86)\Python38-32\lib\logging\handlers.py", line 69, in emit
    if self.shouldRollover(record):
  File "C:\Program Files (x86)\Python38-32\lib\logging\handlers.py", line 186, in shouldRollover
    self.stream.seek(0, 2)  #due to non-posix-compliant Windows feature
PermissionError: [Errno 13] Permission denied

Question

Is it possible to capture the failed state, wait some time, then request the handler to re-open the logfile?


I have simulated the state by pointing the filehandler to a USB drive (D:/) which is removed then re-inserted:

import logging,time,datetime
from logging.handlers import RotatingFileHandler

def configure_logging(processName):
    MAX_BYTES = 500000
    BACKUP_COUNT = 5
    logger = logging.getLogger("testLogger")
    
    logger.setLevel(logging.INFO)
    log_format = logging.Formatter('%(asctime)s %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')

    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(log_format)
    stream_handler.setLevel(logging.INFO)
    logger.addHandler(stream_handler)

    info_handler = RotatingFileHandler('D:/info.log', maxBytes=MAX_BYTES, backupCount=BACKUP_COUNT)
    info_handler.setFormatter(log_format)
    info_handler.setLevel(logging.INFO)
    logger.addHandler(info_handler)

    error_handler = RotatingFileHandler('C:/temp/error.log', maxBytes=MAX_BYTES, backupCount=BACKUP_COUNT)
    error_handler.setFormatter(log_format)
    error_handler.setLevel(logging.ERROR)
    logger.addHandler(error_handler)
    
    return(logger)


def looper():
    while 1:
        logger = logging.getLogger("testLogger")
        logger.info('Remote message')
        logger.error('Local Message')
        print('i looped')
        time.sleep(1)

if __name__ == "__main__":
    processName = 'TestLogger'
    logger = configure_logging(processName)
    looper()

Logs are still written to the local C:/ drive from logger.error, as this is performed by the second filehandler, but the log file at D:/info.log is no longer written to once the file becomes available once again.

R3uben
  • 105
  • 10

0 Answers0