Source code for structlog.stdlib

# Copyright 2013 Hynek Schlawack
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Processors and helpers specific to the `logging module
<http://docs.python.org/2/library/logging.html>`_ from the `Python standard
library <http://docs.python.org/>`_.
"""

from __future__ import absolute_import, division, print_function

import logging

from structlog._base import BoundLoggerBase
from structlog._exc import DropEvent
from structlog._compat import PY3
from structlog._frames import _format_stack, _find_first_app_frame_and_name


class _FixedFindCallerLogger(logging.Logger):
    """
    Change the behavior of findCaller to cope with structlog's extra frames.
    """
    def findCaller(self, stack_info=False):
        """
        Finds the first caller frame outside of structlog so that the caller
        info is populated for wrapping stdlib.
        This logger gets set as the default one when using LoggerFactory.
        """
        f, name = _find_first_app_frame_and_name(['logging'])
        if PY3:  # pragma: nocover
            if stack_info:
                sinfo = _format_stack(f)
            else:
                sinfo = None
            return f.f_code.co_filename, f.f_lineno, f.f_code.co_name, sinfo
        else:
            return f.f_code.co_filename, f.f_lineno, f.f_code.co_name


[docs]class BoundLogger(BoundLoggerBase): """ Python Standard Library version of :class:`structlog.BoundLogger`. Works exactly like the generic one except that it takes advantage of knowing the logging methods in advance. Use it like:: configure( wrapper_class=structlog.stdlib.BoundLogger, ) """ def debug(self, event=None, **kw): """ Process event and call ``Logger.debug()`` with the result. """ return self._proxy_to_logger('debug', event, **kw) def info(self, event=None, **kw): """ Process event and call ``Logger.info()`` with the result. """ return self._proxy_to_logger('info', event, **kw) def warning(self, event=None, **kw): """ Process event and call ``Logger.warning()`` with the result. """ return self._proxy_to_logger('warning', event, **kw) warn = warning def error(self, event=None, **kw): """ Process event and call ``Logger.error()`` with the result. """ return self._proxy_to_logger('error', event, **kw) def critical(self, event=None, **kw): """ Process event and call ``Logger.critical()`` with the result. """ return self._proxy_to_logger('critical', event, **kw)
[docs]class LoggerFactory(object): """ Build a standard library logger when an *instance* is called. Sets a custom logger using `logging.setLogggerClass` so variables in log format are expanded properly. >>> from structlog import configure >>> from structlog.stdlib import LoggerFactory >>> configure(logger_factory=LoggerFactory()) :param ignore_frame_names: When guessing the name of a logger, skip frames whose names *start* with one of these. For example, in pyramid applications you'll want to set it to ``['venusian', 'pyramid.config']``. :type ignore_frame_names: `list` of `str` """ def __init__(self, ignore_frame_names=None): self._ignore = ignore_frame_names logging.setLoggerClass(_FixedFindCallerLogger)
[docs] def __call__(self, *args): """ Deduce the caller's module name and create a stdlib logger. If an optional argument is passed, it will be used as the logger name instead of guesswork. This optional argument would be passed from the :func:`structlog.get_logger` call. For example ``struclog.get_logger('foo')`` would cause this method to be called with ``'foo'`` as its first positional argument. :rtype: `logging.Logger` .. versionchanged:: 0.4.0 Added support for optional positional arguments. Using the first one for naming the constructed logger. """ if args: return logging.getLogger(args[0]) # We skip all frames that originate from within structlog or one of the # configured names. _, name = _find_first_app_frame_and_name(self._ignore) return logging.getLogger(name) # Adapted from the stdlib
CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 _nameToLevel = { 'critical': CRITICAL, 'error': ERROR, 'warn': WARNING, 'warning': WARNING, 'info': INFO, 'debug': DEBUG, 'notset': NOTSET, }
[docs]def filter_by_level(logger, name, event_dict): """ Check whether logging is configured to accept messages from this log level. Should be the first processor if stdlib's filtering by level is used so possibly expensive processors like exception formatters are avoided in the first place. >>> import logging >>> from structlog.stdlib import filter_by_level >>> logging.basicConfig(level=logging.WARN) >>> logger = logging.getLogger() >>> filter_by_level(logger, 'warn', {}) {} >>> filter_by_level(logger, 'debug', {}) Traceback (most recent call last): ... DropEvent """ if logger.isEnabledFor(_nameToLevel[name]): return event_dict else: raise DropEvent
Read the Docs v: 0.4.0
Versions
latest
0.4.0
0.3.2
0.3.1
0.3.0-0
0.2.0-0
0.1.0
Downloads
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.