1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
# Copyright (C) 2006-2008 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
# GNU Mailman is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
"""Logging initialization, using Python's standard logging package."""
from __future__ import absolute_import
import os
import sys
import codecs
import logging
import ConfigParser
from mailman.config import config
from mailman.config.helpers import as_boolean, as_log_level
_handlers = []
class ReopenableFileHandler(logging.Handler):
def __init__(self, filename):
self._filename = filename
self._stream = self._open()
logging.Handler.__init__(self)
def _open(self):
return codecs.open(self._filename, 'a', 'utf-8')
def flush(self):
if self._stream:
self._stream.flush()
def emit(self, record):
# It's possible for the stream to have been closed by the time we get
# here, due to the shut down semantics. This mostly happens in the
# test suite, but be defensive anyway.
stream = (self._stream if self._stream else sys.stderr)
try:
msg = self.format(record)
fs = '%s\n'
try:
stream.write(fs % msg)
except UnicodeError:
stream.write(fs % msg.encode('string-escape'))
self.flush()
except:
self.handleError(record)
def close(self):
self.flush()
self._stream.close()
self._stream = None
logging.Handler.close(self)
def reopen(self):
self._stream.close()
self._stream = self._open()
def initialize(propagate=False):
# First, find the root logger and configure the logging subsystem.
# Initialize the root logger, then create a formatter for all the sublogs.
logging.basicConfig(format=config.logging.root.format,
datefmt=config.logging.root.datefmt,
level=as_log_level(config.logging.root.level))
# Create the subloggers
for logger_config in config.logger_configs:
logger_name = 'mailman.' + logger_config.name.split('.')[-1]
log = logging.getLogger(logger_name)
# Get settings from log configuration file (or defaults).
log_format = logger_config.format
log_datefmt = logger_config.datefmt
# Propagation to the root logger is how we handle logging to stderr
# when the qrunners are not run as a subprocess of mailmanctl.
log.propagate = as_boolean(logger_config.propagate)
# Set the logger's level.
log.setLevel(as_log_level(logger_config.level))
# Create a formatter for this logger, then a handler, and link the
# formatter to the handler.
formatter = logging.Formatter(fmt=log_format, datefmt=log_datefmt)
path_str = logger_config.path
path_abs = os.path.normpath(os.path.join(config.LOG_DIR, path_str))
handler = ReopenableFileHandler(path_abs)
_handlers.append(handler)
handler.setFormatter(formatter)
log.addHandler(handler)
def reopen():
for handler in _handlers:
handler.reopen()
|