diff options
Diffstat (limited to 'rpki/log.py')
-rw-r--r-- | rpki/log.py | 104 |
1 files changed, 85 insertions, 19 deletions
diff --git a/rpki/log.py b/rpki/log.py index 9f59444f..4c4a444c 100644 --- a/rpki/log.py +++ b/rpki/log.py @@ -26,6 +26,7 @@ import sys import time import logging import logging.handlers +import argparse import traceback as tb try: @@ -67,36 +68,101 @@ use_setproctitle = True proctitle_extra = os.path.basename(os.getcwd()) -def init(ident = "rpki", use_syslog = True): +def argparse_setup(parser): + """ + Set up argparse stuff for functionality in this module. + + Default logging destination is syslog, but also see rpki.log.init(). + """ + + class RotatingFile(argparse.Action): + def __call__(self, parser, namespace, values, option_string = None): + setattr(namespace, self.dest, values[0]) + setattr(namespace, self.dest + "_maxBytes", int(values[1])) + setattr(namespace, self.dest + "_backupCount", int(values[2])) + if len(values) > 3: + raise ValueError + + class TimedRotatingFile(argparse.Action): + def __call__(self, parser, namespace, values, option_string = None): + setattr(namespace, self.dest, values[0]) + setattr(namespace, self.dest + "_interval", int(values[1])) + setattr(namespace, self.dest + "_backupCount", int(values[2])) + if len(values) > 3: + raise ValueError + + parser.add_argument("--log-level", default = logging.DEBUG, + choices = ("debug", "info", "warning", "error", "critical"), + type = lambda s: int(getattr(logging, s.upper())), + help = "how verbosely to log") + group = parser.add_mutually_exclusive_group() + group.add_argument("--log-syslog", nargs = "?", default = "daemon", + choices = sorted(logging.handlers.SysLogHandler.facility_names.keys()), + help = "send logging to syslog") + group.add_argument("--log-stderr", dest = "log_stream", action = "store_const", const = sys.stderr, + help = "send logging to standard error") + group.add_argument("--log-stdout", dest = "log_stream", action = "store_const", const = sys.stdout, + help = "send logging to standard output") + group.add_argument("--log-file", + help = "send logging to a plain old file") + group.add_argument("--log-rotating-file", action = RotatingFile, + nargs = 3, metavar = ("FILENAME", "KBYTES", "COUNT"), + help = "send logging to rotating file") + group.add_argument("--log-timed-rotating-file", action = TimedRotatingFile, + nargs = 3, metavar = ("FILENAME", "HOURS", "COUNT"), + help = "send logging to timed rotating file") + + +def init(ident = "rpki", args = argparse.Namespace(log_level = logging.DEBUG, log_stream = sys.stderr)): """ Initialize logging system. + + Default logging destination is syslog if "args" is specified, stderr otherwise. """ - # This will want tweaking after basic conversion to logging package - # is finished. For now, keep it simple. - # - # Should also support LoggingAdapters, rotating log files, - # configurable log levels, and other forms of entertainment. + assert isinstance(args, argparse.Namespace) - format = ident + "[%(process)d] %(message)s" - if not use_syslog: - format = "%(asctime)s " + format + if args.log_stream: + handler = logging.StreamHandler(stream = args.log_stream) - formatter = logging.Formatter(format, "%Y-%m-%dT%H:%M:%SZ") - formatter.converter = time.gmtime + elif args.log_file: + handler = logging.FileHandler(filename = args.log_file) + + elif args.log_rotating_file: + handler = logging.handlers.RotatingFileHandler( + filename = args.log_rotating_file, + maxBytes = args.log_rotating_file_maxBytes, + backupCount = args.log_rotating_file_backupCount) + + elif args.log_timed_rotating_file: + handler = logging.handlers.TimedRotatingFileHandler( + filename = args.log_timed_rotating_file, + interval = args.log_timed_rotating_file_interval, + backupCount = args.log_timed_rotating_file_backupCount) + + elif args.log_syslog: + handler = logging.handlers.SysLogHandler( + address = "/dev/log" if os.path.exists("/dev/log") else ("localhost", logging.handlers.SYSLOG_UDP_PORT), + facility = args.log_syslog) - if not use_syslog: - handler = logging.StreamHandler() - elif os.path.exists("/dev/log"): - handler = logging.handlers.SysLogHandler("/dev/log") else: - handler = logging.handlers.SysLogHandler() + raise ValueError + + format = ident + "[%(process)d]: %(message)s" + if not isinstance(handler, logging.handlers.SysLogHandler): + format = "%(asctime)s " + format + + # At some point we will probably want our own subclass of + # logging.Formatter so we can support LoggingAdapters with extra + # fields, but this suffices for the moment. + formatter = logging.Formatter(format, "%Y-%m-%d %H:%M:%S") + formatter.converter = time.gmtime handler.setFormatter(formatter) - logging.root.addHandler(handler) - #logging.root.setLevel(args.log_level) - logging.root.setLevel(logging.DEBUG) + root_logger = logging.getLogger() + root_logger.addHandler(handler) + root_logger.setLevel(args.log_level) if ident and have_setproctitle and use_setproctitle: if proctitle_extra: |