mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 21:21:15 -07:00
195 lines
6.1 KiB
Python
195 lines
6.1 KiB
Python
#
|
|
# Copyright (C) 2010-2013 Vinay Sajip. See LICENSE.txt for details.
|
|
#
|
|
"""
|
|
The logutils package provides a set of handlers for the Python standard
|
|
library's logging package.
|
|
|
|
Some of these handlers are out-of-scope for the standard library, and
|
|
so they are packaged here. Others are updated versions which have
|
|
appeared in recent Python releases, but are usable with older versions
|
|
of Python, and so are packaged here.
|
|
"""
|
|
import logging
|
|
from string import Template
|
|
|
|
__version__ = '0.3.3'
|
|
|
|
class NullHandler(logging.Handler):
|
|
"""
|
|
This handler does nothing. It's intended to be used to avoid the
|
|
"No handlers could be found for logger XXX" one-off warning. This is
|
|
important for library code, which may contain code to log events. If a user
|
|
of the library does not configure logging, the one-off warning might be
|
|
produced; to avoid this, the library developer simply needs to instantiate
|
|
a NullHandler and add it to the top-level logger of the library module or
|
|
package.
|
|
"""
|
|
|
|
def handle(self, record):
|
|
"""
|
|
Handle a record. Does nothing in this class, but in other
|
|
handlers it typically filters and then emits the record in a
|
|
thread-safe way.
|
|
"""
|
|
pass
|
|
|
|
def emit(self, record):
|
|
"""
|
|
Emit a record. This does nothing and shouldn't be called during normal
|
|
processing, unless you redefine :meth:`~logutils.NullHandler.handle`.
|
|
"""
|
|
pass
|
|
|
|
def createLock(self):
|
|
"""
|
|
Since this handler does nothing, it has no underlying I/O to protect
|
|
against multi-threaded access, so this method returns `None`.
|
|
"""
|
|
self.lock = None
|
|
|
|
class PercentStyle(object):
|
|
|
|
default_format = '%(message)s'
|
|
asctime_format = '%(asctime)s'
|
|
|
|
def __init__(self, fmt):
|
|
self._fmt = fmt or self.default_format
|
|
|
|
def usesTime(self):
|
|
return self._fmt.find(self.asctime_format) >= 0
|
|
|
|
def format(self, record):
|
|
return self._fmt % record.__dict__
|
|
|
|
class StrFormatStyle(PercentStyle):
|
|
default_format = '{message}'
|
|
asctime_format = '{asctime}'
|
|
|
|
def format(self, record):
|
|
return self._fmt.format(**record.__dict__)
|
|
|
|
|
|
class StringTemplateStyle(PercentStyle):
|
|
default_format = '${message}'
|
|
asctime_format = '${asctime}'
|
|
|
|
def __init__(self, fmt):
|
|
self._fmt = fmt or self.default_format
|
|
self._tpl = Template(self._fmt)
|
|
|
|
def usesTime(self):
|
|
fmt = self._fmt
|
|
return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_format) >= 0
|
|
|
|
def format(self, record):
|
|
return self._tpl.substitute(**record.__dict__)
|
|
|
|
_STYLES = {
|
|
'%': PercentStyle,
|
|
'{': StrFormatStyle,
|
|
'$': StringTemplateStyle
|
|
}
|
|
|
|
class Formatter(logging.Formatter):
|
|
"""
|
|
Subclasses Formatter in Pythons earlier than 3.2 in order to give
|
|
3.2 Formatter behaviour with respect to allowing %-, {} or $-
|
|
formatting.
|
|
"""
|
|
def __init__(self, fmt=None, datefmt=None, style='%'):
|
|
"""
|
|
Initialize the formatter with specified format strings.
|
|
|
|
Initialize the formatter either with the specified format string, or a
|
|
default as described above. Allow for specialized date formatting with
|
|
the optional datefmt argument (if omitted, you get the ISO8601 format).
|
|
|
|
Use a style parameter of '%', '{' or '$' to specify that you want to
|
|
use one of %-formatting, :meth:`str.format` (``{}``) formatting or
|
|
:class:`string.Template` formatting in your format string.
|
|
"""
|
|
if style not in _STYLES:
|
|
raise ValueError('Style must be one of: %s' % ','.join(
|
|
_STYLES.keys()))
|
|
self._style = _STYLES[style](fmt)
|
|
self._fmt = self._style._fmt
|
|
self.datefmt = datefmt
|
|
|
|
def usesTime(self):
|
|
"""
|
|
Check if the format uses the creation time of the record.
|
|
"""
|
|
return self._style.usesTime()
|
|
|
|
def formatMessage(self, record):
|
|
return self._style.format(record)
|
|
|
|
def format(self, record):
|
|
"""
|
|
Format the specified record as text.
|
|
|
|
The record's attribute dictionary is used as the operand to a
|
|
string formatting operation which yields the returned string.
|
|
Before formatting the dictionary, a couple of preparatory steps
|
|
are carried out. The message attribute of the record is computed
|
|
using LogRecord.getMessage(). If the formatting string uses the
|
|
time (as determined by a call to usesTime(), formatTime() is
|
|
called to format the event time. If there is exception information,
|
|
it is formatted using formatException() and appended to the message.
|
|
"""
|
|
record.message = record.getMessage()
|
|
if self.usesTime():
|
|
record.asctime = self.formatTime(record, self.datefmt)
|
|
s = self.formatMessage(record)
|
|
if record.exc_info:
|
|
# Cache the traceback text to avoid converting it multiple times
|
|
# (it's constant anyway)
|
|
if not record.exc_text:
|
|
record.exc_text = self.formatException(record.exc_info)
|
|
if record.exc_text:
|
|
if s[-1:] != "\n":
|
|
s = s + "\n"
|
|
s = s + record.exc_text
|
|
return s
|
|
|
|
|
|
class BraceMessage(object):
|
|
def __init__(self, fmt, *args, **kwargs):
|
|
self.fmt = fmt
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
self.str = None
|
|
|
|
def __str__(self):
|
|
if self.str is None:
|
|
self.str = self.fmt.format(*self.args, **self.kwargs)
|
|
return self.str
|
|
|
|
class DollarMessage(object):
|
|
def __init__(self, fmt, **kwargs):
|
|
self.fmt = fmt
|
|
self.kwargs = kwargs
|
|
self.str = None
|
|
|
|
def __str__(self):
|
|
if self.str is None:
|
|
self.str = Template(self.fmt).substitute(**self.kwargs)
|
|
return self.str
|
|
|
|
|
|
def hasHandlers(logger):
|
|
"""
|
|
See if a logger has any handlers.
|
|
"""
|
|
rv = False
|
|
while logger:
|
|
if logger.handlers:
|
|
rv = True
|
|
break
|
|
elif not logger.propagate:
|
|
break
|
|
else:
|
|
logger = logger.parent
|
|
return rv
|
|
|