First round of logging functionality:
* Adds option group for logging-only configuration settings * Adds /etc and /etc/logging.cnf.sample as an example of setting up logging configuration directly with a config file * Adds to glance.common.config a couple function useful in adding logging options and setting up the logger(s) Next round will include the addition of a --debug option and lots more debugging output to the loggers.
This commit is contained in:
parent
087ebf5fec
commit
61711e0378
@ -22,6 +22,7 @@
|
||||
Glance API Server
|
||||
"""
|
||||
|
||||
import logging
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
@ -36,6 +37,7 @@ from glance.common import server
|
||||
import glance.store
|
||||
|
||||
|
||||
logger = logging.getLogger('glance-api')
|
||||
DEFAULT_STORE_CHOICES = ['file', 'swift', 's3']
|
||||
|
||||
|
||||
@ -61,15 +63,6 @@ def create_options(parser):
|
||||
"Default: %default")
|
||||
parser.add_option('--daemonize', default=False, action="store_true",
|
||||
help="Daemonize this process")
|
||||
parser.add_option('--use-syslog', default=True, action="store_true",
|
||||
help="Output to syslog when daemonizing. "
|
||||
"Default: %default")
|
||||
parser.add_option('--logfile', default=None,
|
||||
metavar="PATH",
|
||||
help="(Optional) Name of log file to output to.")
|
||||
parser.add_option("--logdir", default=None,
|
||||
help="(Optional) The directory to keep log files in "
|
||||
"(will be prepended to --logfile)")
|
||||
parser.add_option("--pidfile", default=None,
|
||||
help="(Optional) Name of pid file for the server")
|
||||
parser.add_option('--working-directory', '--working-dir',
|
||||
@ -96,6 +89,7 @@ def create_options(parser):
|
||||
"virtual machine images to. Choices: ('%s') "
|
||||
"Default: %%default" % "','".join(DEFAULT_STORE_CHOICES))
|
||||
glance.store.add_options(parser)
|
||||
config.add_log_options(parser)
|
||||
|
||||
|
||||
def main(_args):
|
||||
@ -113,4 +107,10 @@ if __name__ == '__main__':
|
||||
% version.version_string())
|
||||
create_options(oparser)
|
||||
(options, args) = config.parse_options(oparser)
|
||||
|
||||
try:
|
||||
config.setup_logging('glance-api', options)
|
||||
except RuntimeError, e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
||||
server.serve('glance-api', main, options, args)
|
||||
|
@ -57,15 +57,6 @@ def create_options(parser):
|
||||
"Default: %default")
|
||||
parser.add_option('--daemonize', default=False, action="store_true",
|
||||
help="Daemonize this process")
|
||||
parser.add_option('--use-syslog', default=True, action="store_true",
|
||||
help="Output to syslog when daemonizing. "
|
||||
"Default: %default")
|
||||
parser.add_option('--logfile', default=None,
|
||||
metavar="PATH",
|
||||
help="(Optional) Name of log file to output to.")
|
||||
parser.add_option("--logdir", default=None,
|
||||
help="(Optional) The directory to keep log files in "
|
||||
"(will be prepended to --logfile)")
|
||||
parser.add_option("--pidfile", default=None,
|
||||
help="(Optional) Name of pid file for the server")
|
||||
parser.add_option('--working-directory', '--working-dir',
|
||||
@ -79,6 +70,7 @@ def create_options(parser):
|
||||
default='sqlite:///glance.sqlite',
|
||||
help="A valid SQLAlchemy connection string for the "
|
||||
"registry database. Default: %default")
|
||||
config.add_log_options(parser)
|
||||
|
||||
|
||||
def main(_args):
|
||||
@ -96,4 +88,10 @@ if __name__ == '__main__':
|
||||
% version.version_string())
|
||||
create_options(oparser)
|
||||
(options, args) = config.parse_options(oparser)
|
||||
|
||||
try:
|
||||
config.setup_logging('glance-registry', options)
|
||||
except RuntimeError, e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
||||
server.serve('glance-registry', main, options, args)
|
||||
|
54
etc/logging.cnf.sample
Normal file
54
etc/logging.cnf.sample
Normal file
@ -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
|
@ -16,6 +16,20 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Routines for configuring Glance
|
||||
"""
|
||||
|
||||
import logging
|
||||
import logging.config
|
||||
import logging.handlers
|
||||
import optparse
|
||||
import os
|
||||
|
||||
|
||||
DEFAULT_LOG_FORMAT = "%(asctime)s (%(name)s): %(levelname)s %(message)s"
|
||||
LOGGING_HANDLER_CHOICES = ['syslog', 'file', 'stream']
|
||||
|
||||
|
||||
def parse_options(parser, cli_args=None):
|
||||
"""
|
||||
@ -52,3 +66,77 @@ def options_to_conf(options):
|
||||
:params options: Mapping of typed option key/values
|
||||
"""
|
||||
return dict([(k, str(v)) for k, v in options.items()])
|
||||
|
||||
|
||||
def add_log_options(parser):
|
||||
"""
|
||||
Given a supplied optparse.OptionParser, adds an OptionGroup that
|
||||
represents all the configuration options around logging.
|
||||
|
||||
:param parser: optparse.OptionParser
|
||||
"""
|
||||
help_text = "The following configuration options are specific to logging "\
|
||||
"functionality for this program."
|
||||
|
||||
group = optparse.OptionGroup(parser, "Logging Options", help_text)
|
||||
group.add_option('--log-config', default=None, metavar="PATH",
|
||||
help="If this option is specified, the logging "
|
||||
"configuration file specified is used and overrides "
|
||||
"any other logging options specified. Please see "
|
||||
"the Python logging module documentation for "
|
||||
"details on logging configuration files.")
|
||||
group.add_option('--log-handler', default='stream', metavar="HANDLER",
|
||||
choices=LOGGING_HANDLER_CHOICES,
|
||||
help="What logging handler to use? "
|
||||
"Default: %default")
|
||||
group.add_option('--log-format', metavar="FORMAT",
|
||||
default=DEFAULT_LOG_FORMAT,
|
||||
help="Format string for log records. Default: %default")
|
||||
group.add_option('--log-file', default=None,
|
||||
metavar="PATH",
|
||||
help="(Optional) Name of log file to output to.")
|
||||
group.add_option("--log-dir", default=None,
|
||||
help="(Optional) The directory to keep log files in "
|
||||
"(will be prepended to --logfile)")
|
||||
parser.add_option_group(group)
|
||||
|
||||
|
||||
def setup_logging(prog_name, options):
|
||||
"""
|
||||
Sets up the logging options for a log with supplied name
|
||||
|
||||
:param prog_name: Name of the log/program
|
||||
:param options: Mapping of typed option key/values
|
||||
"""
|
||||
|
||||
if options['log_config']:
|
||||
# Use a logging configuration file for all settings...
|
||||
if os.path.exists(options['log_config']):
|
||||
logging.config.fileConfig(options['log_config'])
|
||||
else:
|
||||
raise RuntimeError("Unable to locate specified logging "
|
||||
"config file: %s" % options['log_config'])
|
||||
else:
|
||||
# Set log configuration from options...
|
||||
logger = logging.getLogger(prog_name)
|
||||
formatter = logging.Formatter(options['log_format'])
|
||||
|
||||
if options['log_handler'] == 'syslog':
|
||||
syslog = logging.handlers.SysLogHandler(address='/dev/log')
|
||||
syslog.setFormatter(formatter)
|
||||
logger.addHandler(syslog)
|
||||
else:
|
||||
logfile = options['log_file']
|
||||
logdir = options['log_dir']
|
||||
if not logfile:
|
||||
logfile = '%s.log' % prog_name
|
||||
if logdir:
|
||||
logfile = os.path.join(logdir, logfile)
|
||||
logfile = logging.FileHandler(logfile)
|
||||
logfile.setFormatter(formatter)
|
||||
logger.addHandler(logfile)
|
||||
|
||||
if options['verbose']:
|
||||
logging.getLogger(prog_name).setLevel(logging.DEBUG)
|
||||
else:
|
||||
logging.getLogger(prog_name).setLevel(logging.WARNING)
|
||||
|
@ -87,14 +87,14 @@ def daemonize(args, name, main, options):
|
||||
"""Does the work of daemonizing the process"""
|
||||
logging.getLogger('amqplib').setLevel(logging.WARN)
|
||||
pidfile = options['pidfile']
|
||||
logfile = options['logfile']
|
||||
logfile = options['log_file']
|
||||
if not logfile:
|
||||
logfile = None
|
||||
logdir = options['logdir']
|
||||
logdir = options['log_dir']
|
||||
if not logdir:
|
||||
logdir = None
|
||||
daemonize = options['daemonize']
|
||||
use_syslog = options['use_syslog']
|
||||
use_syslog = options['log_handler'] == 'syslog'
|
||||
files_to_keep = []
|
||||
if daemonize:
|
||||
logger = logging.getLogger()
|
||||
@ -105,7 +105,7 @@ def daemonize(args, name, main, options):
|
||||
syslog.setFormatter(formatter)
|
||||
logger.addHandler(syslog)
|
||||
files_to_keep.append(syslog.socket)
|
||||
else:
|
||||
elif options['log_handler'] == 'file':
|
||||
if not logfile:
|
||||
logfile = '%s.log' % name
|
||||
if logdir:
|
||||
|
Loading…
Reference in New Issue
Block a user