Sometime I want extract part of disk-based log file, created by standard logging module) into separated file on disk. This recipe shows simple technique to acquire this.
Sample: processing tasks in loop, so on exit I have few logs: on log per task.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # -*- coding: Windows-1251 -*-
'''
'''
import logging
import os
log=logging.getLogger('LogExtractor')
BUF_SIZE=8*1024
class LogExtractor(object):
    '''
    Save current position of first disk file-based handler
    and save log fragment up to current position
    into separated file by request.
    Useful for splitting common program log for further reviewing
    by unprofessional personnel/client ;)
    '''
    def _find_file_handler(self, logger):
        # partially imported from Logger.callHandlers()
        c = logger
        filehandler=None
        while c:
            for hdlr in c.handlers:
                #log.info('Handler: %s' % type(hdlr))
                if isinstance(hdlr, logging.FileHandler):
                    filehandler=hdlr
                    break
            if filehandler:
                break
            if not c.propagate:
                c = None    #break out
            else:
                c = c.parent
        return filehandler
    def __init__(self, logger):
        '''
        search for first FileHandler and store it's current position 
        '''
        self.init_ok=0
        if not isinstance(logger, logging.Logger):
            log.error('__init__: <logger> must be instance of logging.Logger')
            return
        filehandler=self._find_file_handler(logger)
        if filehandler is None:
            log.error('__init__: no FileHandlers binded to <logger>')
            return
        self.stream=filehandler.stream
        self.basename=filehandler.baseFilename
        self.start_pos=self.stream.tell()
        self.init_ok=1
    def write_part(self, part_filename):
        '''
        put log file fragment from saved position to cyurrent state 
        into separate file
        '''
        if not self.init_ok:
            log.error('not properly initialized')
            return 0
        if self.stream.closed:
            if os.path.isfile(self.basename):
                part_size=os.path.getsize()
            else:
                log.error('log file (%s) not found on disk' % (self.basename))
                return 0
        else:
            part_size=self.stream.tell() - self.start_pos
        # put fragment
        f_log=open(self.basename, 'rb')
        f_part=open(part_filename, 'wb')
        try:
            f_log.seek(self.start_pos)
            left_size=part_size
            while left_size > 0:
                s=min(left_size, BUF_SIZE)
                buf=f_log.read(s)
                if len(buf) > 0:
                    f_part.write(buf)
                    left_size-=s
                else:
                    break
            return 1
        finally:
            f_part.close()
            f_log.close()
        return 0
if __name__ == '__main__':
    import sys
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(levelname)s %(message)s',
                        filename='%s.log' % sys.argv[0],
                        filemode='w')
    
    log=logging.getLogger('main')
    for i in range(1, 6):
        logextr=LogExtractor(log) # save current position
        for r in range(10):
            log.info('Pass %d: log message %d' % (i, r))
        rc=logextr.write_part('pass_%d.log' % i) # put fragment to file
        log.info('write_part result: %r' % rc)
 | 
    Tags: sysadmin
  
  
      
 Download
Download Copy to clipboard
Copy to clipboard