示例#1
0
def default_logging(gevent_in_use=True, syslog_executable_name=None):
    """
    Sets up the Calico default logging, with default severities.

    Our default logging consists of:

    - setting the log level of the root logger to DEBUG (a safe initial value)
    - attaching a SysLog handler with no formatter (log to syslog), ERROR level
      only
    - attaching a StreamHandler with the Calico formatter, to log to stdout,
      with ERROR level

    This default explicitly excludes adding logging to file. This is because
    working out what file to log to requires reading the configuration file,
    and doing that may cause errors that we want to log! To add a file logger,
    call :meth:`complete_logging() <calico.common.complete_logging>` after
    this function has been called.
    """
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.DEBUG)

    executable_name = syslog_executable_name or os.path.basename(sys.argv[0])
    syslog_format = SYSLOG_FORMAT_STRING.format(excname=executable_name)
    syslog_formatter = logging.Formatter(syslog_format)
    if os.path.exists("/dev/log"):
        syslog_handler = logging.handlers.SysLogHandler(address='/dev/log')
    else:
        # Probably unit tests running on windows.
        syslog_handler = logging.handlers.SysLogHandler()
    syslog_handler.setLevel(logging.ERROR)
    syslog_handler.setFormatter(syslog_formatter)

    root_logger.addHandler(syslog_handler)

    format_string = FORMAT_STRING_GEVENT if gevent_in_use else FORMAT_STRING
    file_formatter = logging.Formatter(format_string)
    stream_handler = logging.StreamHandler(sys.stdout)
    stream_handler.setLevel(logging.ERROR)
    stream_handler.setFormatter(file_formatter)
    if gevent_in_use:
        from geventutils import GreenletFilter
        stream_handler.addFilter(GreenletFilter())
    root_logger.addHandler(stream_handler)
示例#2
0
def complete_logging(logfile=None,
                     file_level=logging.DEBUG,
                     syslog_level=logging.ERROR,
                     stream_level=logging.ERROR,
                     gevent_in_use=True):
    """
    Updates the logging configuration based on learned configuration.

    The purpose of this function is to update the previously set logging
    configuration such that we can start logging to file. This is done in a
    separate step to the initial logging configuration in order to ensure that
    logging is available as early in execution as possible, i.e. before the
    config file has been parsed.

    This function must only be called once, after
    :meth:`default_logging() <calico.common.default_logging>`
    has been called.

    The xyz_level parameters may be a valid logging level DEBUG/INFO/... or
    None to disable that log entirely.  Note: the config module supports
    using the string "none" in the configuration to disable logging.
    """
    root_logger = logging.getLogger()

    # If default_logging got called already, we'll have some loggers in place.
    # Update their levels.
    file_handler = None
    for handler in root_logger.handlers[:]:
        if isinstance(handler, logging.handlers.SysLogHandler):
            if syslog_level is None:
                root_logger.removeHandler(handler)
            else:
                handler.setLevel(syslog_level)
        elif isinstance(handler, logging.StreamHandler):
            if stream_level is None:
                root_logger.removeHandler(handler)
            else:
                handler.setLevel(stream_level)
        elif isinstance(handler, logging.handlers.WatchedFileHandler):
            file_handler = handler
            if file_level is None:
                root_logger.removeHandler(handler)
            else:
                handler.setLevel(file_level)

    # If we've been given a log file, log to file as well.
    if logfile and file_level is not None:
        if not file_handler:
            mkdir_p(os.path.dirname(logfile))
            format_string = (FORMAT_STRING_GEVENT if gevent_in_use
                             else FORMAT_STRING)
            formatter = logging.Formatter(format_string)
            file_handler = logging.handlers.WatchedFileHandler(logfile)
            if gevent_in_use:
                from geventutils import GreenletFilter
                file_handler.addFilter(GreenletFilter())
            file_handler.setLevel(file_level)
            file_handler.setFormatter(formatter)
            root_logger.addHandler(file_handler)

    # Optimization: disable all logging below the minimum level that we care
    # about.  The global "disable" setting is the first thing that gets checked
    # in the logging framework so it's the fastest way to disable logging.
    levels = [file_level, syslog_level, stream_level]
    # Map None to something greater than the highest logging level.
    levels = [l if l is not None else logging.CRITICAL + 1 for l in levels]
    min_log_level = min(levels)
    logging.disable(min_log_level - 1)

    _log.info("Logging initialized")