import re
import sys
import locale
+import logging
revision = '$Revision$'
revision = re.sub( r'\$', '', revision )
__license__ = 'GPL3'
+logger = logging.getLogger('pylogrotate.common')
+
#========================================================================
def split_parts( text, keep_quotes = False, raise_on_unbalanced = True):
radix = locale.RADIXCHAR
radix = re.escape(radix)
if verbose > 5:
- sys.stderr.write("human2bytes(): using radix »%s«\n" % (radix))
+ logger.debug("using radix »%s«" % (radix))
value_raw = ''
prefix = None
raise ValueError("human2bytes(): Couldn't detect prefix »%s«." %(prefix))
if verbose > 5:
- sys.stderr.write("human2bytes(): found factor %d\n" % (factor))
+ logger.debug("found factor %d" % (factor))
return long(factor * value_float)
raise ValueError("Given period was empty")
if verbose > 4:
- sys.stderr.write("period2days() called with: »%s«\n" % (period))
+ logger.debug("called with: »%s«" % (period))
if period == 'now':
return float(0)
radix = locale.RADIXCHAR
radix = re.escape(radix)
if verbose > 5:
- sys.stderr.write("period2days(): using radix »%s«\n" % (radix))
+ logger.debug("using radix »%s«" % (radix))
# Search for hours in value
pattern = r'(\d+(?:' + radix + r'\d*)?)\s*h(?:ours?)?'
if verbose > 5:
- sys.stderr.write("period2days(): pattern »%s«\n" % (pattern))
+ logger.debug("pattern »%s«" % (pattern))
match = re.search(pattern, value, re.IGNORECASE)
if match:
hours_str = match.group(1)
hours = float(hours_str)
days += (hours/24)
if verbose > 4:
- sys.stderr.write("period2days(): found %f hours.\n" %(hours))
+ logger.debug("found %f hours." % (hours))
value = re.sub(pattern, '', value, re.IGNORECASE)
if verbose > 5:
- sys.stderr.write("period2days(): rest after hours: »%s«\n" %(value))
+ logger.debug("rest after hours: »%s«" %(value))
# Search for weeks in value
pattern = r'(\d+(?:' + radix + r'\d*)?)\s*w(?:eeks?)?'
if verbose > 5:
- sys.stderr.write("period2days(): pattern »%s«\n" % (pattern))
+ logger.debug("pattern »%s«" % (pattern))
match = re.search(pattern, value, re.IGNORECASE)
if match:
weeks_str = match.group(1)
weeks = float(weeks_str)
days += (weeks*7)
if verbose > 4:
- sys.stderr.write("period2days(): found %f weeks.\n" %(weeks))
+ logger.debug("found %f weeks." %(weeks))
value = re.sub(pattern, '', value, re.IGNORECASE)
if verbose > 5:
- sys.stderr.write("period2days(): rest after weeks: »%s«\n" %(value))
+ logger.debug("rest after weeks: »%s«" %(value))
# Search for months in value
pattern = r'(\d+(?:' + radix + r'\d*)?)\s*m(?:onths?)?'
if verbose > 5:
- sys.stderr.write("period2days(): pattern »%s«\n" % (pattern))
+ logger.debug("pattern »%s«" % (pattern))
match = re.search(pattern, value, re.IGNORECASE)
if match:
months_str = match.group(1)
months = float(months_str)
days += (months*30)
if verbose > 4:
- sys.stderr.write("period2days(): found %f months.\n" %(months))
+ logger.debug("found %f months." %(months))
value = re.sub(pattern, '', value, re.IGNORECASE)
if verbose > 5:
- sys.stderr.write("period2days(): rest after months: »%s«\n" %(value))
+ logger.debug("rest after months: »%s«" %(value))
# Search for years in value
pattern = r'(\d+(?:' + radix + r'\d*)?)\s*y(?:ears?)?'
if verbose > 5:
- sys.stderr.write("period2days(): pattern »%s«\n" % (pattern))
+ logger.debug("pattern »%s«" % (pattern))
match = re.search(pattern, value, re.IGNORECASE)
if match:
years_str = match.group(1)
years = float(years_str)
days += (years*365)
if verbose > 4:
- sys.stderr.write("period2days(): found %f years.\n" %(years))
+ logger.debug("found %f years." %(years))
value = re.sub(pattern, '', value, re.IGNORECASE)
if verbose > 5:
- sys.stderr.write("period2days(): rest after years: »%s«\n" %(value))
+ logger.debug("rest after years: »%s«" %(value))
# At last search for days in value
pattern = r'(\d+(?:' + radix + r'\d*)?)\s*(?:d(?:ays?)?)?'
if verbose > 5:
- sys.stderr.write("period2days(): pattern »%s«\n" % (pattern))
+ logger.debug("pattern »%s«" % (pattern))
match = re.search(pattern, value, re.IGNORECASE)
if match:
days_str = match.group(1)
days_float = float(days_str)
days += days_float
if verbose > 4:
- sys.stderr.write("period2days(): found %f days.\n" %(days_float))
+ logger.debug("found %f days." %(days_float))
value = re.sub(pattern, '', value, re.IGNORECASE)
if verbose > 5:
- sys.stderr.write("period2days(): rest after days: »%s«\n" %(value))
+ logger.debug("rest after days: »%s«" %(value))
# warn, if there is a rest
if re.search(r'^\s*$', value) is None:
- sys.stderr.write(
- "period2days(): invalid content for a period: »%s«\n" %(value)
- )
+ logger.warning('invalid content for a period: »%s«'%(value))
if verbose > 4:
- sys.stderr.write("period2days(): total %f days found.\n" %(days))
+ logger.debug("total %f days found." %(days))
return days
#========================================================================
+class StdoutFilter(logging.Filter):
+ '''
+ Class, that filters all logrecords
+ '''
+
+ def filter(self, record):
+ '''
+ Filtering log records and let through messages
+ except them with the level names 'WARNING', 'ERROR' or 'CRITICAL'.
+
+ @param record: the record to filter
+ @type record: logging.LogRecord
+
+ @return: pass the record or not
+ '''
+ if record.levelname == 'WARNING':
+ return False
+ if record.levelname == 'ERROR':
+ return False
+ if record.levelname == 'CRITICAL':
+ return False
+ return True
+
+#========================================================================
+
class LogrotateHandler(object):
'''
Class for application handler for Python logrotating
@type: str
'''
- self.config = {}
+ self.config = []
'''
@ivar: the configuration, how it was read from cofiguration file(s)
@type: dict
self.logger.setLevel(logging.DEBUG)
- pp = pprint.PrettyPrinter(indent=4)
- # create console handler and set level to debug
- ch = logging.StreamHandler()
- #ch.setLevel(logging.DEBUG)
- if verbose:
- ch.setLevel(logging.DEBUG)
- else:
- ch.setLevel(logging.INFO)
-
# create formatter
formatter = logging.Formatter('[%(asctime)s]: %(name)s %(levelname)-8s'
+ ' - %(message)s')
-
- # add formatter to ch
- ch.setFormatter(formatter)
-
- # add ch to logger
- self.logger.addHandler(ch)
+ if verbose > 1:
+ formatter = logging.Formatter('[%(asctime)s]: %(name)s %(levelname)-8s'
+ + '%(funcName)s() - %(message)s')
+
+ # create console handler for error messages
+ console_stderr = logging.StreamHandler(sys.stderr)
+ console_stderr.setLevel(logging.WARNING)
+ console_stderr.setFormatter(formatter)
+ self.logger.addHandler(console_stderr)
+
+ # create console handler for other messages
+ console_stdout = logging.StreamHandler(sys.stdout)
+ if verbose:
+ console_stdout.setLevel(logging.DEBUG)
+ else:
+ console_stdout.setLevel(logging.INFO)
+ fltr = StdoutFilter()
+ console_stdout.addFilter(fltr)
+ console_stdout.setFormatter(formatter)
+ self.logger.addHandler(console_stdout)
self.logger.debug( _("Logrotating initialised") )
self.logger.info( _("Testmode, skip writing of PID file '%s'.") % (self.pid_file) )
return True
- self.logger.info( _("Writing PID file '%s' ...") % (self.pid_file) )
+ self.logger.debug( _("Writing PID file '%s' ...") % (self.pid_file) )
f = None
try:
#------------------------------------------------------------
def rotate(self):
- pass
+ '''
+ Starting the underlying rotating.
+
+ @return: None
+ '''
+
+ _ = self.t.lgettext
+
+ if len(self.config) < 1:
+ msg = _("No logfile definitions found.")
+ self.logger.info(msg)
+ return
+
+ msg = _("Starting underlying rotation ...")
+ self.logger.info(msg)
+
+ for definition in self.config:
+ self._rotate_definition(definition)
+
+ return
+
+ #------------------------------------------------------------
+ def _rotate_definition(self, definition):
+ '''
+ Rotation of a logfile definition from a configuration file.
+
+ @param definition: definitions from configuration file
+ @type definition: dict
+
+ @return: None
+ '''
+
+ _ = self.t.lgettext
+
+ if self.verbose >= 4:
+ pp = pprint.PrettyPrinter(indent=4)
+ msg = _("Rotating of logfile definition:") + \
+ "\n" + pp.pformat(definition)
+ self.logger.debug(msg)
+
+
+
+ return
#------------------------------------------------------------
def delete_oldfiles(self):