Changeset 8512


Ignore:
Timestamp:
25 May 2012, 00:30:22 (12 years ago)
Author:
uli
Message:

Add support for datacenter to search log files.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/datacenter.py

    r8397 r8512  
    2222"""
    2323import os
     24import re
    2425import shutil
    2526import grok
     
    3233from waeup.kofa.utils.helpers import copy_filesystem_tree
    3334from waeup.kofa.utils.logger import Logger
     35
     36#: Regular expression describing a logfile name with backup extension
     37RE_LOGFILE_NAME = re.compile('^.+\.\d+$')
    3438
    3539class DataCenter(grok.Container, Logger):
     
    186190        return
    187191
     192    def _logfiles(self, basename):
     193        """Get sorted logfiles starting with `basename`.
     194        """
     195        def numerical_suffix(name):
     196            # return numerical suffix in `name` as number or 0.
     197            suffix = name.rsplit('.', 1)[-1]
     198            try:
     199                return int(suffix)
     200            except ValueError:
     201                return 0
     202            pass
     203        files = [basename,]
     204        for name in os.listdir(os.path.join(self.storage, 'logs')):
     205            if RE_LOGFILE_NAME.match(name):
     206                files.append(name)
     207        return sorted(files, key=numerical_suffix)
     208
     209    def queryLogfiles(self, basename, query=None, limit=0, start=0):
     210        """Search `query` in all logfiles starting with `basename`.
     211
     212        Returns an iterator of those lines in logfiles starting with
     213        `basename` that match `query`. If you want the result as a
     214        list, simply list() the iterator.
     215
     216        All logfiles with name `basename` and maybe some numerical
     217        extension ('.1', '.2', ...) are searched for the `query` term
     218        in correct order. So, if you ask for a basename 'app.log',
     219        then any file named 'app.log', 'app.log.1', 'app.log.2',
     220        etc. will be searched in that order.
     221
     222        The `query` is expected to be a string containing a regular
     223        expression.
     224
     225        If `limit` is set to some numerical value, at most this number
     226        of lines is returned.
     227
     228        With `start` you can give the number of first matched line to
     229        return. `start` is zero-based, i.e. the first match has number
     230        0, the scond one 1, etc.
     231
     232        Together with `limit` this allows some basic
     233        batching. Please keep in mind that batching might give
     234        unpredictable results, when logfiles change between two
     235        requests. This is not a problem when only one file is searched
     236        and changes include only appending new log messages.
     237
     238        Matches are found per line only (no multiline matches).
     239
     240        This method raises ValueError if some basic condition is not
     241        met, for instance if the given query string is not a valid
     242        regular expression.
     243
     244        Please note, that this exception will happen not before you
     245        really fetch a result line.
     246        """
     247        try:
     248            re_query = re.compile(query)
     249        except:
     250            raise ValueError('Invalid query string: %s' % query)
     251
     252        basename = basename.replace('/../', '')
     253        files = self._logfiles(basename)
     254
     255        # Search the log files
     256        num = 0
     257        for name in files:
     258            path = os.path.join(self.storage, 'logs', name)
     259            if not os.path.isfile(path):
     260                continue
     261            for line in open(path, 'rb'):
     262                if not re_query.match(line):
     263                    continue
     264                num += 1
     265                if (num - 1) < start:
     266                    continue
     267                yield line
     268
     269                if limit and (num - limit >= start):
     270                    raise StopIteration
     271        pass
    188272
    189273class DataCenterFile(object):
Note: See TracChangeset for help on using the changeset viewer.