From 393aedb7ace6843b637aca7d156ffb9a430e671f Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Tue, 10 Jan 2012 13:42:03 -0800 Subject: adding logging from configuration files, default logging per common --- bin/keystone | 9 +++-- etc/keystone.conf | 11 ++++++ etc/logging.conf.sample | 54 +++++++++++++++++++++++++++++ keystone/cfg.py | 4 +++ keystone/config.py | 92 +++++++++++++++++++++++++++++++++++++------------ keystone/logging.py | 3 ++ tools/pip-requires | 2 ++ tools/pip-requires-test | 2 ++ 8 files changed, 153 insertions(+), 24 deletions(-) create mode 100644 etc/logging.conf.sample diff --git a/bin/keystone b/bin/keystone index 881e5175..6e0f4398 100755 --- a/bin/keystone +++ b/bin/keystone @@ -32,6 +32,8 @@ def create_server(conf, name, port): def serve(*servers): for server in servers: + logging.debug("starting server %s on port %s", server.application, + server.port) server.start() for server in servers: @@ -51,8 +53,11 @@ if __name__ == '__main__': CONF(config_files=config_files) - # TODO(termie): configure this based on config - logging.getLogger().setLevel(logging.DEBUG) + config.setup_logging(CONF) + + # Log the options used when starting if we're in debug mode... + if CONF.debug: + CONF.log_opt_values(logging.getLogger(CONF.prog), logging.DEBUG) options = deploy.appconfig('config:%s' % CONF.config_file[0]) diff --git a/etc/keystone.conf b/etc/keystone.conf index a1837095..70559af8 100644 --- a/etc/keystone.conf +++ b/etc/keystone.conf @@ -3,6 +3,17 @@ public_port = 5000 admin_port = 35357 admin_token = ADMIN compute_port = 3000 +verbose = True +debug = False +#log_config = /etc/keystone/logging.conf + +# ================= Syslog Options ============================ +# Send logs to syslog (/dev/log) instead of to file specified +# by `log-file` +use_syslog = False + +# Facility to use. If unset defaults to LOG_USER. +# syslog_log_facility = LOG_LOCAL0 [sql] connection = sqlite:///bla.db diff --git a/etc/logging.conf.sample b/etc/logging.conf.sample new file mode 100644 index 00000000..6e3d1a04 --- /dev/null +++ b/etc/logging.conf.sample @@ -0,0 +1,54 @@ +[loggers] +keys=root,api,registry,combined + +[formatters] +keys=normal,normal_with_name,debug + +[handlers] +keys=production,file,devel + +[logger_root] +level=NOTSET +handlers=devel + +[logger_api] +level=DEBUG +handlers=devel +qualname=glance-api + +[logger_registry] +level=DEBUG +handlers=devel +qualname=glance-registry + +[logger_combined] +level=DEBUG +handlers=devel +qualname=glance-combined + +[handler_production] +class=handlers.SysLogHandler +level=ERROR +formatter=normal_with_name +args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER) + +[handler_file] +class=FileHandler +level=DEBUG +formatter=normal_with_name +args=('glance.log', 'w') + +[handler_devel] +class=StreamHandler +level=NOTSET +formatter=debug +args=(sys.stdout,) + +[formatter_normal] +format=%(asctime)s %(levelname)s %(message)s + +[formatter_normal_with_name] +format=(%(name)s): %(asctime)s %(levelname)s %(message)s + +[formatter_debug] +format=(%(name)s): %(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s diff --git a/keystone/cfg.py b/keystone/cfg.py index 54940e7d..fd79e122 100644 --- a/keystone/cfg.py +++ b/keystone/cfg.py @@ -1115,6 +1115,10 @@ class CommonConfigOpts(ConfigOpts): StrOpt('log-dir', help='(Optional) The directory to keep log files in ' '(will be prepended to --logfile)'), + StrOpt('syslog-log-facility', + default='LOG_USER', + help='(Optional) The syslog facility to use when logging ' + 'to syslog (defaults to LOG_USER)'), BoolOpt('use-syslog', default=False, help='Use syslog for logging.'), diff --git a/keystone/config.py b/keystone/config.py index 80c73cb8..5e6f909c 100644 --- a/keystone/config.py +++ b/keystone/config.py @@ -1,42 +1,90 @@ - +import logging +import sys +import os from keystone import cfg -class Config(cfg.ConfigOpts): - def __call__(self, config_files=None, *args, **kw): - if config_files is not None: - self._opts['config_file']['opt'].default = config_files - return super(Config, self).__call__(*args, **kw) +class Config(cfg.CommonConfigOpts): + def __call__(self, config_files=None, *args, **kw): + if config_files is not None: + self._opts['config_file']['opt'].default = config_files + return super(Config, self).__call__(*args, **kw) - def __getitem__(self, key, default=None): - return getattr(self, key, default) + def __getitem__(self, key, default=None): + return getattr(self, key, default) - def __setitem__(self, key, value): - return setattr(self, key, value) + def __setitem__(self, key, value): + return setattr(self, key, value) - def iteritems(self): - for k in self._opts: - yield (k, getattr(self, k)) + def iteritems(self): + for k in self._opts: + yield (k, getattr(self, k)) def register_str(*args, **kw): - group = kw.pop('group', None) - if group: - CONF.register_group(cfg.OptGroup(name=group)) - return CONF.register_opt(cfg.StrOpt(*args, **kw), group=group) + group = kw.pop('group', None) + if group: + CONF.register_group(cfg.OptGroup(name=group)) + return CONF.register_opt(cfg.StrOpt(*args, **kw), group=group) def register_cli_str(*args, **kw): - group = kw.pop('group', None) - if group: - CONF.register_group(cfg.OptGroup(name=group)) - return CONF.register_cli_opt(cfg.StrOpt(*args, **kw), group=group) + group = kw.pop('group', None) + if group: + CONF.register_group(cfg.OptGroup(name=group)) + return CONF.register_cli_opt(cfg.StrOpt(*args, **kw), group=group) + + +def setup_logging(conf): + """ + Sets up the logging options for a log with supplied name + + :param conf: a cfg.ConfOpts object + """ + + if conf.log_config: + # Use a logging configuration file for all settings... + if os.path.exists(conf.log_config): + logging.config.fileConfig(conf.log_config) + return + else: + raise RuntimeError("Unable to locate specified logging " + "config file: %s" % conf.log_config) + + root_logger = logging.root + if conf.debug: + root_logger.setLevel(logging.DEBUG) + elif conf.verbose: + root_logger.setLevel(logging.INFO) + else: + root_logger.setLevel(logging.WARNING) + + formatter = logging.Formatter(conf.log_format, conf.log_date_format) + + if conf.use_syslog: + try: + facility = getattr(logging.handlers.SysLogHandler, + conf.syslog_log_facility) + except AttributeError: + raise ValueError(_("Invalid syslog facility")) + + handler = logging.handlers.SysLogHandler(address='/dev/log', + facility=facility) + elif conf.log_file: + logfile = conf.log_file + if conf.log_dir: + logfile = os.path.join(conf.log_dir, logfile) + handler = logging.handlers.WatchedFileHandler(logfile) + else: + handler = logging.StreamHandler(sys.stdout) + + handler.setFormatter(formatter) + root_logger.addHandler(handler) CONF = Config(project='keystone') - register_str('admin_token', default='ADMIN') register_str('compute_port') register_str('admin_port') diff --git a/keystone/logging.py b/keystone/logging.py index c1543961..d7cc6756 100644 --- a/keystone/logging.py +++ b/keystone/logging.py @@ -28,6 +28,9 @@ exception = logging.exception critical = logging.critical log = logging.log +# classes +root = logging.root +Formatter = logging.Formatter # handlers StreamHandler = logging.StreamHandler diff --git a/tools/pip-requires b/tools/pip-requires index 80b03695..3352ed66 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -5,3 +5,5 @@ PasteDeploy paste routes pycli +sqlalchemy +sqlalchemy-migrate diff --git a/tools/pip-requires-test b/tools/pip-requires-test index 94adcc05..563eaa2c 100644 --- a/tools/pip-requires-test +++ b/tools/pip-requires-test @@ -5,6 +5,8 @@ eventlet==0.9.12 PasteDeploy paste routes +sqlalchemy +sqlalchemy-migrate # keystonelight testing dependencies nose -- cgit