Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python, want logging with log rotation and compression

Tags:

python

logging

Can anyone suggest a way in python to do logging with:

  • log rotation every day
  • compression of logs when they're rotated
  • optional - delete oldest log file to preserve X MB of free space
  • optional - sftp log files to server

Thanks for any responses, Fred

like image 336
fred basset Avatar asked Dec 11 '11 22:12

fred basset


People also ask

How do you force a log to rotate in the VAR log directory?

If you want to rotate /var/log/syslog it needs to be listed in a logrotate config file somewhere, and you just run logrotate . If it rotated recently, then logrotate -f to force it to do it again. So, you need that in a file, normally either /etc/logrotate. conf or as a file snippet in /etc/logrotate.

How do I add log to rotated file?

Add an entry for your log fileAt the end of logrotate. conf, add the full path to your log file followed by open and close curly brackets. There are many options you can add like the frequency to rotate "daily/weekly/monthly" and the number of rotations to keep "rotate 2/rotate 3".


1 Answers

  • log rotation every day: Use a TimedRotatingFileHandler
  • compression of logs: Set the encoding='bz2' parameter. (Note this "trick" will only work for Python2. 'bz2' is no longer considered an encoding in Python3.)
  • optional - delete oldest log file to preserve X MB of free space. You could (indirectly) arrange this using a RotatingFileHandler. By setting the maxBytes parameter, the log file will rollover when it reaches a certain size. By setting the backupCount parameter, you can control how many rollovers are kept. The two parameters together allow you to control the maximum space consumed by the log files. You could probably subclass the TimeRotatingFileHandler to incorporate this behavior into it as well.

Just for fun, here is how you could subclass TimeRotatingFileHandler. When you run the script below, it will write log files to /tmp/log_rotate*.

With a small value for time.sleep (such as 0.1), the log files fill up quickly, reach the maxBytes limit, and are then rolled over.

With a large time.sleep (such as 1.0), the log files fill up slowly, the maxBytes limit is not reached, but they roll over anyway when the timed interval (of 10 seconds) is reached.

All the code below comes from logging/handlers.py. I simply meshed TimeRotatingFileHandler with RotatingFileHandler in the most straight-forward way possible.

import time import re import os import stat import logging import logging.handlers as handlers   class SizedTimedRotatingFileHandler(handlers.TimedRotatingFileHandler):     """     Handler for logging to a set of files, which switches from one file     to the next when the current file reaches a certain size, or at certain     timed intervals     """      def __init__(self, filename, maxBytes=0, backupCount=0, encoding=None,                  delay=0, when='h', interval=1, utc=False):         handlers.TimedRotatingFileHandler.__init__(             self, filename, when, interval, backupCount, encoding, delay, utc)         self.maxBytes = maxBytes      def shouldRollover(self, record):         """         Determine if rollover should occur.          Basically, see if the supplied record would cause the file to exceed         the size limit we have.         """         if self.stream is None:                 # delay was set...             self.stream = self._open()         if self.maxBytes > 0:                   # are we rolling over?             msg = "%s\n" % self.format(record)             # due to non-posix-compliant Windows feature             self.stream.seek(0, 2)             if self.stream.tell() + len(msg) >= self.maxBytes:                 return 1         t = int(time.time())         if t >= self.rolloverAt:             return 1         return 0   def demo_SizedTimedRotatingFileHandler():     log_filename = '/tmp/log_rotate'     logger = logging.getLogger('MyLogger')     logger.setLevel(logging.DEBUG)     handler = SizedTimedRotatingFileHandler(         log_filename, maxBytes=100, backupCount=5,         when='s', interval=10,         # encoding='bz2',  # uncomment for bz2 compression     )     logger.addHandler(handler)     for i in range(10000):         time.sleep(0.1)         logger.debug('i=%d' % i)  demo_SizedTimedRotatingFileHandler() 
like image 174
unutbu Avatar answered Oct 01 '22 03:10

unutbu