File: //lib/python3/dist-packages/twisted/logger/_logger.py
# -*- test-case-name: twisted.logger.test.test_logger -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Logger class.
"""
from time import time
from twisted.python.compat import currentframe
from twisted.python.failure import Failure
from ._levels import InvalidLogLevelError, LogLevel
class Logger(object):
    """
    A L{Logger} emits log messages to an observer.  You should instantiate it
    as a class or module attribute, as documented in L{this module's
    documentation <twisted.logger>}.
    @type namespace: L{str}
    @ivar namespace: the namespace for this logger
    @type source: L{object}
    @ivar source: The object which is emitting events via this logger
    @type: L{ILogObserver}
    @ivar observer: The observer that this logger will send events to.
    """
    @staticmethod
    def _namespaceFromCallingContext():
        """
        Derive a namespace from the module containing the caller's caller.
        @return: the fully qualified python name of a module.
        @rtype: L{str} (native string)
        """
        try:
            return currentframe(2).f_globals["__name__"]
        except KeyError:
            return "<unknown>"
    def __init__(self, namespace=None, source=None, observer=None):
        """
        @param namespace: The namespace for this logger.  Uses a dotted
            notation, as used by python modules.  If not L{None}, then the name
            of the module of the caller is used.
        @type namespace: L{str} (native string)
        @param source: The object which is emitting events via this
            logger; this is automatically set on instances of a class
            if this L{Logger} is an attribute of that class.
        @type source: L{object}
        @param observer: The observer that this logger will send events to.
            If L{None}, use the L{global log publisher <globalLogPublisher>}.
        @type observer: L{ILogObserver}
        """
        if namespace is None:
            namespace = self._namespaceFromCallingContext()
        self.namespace = namespace
        self.source = source
        if observer is None:
            from ._global import globalLogPublisher
            self.observer = globalLogPublisher
        else:
            self.observer = observer
    def __get__(self, oself, type=None):
        """
        When used as a descriptor, i.e.::
            # File: athing.py
            class Something(object):
                log = Logger()
                def hello(self):
                    self.log.info("Hello")
        a L{Logger}'s namespace will be set to the name of the class it is
        declared on.  In the above example, the namespace would be
        C{athing.Something}.
        Additionally, its source will be set to the actual object referring to
        the L{Logger}.  In the above example, C{Something.log.source} would be
        C{Something}, and C{Something().log.source} would be an instance of
        C{Something}.
        """
        if oself is None:
            source = type
        else:
            source = oself
        return self.__class__(
            ".".join([type.__module__, type.__name__]),
            source,
            observer=self.observer,
        )
    def __repr__(self):
        return "<%s %r>" % (self.__class__.__name__, self.namespace)
    def emit(self, level, format=None, **kwargs):
        """
        Emit a log event to all log observers at the given level.
        @param level: a L{LogLevel}
        @param format: a message format using new-style (PEP 3101)
            formatting.  The logging event (which is a L{dict}) is
            used to render this format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        if level not in LogLevel.iterconstants():
            self.failure(
                "Got invalid log level {invalidLevel!r} in {logger}.emit().",
                Failure(InvalidLogLevelError(level)),
                invalidLevel=level,
                logger=self,
            )
            return
        event = kwargs
        event.update(
            log_logger=self, log_level=level, log_namespace=self.namespace,
            log_source=self.source, log_format=format, log_time=time(),
        )
        if "log_trace" in event:
            event["log_trace"].append((self, self.observer))
        self.observer(event)
    def failure(self, format, failure=None, level=LogLevel.critical, **kwargs):
        """
        Log a failure and emit a traceback.
        For example::
            try:
                frob(knob)
            except Exception:
                log.failure("While frobbing {knob}", knob=knob)
        or::
            d = deferredFrob(knob)
            d.addErrback(lambda f: log.failure, "While frobbing {knob}",
                         f, knob=knob)
        This method is generally meant to capture unexpected exceptions in
        code; an exception that is caught and handled somehow should be logged,
        if appropriate, via L{Logger.error} instead.  If some unknown exception
        occurs and your code doesn't know how to handle it, as in the above
        example, then this method provides a means to describe the failure in
        nerd-speak.  This is done at L{LogLevel.critical} by default, since no
        corrective guidance can be offered to an user/administrator, and the
        impact of the condition is unknown.
        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.
        @param failure: a L{Failure} to log.  If L{None}, a L{Failure} is
            created from the exception in flight.
        @param level: a L{LogLevel} to use.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        if failure is None:
            failure = Failure()
        self.emit(level, format, log_failure=failure, **kwargs)
    def debug(self, format=None, **kwargs):
        """
        Emit a log event at log level L{LogLevel.debug}.
        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        self.emit(LogLevel.debug, format, **kwargs)
    def info(self, format=None, **kwargs):
        """
        Emit a log event at log level L{LogLevel.info}.
        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        self.emit(LogLevel.info, format, **kwargs)
    def warn(self, format=None, **kwargs):
        """
        Emit a log event at log level L{LogLevel.warn}.
        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        self.emit(LogLevel.warn, format, **kwargs)
    def error(self, format=None, **kwargs):
        """
        Emit a log event at log level L{LogLevel.error}.
        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        self.emit(LogLevel.error, format, **kwargs)
    def critical(self, format=None, **kwargs):
        """
        Emit a log event at log level L{LogLevel.critical}.
        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        """
        self.emit(LogLevel.critical, format, **kwargs)
_log = Logger()
_loggerFor = lambda obj:_log.__get__(obj, obj.__class__)