123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- # 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.
- import logging
- import logging.config
- import logging.handlers
- import sys
- import traceback
- import weakref
- from daiquiri import output
- class KeywordArgumentAdapter(logging.LoggerAdapter):
- """Logger adapter to add keyword arguments to log record's extra data
- Keywords passed to the log call are added to the "extra"
- dictionary passed to the underlying logger so they are emitted
- with the log message and available to the format string.
- Special keywords:
- extra
- An existing dictionary of extra values to be passed to the
- logger. If present, the dictionary is copied and extended.
- """
- def process(self, msg, kwargs):
- # Make a new extra dictionary combining the values we were
- # given when we were constructed and anything from kwargs.
- extra = self.extra.copy()
- if 'extra' in kwargs:
- extra.update(kwargs.pop('extra'))
- # Move any unknown keyword arguments into the extra
- # dictionary.
- for name in list(kwargs.keys()):
- if name == 'exc_info':
- continue
- extra[name] = kwargs.pop(name)
- extra['_daiquiri_extra_keys'] = set(extra.keys())
- kwargs['extra'] = extra
- return msg, kwargs
- if sys.version_info.major == 2:
- def setLevel(self, level):
- """
- Set the specified level on the underlying logger.
- """
- self.logger.setLevel(level)
- _LOGGERS = weakref.WeakValueDictionary()
- def getLogger(name=None, **kwargs):
- """Build a logger with the given name.
- :param name: The name for the logger. This is usually the module
- name, ``__name__``.
- :type name: string
- """
- adapter = _LOGGERS.get(name)
- if not adapter:
- # NOTE(jd) Keep using the `adapter' variable here because so it's not
- # collected by Python since _LOGGERS contains only a weakref
- adapter = KeywordArgumentAdapter(logging.getLogger(name), kwargs)
- _LOGGERS[name] = adapter
- return adapter
- def setup(level=logging.WARNING, outputs=[output.STDERR], program_name=None,
- capture_warnings=True):
- """Setup Python logging.
- This will setup basic handlers for Python logging.
- :param level: Root log level.
- :param outputs: Iterable of outputs to log to.
- :param program_name: The name of the program. Auto-detected if not set.
- :param capture_warnings: Capture warnings from the `warnings' module.
- """
- root_logger = logging.getLogger(None)
- # Remove all handlers
- for handler in list(root_logger.handlers):
- root_logger.removeHandler(handler)
- # Add configured handlers
- for out in outputs:
- if isinstance(out, str):
- out = output.preconfigured.get(out)
- if out is None:
- raise RuntimeError("Output {} is not available".format(out))
- out.add_to_logger(root_logger)
- root_logger.setLevel(level)
- program_logger = logging.getLogger(program_name)
- def logging_excepthook(exc_type, value, tb):
- program_logger.critical(
- "".join(traceback.format_exception(exc_type, value, tb)))
- sys.excepthook = logging_excepthook
- if capture_warnings:
- logging.captureWarnings(True)
- def parse_and_set_default_log_levels(default_log_levels, separator='='):
- """Set default log levels for some loggers.
- :param default_log_levels: List of strings with format
- <logger_name><separator><log_level>
- """
- return set_default_log_levels((pair.split(separator, 1)
- for pair in default_log_levels))
- def set_default_log_levels(loggers_and_log_levels):
- """Set default log levels for some loggers.
- :param loggers_and_log_levels: List of tuple (logger name, level).
- """
- for logger, level in loggers_and_log_levels:
- if isinstance(level, str):
- level = level.upper()
- logging.getLogger(logger).setLevel(level)
|