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

Last change on this file since 6479 was 6445, checked in by uli, 13 years ago
  • Reorder imports
  • Remove outdated stuff
  • Fixes.
File size: 8.3 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
28from zope.interface import Interface, Attribute
29
30marker_ = object()
31
32class WAeUPLogger(object):
33
34    _logger = None
35
36    def __init__(self, loggername, filename, site=marker_, logdir=marker_,
37                 handlers=marker_, formatters=marker_, propagate=False,
38                 level=logging.DEBUG):
39        self.loggername = loggername
40        self.filename = filename
41        self.site = site
42        self.sitename = None
43        self.logdir = logdir
44        self.handlers = handlers
45        self.formatters = formatters
46        self.propagate = propagate
47        self.level = level
48        self._logger = None
49        return
50
51
52    @property
53    def logger(self):
54        if self._logger is not None:
55            if '__app' in self._logger.name:
56                if getattr(self.site, '__name__', None) is not None:
57                    self.setup()
58            return self._logger
59        self.setup()
60        return self._logger
61
62    def setup(self):
63        if self.site is marker_:
64            self.site = grok.getSite()
65        if '%s' in self.loggername:
66            name = getattr(self.site, '__name__', '__app')
67            self.loggername = self.loggername % (name,)
68        self.logger = logging.getLogger(self.loggername)
69        self.update()
70        return
71
72    def update(self):
73        if self.site is marker_:
74            self.site = grok.getSite()
75        if self.logdir is marker_:
76            self.logdir = os.path.join(self.site['datacenter'].storage, 'logs')
77        if not os.path.exists(self.logdir):
78            os.mkdir(self.logdir)
79        filename = os.path.join(self.logdir, self.filename)
80
81        # Create a rotating file handler logger for datacenter.
82        if self.handlers is marker_:
83            self.handlers = [logging.handlers.RotatingFileHandler(
84                    filename, maxBytes=5*1024**1, backupCount=5)]
85        if self.formatters is marker_:
86            self.formatters = [logging.Formatter(
87                    '%(asctime)s - %(levelname)s - %(message)s')]
88
89        self.logger.propagate = self.propagate
90        self.logger.setLevel(self.level)
91
92        for handler, formatter in map(lambda x, y: (x,y),
93                                     self.handlers, self.formatters):
94            handler.setFormatter(formatter)
95            self.logger.addHandler(handler)
96        return self.logger
97
98
99class ISiteLoggers(Interface):
100
101    loggers = Attribute("A list or generator of registered WAeUPLoggers")
102
103    def register(name, filename=None, site=None, **options):
104        """Register a logger `name` which logs to `filename`.
105
106        If `filename` is not given, logfile will be `name` with
107        ``.log`` as filename extension.
108        """
109
110    def unregister(name):
111        """Unregister a once registered logger.
112        """
113
114class SiteLoggers(object):
115
116    grok.implements(ISiteLoggers)
117
118    @property
119    def loggers(self):
120        return self._loggers.values()
121
122    def __init__(self):
123        self._loggers = dict()
124
125    def getLogger(self, filename):
126        waeup_logger = self._loggers.get(filename, None)
127        return waeup_logger.logger
128
129    def register(self, loggername, filename=None, site=None, **kw):
130        if loggername in self._loggers.keys():
131            raise KeyError('Logger "%s" exists already.' % loggername)
132        self._loggers[loggername] = WAeUPLogger(
133            loggername, filename=filename, site=site, **kw)
134        return
135
136    def unregister(self, name):
137        if name in self._loggers.keys():
138            del self._loggers[name]
139        return
140
141    def keys(self):
142        return self._loggers.keys()
143
144class ILogger(Interface):
145    """A logger cares for setup, update and restarting of a Python logger.
146    """
147
148    logger = Attribute("""A :class:`logging.Logger` instance""")
149
150
151    def __init__(name, filename=None, site=None, **options):
152        """Create a WAeUP logger instance.
153        """
154        pass
155
156    def setup():
157        """Create a Python :class:`logging.Logger` instance.
158
159        The created logger is based on the params given by constructor.
160        """
161        pass
162
163    def update(**options):
164        """Update the logger.
165
166        Updates the logger respecting modified `options` and changed
167        paths.
168        """
169
170class WAeUPLogger(object):
171
172    grok.implements(ILogger)
173
174    _logger = None
175
176    def __init__(self, name, filename=None, site=None, **options):
177        self.name = name
178        self.filename = filename
179        if filename is None:
180            if '.' in name:
181                name = name.rsplit('.', 1)[1]
182            self.filename = "%s.log" % name
183        self.site = site
184        self.max_bytes = options.get('maxBytes', 5 * 1024 ** 2)
185        self.backup_count = options.get('backupCount', 5)
186        self.options = options
187        return
188
189    @property
190    def logger(self):
191        if self._needSetup():
192            self._setup()
193        return logging.getLogger(self._loggername)
194
195    def setup(self):
196        return self._setup()
197
198    def update(self, **options):
199        self._logger = None # unset to be set up again on next access.
200        # XXX: set options
201        pass
202
203    def _needSetup(self):
204        if self._logger is None:
205            return True
206        if not '__app' in self._logger.name:
207            return False
208        if getattr(self.site, '__name__', None) is not None:
209            return True
210        return False
211
212    def _removeHandlers(self):
213        handlers = self._logger.handlers
214        for handler in handlers:
215            self._logger.removeHandler(handler)
216
217    def _setup(self):
218        if self.site is None:
219            self.site = grok.getSite()
220        self._loggername = self.name
221        if not '.' in self._loggername:
222            self._loggername = 'waeup.sirp.%s.%s' % ('%s', self._loggername)
223        if '%s' in self._loggername:
224            site_name = getattr(self.site, '__name__', '__app')
225            if site_name is None:
226                site_name = '__app'
227            self._loggername = self._loggername % (site_name,)
228        self._logger = logging.getLogger(self._loggername)
229        return self._update()
230
231    def _update(self):
232        self._removeHandlers() # Remove any old handlers
233        self._logdir = os.path.join(self.site['datacenter'].storage, 'logs')
234        if not os.path.exists(self._logdir):
235            os.mkdir(self._logdir)
236        filename = os.path.join(self._logdir, self.filename)
237
238        # Create a rotating file handler logger for datacenter.
239        default_handler = logging.handlers.RotatingFileHandler(
240            filename, maxBytes=self.max_bytes, backupCount=self.backup_count)
241        self.handler = self.options.get('handler', default_handler)
242
243        default_formatter = logging.Formatter(
244            '%(asctime)s - %(levelname)s - %(message)s')
245        formatter = self.options.get('formatter', default_formatter)
246        self.handler.setFormatter(formatter)
247
248        self._logger.addHandler(self.handler)
249        self._logger.propagate = self.options.get('propagate', False)
250        self._logger.setLevel(self.options.get('level', logging.DEBUG))
251        return self._logger
252
253#: A place where we store seen loggers.
254SiteLoggersRepository = dict()
255
256class SiteLoggersFinder(object):
257    grok.provides(ISiteLoggers)
258
259    def getLoggers(self, site=None):
260        if site is None:
261            site = grok.getSite()
262        if site not in SiteLoggersRepository.keys():
263            SiteLoggersRepository[site] = SiteLoggers()
264        return SiteLoggersRepository[site]
265
266grok.global_utility(SiteLoggersFinder, provides=ISiteLoggers)
Note: See TracBrowser for help on using the repository browser.