This module abstracts the logging handling away from the rest of the
Ganeti code. It offers some utility functions for easy logging.
+
"""
# pylint: disable-msg=W0603,C0103
import sys
import logging
-import os, os.path
-
-from ganeti import constants
-
-_program = '(unknown)'
-_errlog = None
-_inflog = None
-_dbglog = None
-_stdout = None
-_stderr = None
-_debug = False
-
-
-def _SetDestination(name, filename, stream=None):
- """Configure the destination for a given logger
-
- This function configures the logging destination for a given loger.
- Parameters:
- - name: the logger name
- - filename: if not empty, log messages will be written (also) to this file
- - stream: if not none, log messages will be output (also) to this stream
-
- Returns:
- - the logger identified by the `name` argument
- """
- ret = logging.getLogger(name)
-
- if filename:
- fmtr = logging.Formatter('%(asctime)s %(message)s')
-
- hdlr = logging.FileHandler(filename)
- hdlr.setFormatter(fmtr)
- ret.addHandler(hdlr)
-
- if stream:
- if name in ('error', 'info', 'debug'):
- fmtr = logging.Formatter('%(asctime)s %(message)s')
- else:
- fmtr = logging.Formatter('%(message)s')
- hdlr = logging.StreamHandler(stream)
- hdlr.setFormatter(fmtr)
- ret.addHandler(hdlr)
-
- ret.setLevel(logging.INFO)
- return ret
+def SetupLogging(logfile, debug=False, stderr_logging=False, program=""):
+ """Configures the logging module.
-def _GenericSetup(program, errfile, inffile, dbgfile,
- twisted_workaround=False):
- """Configure logging based on arguments
-
- Arguments:
- - name of program
- - error log filename
- - info log filename
- - debug log filename
- - twisted_workaround: if true, emit all messages to stderr
"""
- global _program
- global _errlog
- global _inflog
- global _dbglog
- global _stdout
- global _stderr
-
- _program = program
- if twisted_workaround:
- _errlog = _SetDestination('error', None, sys.stderr)
- _inflog = _SetDestination('info', None, sys.stderr)
- _dbglog = _SetDestination('debug', None, sys.stderr)
+ fmt = "%(asctime)s: " + program + " "
+ if debug:
+ fmt += ("pid=%(process)d/%(threadName)s %(levelname)s"
+ " %(module)s:%(lineno)s %(message)s")
else:
- _errlog = _SetDestination('error', errfile)
- _inflog = _SetDestination('info', inffile)
- _dbglog = _SetDestination('debug', dbgfile)
-
- _stdout = _SetDestination('user', None, sys.stdout)
- _stderr = _SetDestination('stderr', None, sys.stderr)
-
-
-def SetupLogging(twisted_workaround=False, debug=False, program='ganeti'):
- """Setup logging for ganeti
+ fmt += "pid=%(process)d %(levelname)s %(message)s"
+ formatter = logging.Formatter(fmt)
- On failure, a check is made whether process is run by root or not,
- and an appropriate error message is printed on stderr, then process
- exits.
+ root_logger = logging.getLogger("")
+ root_logger.setLevel(logging.NOTSET)
- This function is just a wraper over `_GenericSetup()` using specific
- arguments.
-
- Parameter:
- twisted_workaround: passed to `_GenericSetup()`
+ if stderr_logging:
+ stderr_handler = logging.StreamHandler()
+ stderr_handler.setFormatter(formatter)
+ if debug:
+ stderr_handler.setLevel(logging.NOTSET)
+ else:
+ stderr_handler.setLevel(logging.CRITICAL)
+ root_logger.addHandler(stderr_handler)
- """
+ # this can fail, if the logging directories are not setup or we have
+ # a permisssion problem; in this case, it's best to log but ignore
+ # the error if stderr_logging is True, and if false we re-raise the
+ # exception since otherwise we could run but without any logs at all
try:
- _GenericSetup(program,
- os.path.join(constants.LOG_DIR, "errors"),
- os.path.join(constants.LOG_DIR, "info"),
- os.path.join(constants.LOG_DIR, "debug"),
- twisted_workaround)
- except IOError:
- # The major reason to end up here is that we're being run as a
- # non-root user. We might also get here if xen has not been
- # installed properly. This is not the correct place to enforce
- # being run by root; nevertheless, here makes sense because here
- # is where we first notice it.
- if os.getuid() != 0:
- sys.stderr.write('This program must be run by the superuser.\n')
+ logfile_handler = logging.FileHandler(logfile)
+ logfile_handler.setFormatter(formatter)
+ if debug:
+ logfile_handler.setLevel(logging.DEBUG)
else:
- sys.stderr.write('Unable to open log files. Incomplete system?\n')
-
- sys.exit(2)
-
- global _debug
- _debug = debug
-
-
-def _WriteEntry(log, txt):
- """
- Write a message to a given log.
- Splits multi-line messages up into a series of log writes, to
- keep consistent format on lines in file.
-
- Parameters:
- - log: the destination log
- - txt: the message
-
- """
- if log is None:
- sys.stderr.write("Logging system not initialized while processing"
- " message:\n")
- sys.stderr.write("%s\n" % txt)
- return
-
- lines = txt.split('\n')
-
- spaces = ' ' * len(_program) + '| '
+ logfile_handler.setLevel(logging.INFO)
+ root_logger.addHandler(logfile_handler)
+ except EnvironmentError, err:
+ if stderr_logging:
+ logging.exception("Failed to enable logging to file '%s'", logfile)
+ else:
+ # we need to re-raise the exception
+ raise
- lines = ([ _program + ': ' + lines[0] ] +
- map(lambda a: spaces + a, lines[1:]))
- for line in lines:
- log.log(logging.INFO, line)
+# Backwards compatibility
+Error = logging.error
+Info = logging.info
+Debug = logging.debug
def ToStdout(txt):
"""
sys.stderr.write(txt + '\n')
sys.stderr.flush()
-
-
-def Error(txt):
- """Write a message to our error log
-
- Parameters:
- - dbg: if true, the message will also be output to stderr
- - txt: the log message
-
- """
- _WriteEntry(_errlog, txt)
- sys.stderr.write(txt + '\n')
-
-
-def Info(txt):
- """Write a message to our general messages log
-
- If the global debug flag is true, the log message will also be
- output to stderr.
-
- Parameters:
- - txt: the log message
-
- """
- _WriteEntry(_inflog, txt)
- if _debug:
- _WriteEntry(_stderr, txt)
-
-
-def Debug(txt):
- """Write a message to the debug log
-
- If the global debug flag is true, the log message will also be
- output to stderr.
-
- Parameters:
- - txt: the log message
-
- """
- _WriteEntry(_dbglog, txt)
- if _debug:
- _WriteEntry(_stderr, txt)