7
# A level more detailed than DEBUG
9
# A level more detailed than INFO
13
class FlexGetLogger(logging.Logger):
14
"""Custom logger that adds feed and execution info to log records."""
15
local = threading.local()
17
def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
18
extra = {'feed': getattr(FlexGetLogger.local, 'feed', u''),
19
'execution': getattr(FlexGetLogger.local, 'execution', '')}
20
return logging.Logger.makeRecord(self, name, level, fn, lno, msg, args, exc_info, func, extra)
22
def trace(self, msg, *args, **kwargs):
23
"""Log at TRACE level (more detailed than DEBUG)."""
24
self.log(TRACE, msg, *args, **kwargs)
26
def verbose(self, msg, *args, **kwargs):
27
"""Log at VERBOSE level (displayed when FlexGet is run interactively.)"""
28
self.log(VERBOSE, msg, *args, **kwargs)
30
# backwards compatibility
34
class FlexGetFormatter(logging.Formatter):
35
"""Custom formatter that can handle both regular log records and those created by FlexGetLogger"""
36
plain_fmt = '%(asctime)-15s %(levelname)-8s %(name)-29s %(message)s'
37
flexget_fmt = '%(asctime)-15s %(levelname)-8s %(name)-13s %(feed)-15s %(message)s'
40
logging.Formatter.__init__(self, self.plain_fmt, '%Y-%m-%d %H:%M')
42
def format(self, record):
43
if hasattr(record, 'feed'):
44
self._fmt = self.flexget_fmt
46
self._fmt = self.plain_fmt
47
return logging.Formatter.format(self, record)
50
def set_execution(execution):
51
FlexGetLogger.local.execution = execution
55
FlexGetLogger.local.feed = feed
58
class PrivacyFilter(logging.Filter):
59
"""Edits log messages and <hides> obviously private information."""
65
s = '([?&]%s=)\w+' % name
67
self.replaces.append(p)
69
for param in ['passwd', 'password', 'pw', 'pass', 'passkey',
70
'key', 'apikey', 'user', 'username', 'uname', 'login', 'id']:
73
def filter(self, record):
74
if not isinstance(record.msg, basestring):
76
for p in self.replaces:
77
record.msg = p.sub(r'\g<1><hidden>', record.msg)
78
record.msg = record.msg
81
_logging_configured = False
83
_logging_started = False
86
def initialize(unit_test=False):
89
global _logging_configured, _mem_handler
91
if _logging_configured:
94
logging.addLevelName(TRACE, 'TRACE')
95
logging.addLevelName(VERBOSE, 'VERBOSE')
96
_logging_configured = True
98
# with unit test we want a bit simpler setup
100
logging.basicConfig()
104
logger = logging.getLogger()
105
formatter = FlexGetFormatter()
107
_mem_handler = logging.handlers.MemoryHandler(1000 * 1000, 100)
108
_mem_handler.setFormatter(formatter)
109
logger.addHandler(_mem_handler)
112
# Process commandline options, unfortunately we need to do it before optparse is available
115
# turn on debug level
116
if '--debug' in sys.argv:
117
logger.setLevel(logging.DEBUG)
118
elif '--debug-trace' in sys.argv:
119
logger.setLevel(TRACE)
120
elif '--cron' not in sys.argv:
121
logger.setLevel(VERBOSE)
123
logger.setLevel(logging.INFO)
125
# without --cron we log to console
126
# this must be done at initialize because otherwise there will be too much delay (user feedback) (see #1113)
127
if not '--cron' in sys.argv:
128
console = logging.StreamHandler()
129
console.setFormatter(formatter)
130
logger.addHandler(console)
133
def start(filename=None, level=logging.INFO, debug=False):
134
"""After initialization, start file logging.
136
global _logging_started
138
assert _logging_configured
143
handler = logging.StreamHandler()
145
handler = logging.handlers.RotatingFileHandler(filename, maxBytes=1000 * 1024, backupCount=9)
147
handler.setFormatter(_mem_handler.formatter)
149
_mem_handler.setTarget(handler)
152
logger = logging.getLogger()
153
logger.removeHandler(_mem_handler)
154
logger.addHandler(handler)
155
logger.addFilter(PrivacyFilter())
156
logger.setLevel(level)
158
# flush what we have stored from the plugin initialization
160
_logging_started = True
163
def flush_logging_to_console():
164
"""Flushes memory logger to console"""
165
console = logging.StreamHandler()
166
console.setFormatter(_mem_handler.formatter)
167
logger = logging.getLogger()
168
logger.addHandler(console)
169
if len(_mem_handler.buffer) > 0:
170
for record in _mem_handler.buffer:
171
console.handle(record)
174
# Set our custom logger class as default
175
logging.setLoggerClass(FlexGetLogger)