source: main/waeup.sirp/trunk/src/waeup/sirp/utils/logger.py @ 6440

Last change on this file since 6440 was 6440, checked in by uli, 13 years ago

Rollback #6400, loggers are back.

File size: 10.2 KB
Line 
1##
2## logging.py
3## Login : <uli@pu.smp.net>
4## Started on  Mon Jun 13 01:25:07 2011 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2011 Uli Fouquet
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""
23Convenience stuff for logging.
24"""
25import os
26import grok
27import logging
28
29marker_ = object()
30
31def setup_logger(loggername, filename, site=marker_, logdir=marker_,
32                 handler=marker_, formatter=marker_, propagate=False,
33                 level=logging.DEBUG):
34    """Create a logger.
35    """
36    if site is marker_:
37        site = grok.getSite()
38    if '%s' in loggername:
39        name = getattr(site, '__name__', 'app')
40        loggername = loggername % (name,)
41    logger = logging.getLogger(loggername)
42    update_logger(logger, filename, site=site, logdir=logdir, handler=handler,
43                  formatter=formatter, propagate=propagate, level=level)
44    return logger, loggername
45
46def update_logger(logger, filename, site=marker_, logdir=marker_,
47                  handler=marker_, formatter=marker_, propagate=False,
48                  level=logging.DEBUG):
49    if site is marker_:
50        site = grok.getSite()
51    if logdir is marker_:
52        logdir = os.path.join(site['datacenter'].storage, 'logs')
53    if not os.path.exists(logdir):
54        os.mkdir(logdir)
55    filename = os.path.join(logdir, filename)
56
57    # Create a rotating file handler logger for datacenter.
58    if handler is marker_:
59        handler = logging.handlers.RotatingFileHandler(
60            filename, maxBytes=5*1024**1, backupCount=5)
61    if formatter is marker_:
62        formatter = logging.Formatter(
63            '%(asctime)s - %(levelname)s - %(message)s')
64    handler.setFormatter(formatter)
65
66    logger.propagate = propagate
67    logger.setLevel(level)
68    logger.addHandler(handler)
69    return logger
70
71def get_logger(loggername, filename, site=marker_, **kw):
72    """Get a logger.
73    """
74    if '%s' in loggername:
75        if site is marker_:
76            site = grok.getSite()
77        loggername = loggername % (
78            getattr(site, '__name__', 'app'))
79    logger = logging.getLogger(loggername)
80    if not logger.handlers:
81        kw.update(dict(site=site))
82        logger, loggername = setup_logger(
83            loggername, filename, **kw)
84    return logger
85
86class WAeUPLogger(object):
87
88    _logger = None
89
90    def __init__(self, loggername, filename, site=marker_, logdir=marker_,
91                 handlers=marker_, formatters=marker_, propagate=False,
92                 level=logging.DEBUG):
93        self.loggername = loggername
94        self.filename = filename
95        self.site = site
96        self.sitename = None
97        self.logdir = logdir
98        self.handlers = handlers
99        self.formatters = formatters
100        self.propagate = propagate
101        self.level = level
102        self._logger = None
103        return
104
105
106    @property
107    def logger(self):
108        if self._logger is not None:
109            if '__app' in self._logger.name:
110                if getattr(self.site, '__name__', None) is not None:
111                    self.setup()
112            return self._logger
113        self.setup()
114        return self._logger
115
116    def setup(self):
117        if self.site is marker_:
118            self.site = grok.getSite()
119        if '%s' in loggername:
120            name = getattr(site, '__name__', '__app')
121            loggername = loggername % (name,)
122        self.logger = logging.getLogger(loggername)
123        self.update()
124        return
125
126    def update(self):
127        if self.site is marker_:
128            self.site = grok.getSite()
129        if self.logdir is marker_:
130            self.logdir = os.path.join(site['datacenter'].storage, 'logs')
131        if not os.path.exists(self.logdir):
132            os.mkdir(self.logdir)
133        filename = os.path.join(self.logdir, self.filename)
134
135        # Create a rotating file handler logger for datacenter.
136        if self.handlers is marker_:
137            self.handlers = [logging.handlers.RotatingFileHandler(
138                    filename, maxBytes=5*1024**1, backupCount=5)]
139        if formatters is marker_:
140            formatters = [logging.Formatter(
141                    '%(asctime)s - %(levelname)s - %(message)s')]
142
143        self.logger.propagate = self.propagate
144        self.logger.setLevel(self.level)
145
146        for handler, formatter in map(lambda x, y: (x,y),
147                                     self.handlers, self.formatters):
148            handler.setFormatter(formatter)
149            self.logger.addHandler(handler)
150        return self.logger
151
152
153from zope import schema
154from zope.interface import Interface, Attribute
155
156class ISiteLoggers(Interface):
157
158    loggers = Attribute("A list or generator of registered WAeUPLoggers")
159
160    def register(name, filename=None, site=None, **options):
161        """Register a logger `name` which logs to `filename`.
162
163        If `filename` is not given, logfile will be `name` with
164        ``.log`` as filename extension.
165        """
166
167    def unregister(name):
168        """Unregister a once registered logger.
169        """
170
171class SiteLoggers(object):
172
173    grok.implements(ISiteLoggers)
174
175    @property
176    def loggers(self):
177        return self._loggers.values()
178
179    def __init__(self):
180        self._loggers = dict()
181
182    def getLogger(self, filename):
183        waeup_logger = self._loggers.get(filename, None)
184        return waeup_logger.logger
185
186    def register(self, loggername, filename=None, site=None, **kw):
187        if loggername in self._loggers.keys():
188            raise KeyError('Logger "%s" exists already.' % loggername)
189        self._loggers[loggername] = WAeUPLogger(
190            loggername, filename=filename, site=site, **kw)
191        return
192
193    def unregister(self, name):
194        if name in self._loggers.keys():
195            del self._loggers[name]
196        return
197
198    def keys(self):
199        return self._loggers.keys()
200
201class ILogger(Interface):
202    """A logger cares for setup, update and restarting of a Python logger.
203    """
204
205    logger = Attribute("""A :class:`logging.Logger` instance""")
206
207
208    def __init__(name, filename=None, site=None, **options):
209        """Create a WAeUP logger instance.
210        """
211        pass
212
213    def setup():
214        """Create a Python :class:`logging.Logger` instance.
215
216        The created logger is based on the params given by constructor.
217        """
218        pass
219
220    def update(**options):
221        """Update the logger.
222
223        Updates the logger respecting modified `options` and changed
224        paths.
225        """
226
227class WAeUPLogger(object):
228
229    grok.implements(ILogger)
230
231    _logger = None
232
233    def __init__(self, name, filename=None, site=None, **options):
234        self.name = name
235        self.filename = filename
236        if filename is None:
237            if '.' in name:
238                name = name.rsplit('.', 1)[1]
239            self.filename = "%s.log" % name
240        self.site = site
241        self.max_bytes = options.get('maxBytes', 5 * 1024 ** 2)
242        self.backup_count = options.get('backupCount', 5)
243        self.options = options
244        return
245
246    @property
247    def logger(self):
248        if self._needSetup():
249            self._setup()
250        return logging.getLogger(self._loggername)
251
252    def setup(self):
253        return self._setup()
254
255    def update(self, **options):
256        self._logger = None # unset to be set up again on next access.
257        # XXX: set options
258        pass
259
260    def _needSetup(self):
261        if self._logger is None:
262            return True
263        if not '__app' in self._logger.name:
264            return False
265        if getattr(self.site, '__name__', None) is not None:
266            return True
267        return False
268
269    def _removeHandlers(self):
270        handlers = self._logger.handlers
271        for handler in handlers:
272            self._logger.removeHandler(handler)
273
274    def _setup(self):
275        if self.site is None:
276            self.site = grok.getSite()
277        self._loggername = self.name
278        if not '.' in self._loggername:
279            self._loggername = 'waeup.sirp.%s.%s' % ('%s', self._loggername)
280        if '%s' in self._loggername:
281            site_name = getattr(self.site, '__name__', '__app')
282            if site_name is None:
283                site_name = '__app'
284            self._loggername = self._loggername % (site_name,)
285        self._logger = logging.getLogger(self._loggername)
286        return self._update()
287
288    def _update(self):
289        self._removeHandlers() # Remove any old handlers
290        self._logdir = os.path.join(self.site['datacenter'].storage, 'logs')
291        if not os.path.exists(self._logdir):
292            os.mkdir(self._logdir)
293        filename = os.path.join(self._logdir, self.filename)
294
295        # Create a rotating file handler logger for datacenter.
296        default_handler = logging.handlers.RotatingFileHandler(
297            filename, maxBytes=self.max_bytes, backupCount=self.backup_count)
298        self.handler = self.options.get('handler', default_handler)
299
300        default_formatter = logging.Formatter(
301            '%(asctime)s - %(levelname)s - %(message)s')
302        formatter = self.options.get('formatter', default_formatter)
303        self.handler.setFormatter(formatter)
304
305        self._logger.addHandler(self.handler)
306        self._logger.propagate = self.options.get('propagate', False)
307        self._logger.setLevel(self.options.get('level', logging.DEBUG))
308        return self._logger
309
310#: A place where we store seen loggers.
311SiteLoggersRepository = dict()
312
313class SiteLoggersFinder(object):
314    grok.provides(ISiteLoggers)
315
316    def getLoggers(self, site=None):
317        if site is None:
318            site = grok.getSite()
319        if site not in SiteLoggersRepository.keys():
320            SiteLoggersRepository[site] = SiteLoggers()
321        return SiteLoggersRepository[site]
322
323grok.global_utility(SiteLoggersFinder, provides=ISiteLoggers)
Note: See TracBrowser for help on using the repository browser.