Gracefully handle errors in logging config files

Fixes bug #1154245

If the parameter to the --log-config option cannot be loaded by the
logging.config.fileConfig() function, you get an exception like this
raised:

  NoSectionError: No section: 'formatters'

which doesn't do much to help users understand the error.

Improve the situation by wrapping the error in a custom exception type
giving this:

 LogConfigError: Error loading logging config /etc/logging.conf: No section: 'formatters'

Also add some tests to check we raise this error under the most common
failure conditions.

Change-Id: I6ad2eb4867213b6356ce43d75da50218d1b498f6
This commit is contained in:
Mark McLoughlin
2013-03-22 07:32:31 +00:00
parent f52e8cf870
commit 2409ec7ac7
2 changed files with 70 additions and 1 deletions

View File

@@ -29,6 +29,7 @@ It also allows setting of formatting information through conf.
"""
import ConfigParser
import cStringIO
import inspect
import itertools
@@ -323,10 +324,30 @@ def _create_logging_excepthook(product_name):
return logging_excepthook
class LogConfigError(Exception):
message = _('Error loading logging config %(log_config)s: %(err_msg)s')
def __init__(self, log_config, err_msg):
self.log_config = log_config
self.err_msg = err_msg
def __str__(self):
return self.message % dict(log_config=self.log_config,
err_msg=self.err_msg)
def _load_log_config(log_config):
try:
logging.config.fileConfig(log_config)
except ConfigParser.Error, exc:
raise LogConfigError(log_config, str(exc))
def setup(product_name):
"""Setup logging."""
if CONF.log_config:
logging.config.fileConfig(CONF.log_config)
_load_log_config(CONF.log_config)
else:
_setup_logging_from_conf()
sys.excepthook = _create_logging_excepthook(product_name)

View File

@@ -1,7 +1,9 @@
import cStringIO
import logging
import os
import StringIO
import sys
import tempfile
from oslo.config import cfg
@@ -377,3 +379,49 @@ class LogConfigOptsTestCase(test_utils.BaseTestCase):
logdir = '/some/other/path/'
CONF(['--logdir', logdir])
self.assertEquals(CONF.log_dir, logdir)
class LogConfigTestCase(test_utils.BaseTestCase):
minimal_config = """[loggers]
keys=root
[formatters]
keys=
[handlers]
keys=
[logger_root]
handlers=
"""
def _create_tempfile(self, basename, contents, ext='.conf'):
(fd, path) = tempfile.mkstemp(prefix=basename, suffix=ext)
try:
os.write(fd, contents)
finally:
os.close(fd)
return path
def test_log_config_ok(self):
log_config = self._create_tempfile('logging', self.minimal_config)
self.config(log_config=log_config)
log.setup('test_log_config')
def test_log_config_not_exist(self):
log_config = self._create_tempfile('logging', self.minimal_config)
os.remove(log_config)
self.config(log_config=log_config)
self.assertRaises(log.LogConfigError, log.setup, 'test_log_config')
def test_log_config_invalid(self):
log_config = self._create_tempfile('logging', self.minimal_config[5:])
self.config(log_config=log_config)
self.assertRaises(log.LogConfigError, log.setup, 'test_log_config')
def test_log_config_unreadable(self):
log_config = self._create_tempfile('logging', self.minimal_config)
os.chmod(log_config, 0)
self.config(log_config=log_config)
self.assertRaises(log.LogConfigError, log.setup, 'test_log_config')