mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
Rewritten XendLogging to not be a singleton class, and not have methods used
from nowhere at all. Log to a temporary file if permission is denied to log to /var/log/xend.log, as happens when you are not root. Fixes bug #305. Remove all the log-related garbage from XendRoot -- just about every module was going straight to XendLogging.log already, so there was no need to have XendRoot replicate this functionality. Remove XendRoot.event_handler, which hasn't been in use since the EventServer was removed. Signed-off-by: Ewan Mellor <ewan@xensource.com>
This commit is contained in:
1 parent
5910d2c460
commit
dc988367d8
4 files changed
+90
-152
No files matched your search
@@ -13,79 +13,82 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2005 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
|
||||
import tempfile
|
||||
import types
|
||||
import logging
|
||||
from logging import Formatter, StreamHandler
|
||||
from logging.handlers import RotatingFileHandler
|
||||
import logging.handlers
|
||||
|
||||
class XendLogging:
|
||||
|
||||
KB = 1024
|
||||
MB = 1024 * KB
|
||||
|
||||
maxBytes = 1 * MB
|
||||
backupCount = 5
|
||||
__all__ = [ 'log', 'init', 'getLogFilename', 'addLogStderr',
|
||||
'removeLogStderr' ]
|
||||
|
||||
logStderrFormat = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
|
||||
logFileFormat = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
|
||||
dateFormat = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
def __init__(self, filename, level=logging.INFO, maxBytes=None, backupCount=None):
|
||||
"""Initialise logging. Logs to 'filename' by default, but does not log to
|
||||
stderr unless addLogStderr() is called.
|
||||
"""
|
||||
self.setLevel(level)
|
||||
if maxBytes:
|
||||
self.maxBytes = maxBytes
|
||||
if backupCount:
|
||||
self.backupCount = backupCount
|
||||
self.initLogFile(filename)
|
||||
self.initLogStderr()
|
||||
|
||||
def setLevel(self, level):
|
||||
if isinstance(level, types.StringType):
|
||||
level = logging._levelNames[level]
|
||||
self.getLogger().setLevel(level)
|
||||
self.level = level
|
||||
|
||||
def getLogger(self):
|
||||
return logging.getLogger("xend")
|
||||
|
||||
def initLogFile(self, filename):
|
||||
"""Create the file logger and add it.
|
||||
"""
|
||||
self.logfile = RotatingFileHandler(filename,
|
||||
mode='a',
|
||||
maxBytes=self.maxBytes,
|
||||
backupCount=self.backupCount)
|
||||
self.logfilename = filename
|
||||
self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
|
||||
self.getLogger().addHandler(self.logfile)
|
||||
|
||||
def getLogFile(self):
|
||||
return self.logfile
|
||||
|
||||
def getLogFilename(self):
|
||||
return self.logfilename
|
||||
|
||||
def initLogStderr(self):
|
||||
"""Create the stderr logger, but don't add it.
|
||||
"""
|
||||
self.logstderr = StreamHandler()
|
||||
self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
|
||||
|
||||
def addLogStderr(self):
|
||||
"""Add logging to stderr."""
|
||||
self.getLogger().addHandler(self.logstderr)
|
||||
|
||||
def removeLogStderr(self):
|
||||
"""Remove logging to stderr."""
|
||||
self.getLogger().removeHandler(self.logstderr)
|
||||
|
||||
def getLogStderr(self):
|
||||
return self.logstderr
|
||||
|
||||
log = logging.getLogger("xend")
|
||||
|
||||
|
||||
|
||||
DEFAULT_MAX_BYTES = 1 << 20 # 1MB
|
||||
DEFAULT_BACKUP_COUNT = 5
|
||||
|
||||
STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
|
||||
LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
|
||||
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
|
||||
stderrHandler = logging.StreamHandler()
|
||||
stderrHandler.setFormatter(logging.Formatter(STDERR_FORMAT, DATE_FORMAT))
|
||||
|
||||
logfilename = None
|
||||
|
||||
|
||||
def init(filename, level=logging.INFO, maxBytes=None, backupCount=None):
|
||||
"""Initialise logging. Logs to 'filename' by default, but does not log to
|
||||
stderr unless addLogStderr() is called.
|
||||
"""
|
||||
|
||||
def openFileHandler(fname):
|
||||
return logging.handlers.RotatingFileHandler(fname,
|
||||
mode='a',
|
||||
maxBytes=maxBytes,
|
||||
backupCount=backupCount)
|
||||
|
||||
if not maxBytes:
|
||||
maxBytes = DEFAULT_MAX_BYTES
|
||||
if not backupCount:
|
||||
backupCount = DEFAULT_BACKUP_COUNT
|
||||
|
||||
# Rather unintuitively, getLevelName will get the number corresponding to
|
||||
# a level name, as well as getting the name corresponding to a level
|
||||
# number. setLevel seems to take the number only though, so convert if we
|
||||
# are given a string.
|
||||
if isinstance(level, types.StringType):
|
||||
level = logging.getLevelName(level)
|
||||
|
||||
log.setLevel(level)
|
||||
|
||||
try:
|
||||
fileHandler = openFileHandler(filename)
|
||||
logfilename = filename
|
||||
except IOError:
|
||||
logfilename = tempfile.mkstemp("-xend.log")[1]
|
||||
fileHandler = openFileHandler(logfilename)
|
||||
|
||||
fileHandler.setFormatter(logging.Formatter(LOGFILE_FORMAT, DATE_FORMAT))
|
||||
log.addHandler(fileHandler)
|
||||
|
||||
|
||||
def getLogFilename():
|
||||
return logfilename
|
||||
|
||||
|
||||
def addLogStderr():
|
||||
"""Add logging to stderr."""
|
||||
log.addHandler(stderrHandler)
|
||||
|
||||
|
||||
def removeLogStderr():
|
||||
"""Remove logging to stderr."""
|
||||
log.removeHandler(stderrHandler)
|
||||
@@ -13,6 +13,7 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2005 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
"""Xend root class.
|
||||
@@ -29,7 +30,7 @@ import os.path
|
||||
import string
|
||||
import sys
|
||||
|
||||
from XendLogging import XendLogging
|
||||
import XendLogging
|
||||
from XendError import XendError
|
||||
|
||||
import sxp
|
||||
@@ -92,7 +93,6 @@ class XendRoot:
|
||||
def __init__(self):
|
||||
self.config_path = None
|
||||
self.config = None
|
||||
self.logging = None
|
||||
self.configure()
|
||||
|
||||
|
||||
@@ -114,84 +114,22 @@ class XendRoot:
|
||||
"""
|
||||
return self.components.get(name)
|
||||
|
||||
def _format(self, msg, args):
|
||||
if args:
|
||||
return str(msg) % args
|
||||
else:
|
||||
return str(msg)
|
||||
|
||||
def _log(self, mode, fmt, args):
|
||||
"""Logging function that uses the logger if it exists, otherwise
|
||||
logs to stderr. We use this for XendRoot log messages because
|
||||
they may be logged before the logger has been configured.
|
||||
Other components can safely use the logger.
|
||||
def _logError(self, fmt, args):
|
||||
"""Logging function to log to stderr. We use this for XendRoot log
|
||||
messages because they may be logged before the logger has been
|
||||
configured. Other components can safely use the logger.
|
||||
"""
|
||||
log = self.get_logger()
|
||||
if mode not in ['warning', 'info', 'debug', 'error']:
|
||||
mode = 'info'
|
||||
level = mode.upper()
|
||||
if log:
|
||||
getattr(log, mode)(fmt, *args)
|
||||
else:
|
||||
print >>sys.stderr, "xend", "[%s]" % level, self._format(fmt, args)
|
||||
|
||||
def logDebug(self, fmt, *args):
|
||||
"""Log a debug message.
|
||||
|
||||
@param fmt: message format
|
||||
@param args: arguments
|
||||
"""
|
||||
self._log('debug', fmt, args)
|
||||
|
||||
def logInfo(self, fmt, *args):
|
||||
"""Log an info message.
|
||||
|
||||
@param fmt: message format
|
||||
@param args: arguments
|
||||
"""
|
||||
self._log('info', fmt, args)
|
||||
|
||||
def logWarning(self, fmt, *args):
|
||||
"""Log a warning message.
|
||||
|
||||
@param fmt: message format
|
||||
@param args: arguments
|
||||
"""
|
||||
self._log('warning', fmt, args)
|
||||
|
||||
def logError(self, fmt, *args):
|
||||
"""Log an error message.
|
||||
|
||||
@param fmt: message format
|
||||
@param args: arguments
|
||||
"""
|
||||
self._log('error', fmt, args)
|
||||
|
||||
def event_handler(self, event, val):
|
||||
self.logInfo("EVENT> %s %s", str(event), str(val))
|
||||
print >>sys.stderr, "xend [ERROR]", fmt % args
|
||||
|
||||
def configure(self):
|
||||
self.set_config()
|
||||
self.configure_logger()
|
||||
|
||||
def configure_logger(self):
|
||||
logfile = self.get_config_value("logfile", self.logfile_default)
|
||||
loglevel = self.get_config_value("loglevel", self.loglevel_default)
|
||||
self.logging = XendLogging(logfile, level=loglevel)
|
||||
XendLogging.init(logfile, level = loglevel)
|
||||
|
||||
from xen.xend.server import params
|
||||
if params.XEND_DEBUG:
|
||||
self.logging.addLogStderr()
|
||||
|
||||
def get_logging(self):
|
||||
"""Get the XendLogging instance.
|
||||
"""
|
||||
return self.logging
|
||||
|
||||
def get_logger(self):
|
||||
"""Get the logger.
|
||||
"""
|
||||
return self.logging and self.logging.getLogger()
|
||||
XendLogging.addLogStderr()
|
||||
|
||||
def set_config(self):
|
||||
"""If the config file exists, read it. If not, ignore it.
|
||||
@@ -200,7 +138,6 @@ class XendRoot:
|
||||
"""
|
||||
self.config_path = os.getenv(self.config_var, self.config_default)
|
||||
if os.path.exists(self.config_path):
|
||||
#self.logInfo('Reading config file %s', self.config_path)
|
||||
try:
|
||||
fin = file(self.config_path, 'rb')
|
||||
try:
|
||||
@@ -210,10 +147,12 @@ class XendRoot:
|
||||
config.insert(0, 'xend-config')
|
||||
self.config = config
|
||||
except Exception, ex:
|
||||
self.logError('Reading config file %s: %s', self.config_path, str(ex))
|
||||
self._logError('Reading config file %s: %s',
|
||||
self.config_path, str(ex))
|
||||
raise
|
||||
else:
|
||||
self.logError('Config file does not exist: %s', self.config_path)
|
||||
self._logError('Config file does not exist: %s',
|
||||
self.config_path)
|
||||
self.config = ['xend-config']
|
||||
|
||||
def get_config(self, name=None):
|
||||
@@ -339,11 +278,6 @@ def instance():
|
||||
inst = XendRoot()
|
||||
return inst
|
||||
|
||||
def logger():
|
||||
"""Get the logger.
|
||||
"""
|
||||
return instance().get_logger()
|
||||
|
||||
def add_component(name, val):
|
||||
"""Register a component with XendRoot.
|
||||
This is used to work-round import cycles.
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2005 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
from xen.web import static
|
||||
|
||||
from xen.xend import XendRoot
|
||||
from xen.xend import XendLogging
|
||||
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
@@ -27,8 +28,8 @@ class SrvXendLog(SrvDir):
|
||||
|
||||
def __init__(self):
|
||||
SrvDir.__init__(self)
|
||||
logging = XendRoot.instance().get_logging()
|
||||
self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
|
||||
self.logfile = static.File(XendLogging.getLogFilename(),
|
||||
defaultType="text/plain")
|
||||
self.logfile.type = "text/plain"
|
||||
self.logfile.encoding = None
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from xen.xend import scheduler
|
||||
from xen.xend import sxp
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend import XendLogging
|
||||
from xen.xend import XendRoot
|
||||
|
||||
|
||||
@@ -146,11 +147,10 @@ class EventProtocol(protocol.Protocol):
|
||||
|
||||
def op_log_stderr(self, _, v):
|
||||
mode = v[1]
|
||||
logging = xroot.get_logging()
|
||||
if mode == 'on':
|
||||
logging.addLogStderr()
|
||||
XendLogging.addLogStderr()
|
||||
else:
|
||||
logging.removeLogStderr()
|
||||
XendLogging.removeLogStderr()
|
||||
|
||||
def op_domain_ls(self, _1, _2):
|
||||
xd = xroot.get_component("xen.xend.XendDomain")
|
||||
|
||||