# # # from argparse import ArgumentParser as _Base from logging import DEBUG, INFO, WARNING, Formatter, StreamHandler, getLogger from logging.config import dictConfig from logging.handlers import SysLogHandler from sys import stderr, stdout from yaml import safe_load from octodns import __VERSION__ class ArgumentParser(_Base): ''' Manages argument parsing and adds some defaults and takes action on them. Also manages logging setup. ''' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def parse_args(self, default_log_level=INFO): version = f'octoDNS {__VERSION__}' self.add_argument( '--version', action='version', version=version, help='Print octoDNS version and exit', ) self.add_argument( '--log-stream-stdout', action='store_true', default=False, help='Log to stdout instead of stderr', ) _help = 'Send logging data to syslog in addition to stderr' self.add_argument( '--log-syslog', action='store_true', default=False, help=_help ) self.add_argument( '--syslog-device', default='/dev/log', help='Syslog device' ) self.add_argument( '--syslog-facility', default='local0', help='Syslog facility' ) _help = 'Increase verbosity to get details and help track down issues' self.add_argument( '--debug', action='store_true', default=False, help=_help ) _help = 'Decrease verbosity to show only warnings, errors, and the plan' self.add_argument( '--quiet', action='store_true', default=False, help=_help ) _help = 'Configure logging with a YAML file, see https://docs.python.org/3/library/logging.config.html#logging-config-dictschema for schema details' self.add_argument('--logging-config', default=False, help=_help) args = super().parse_args() self._setup_logging(args, default_log_level) return args def _setup_logging(self, args, default_log_level): if args.logging_config: with open(args.logging_config) as fh: config = safe_load(fh.read()) dictConfig(config) # if we're provided a logging_config we won't do any of our normal # configuration return fmt = '%(asctime)s [%(thread)d] %(levelname)-5s %(name)s %(message)s' formatter = Formatter(fmt=fmt, datefmt='%Y-%m-%dT%H:%M:%S ') stream = stdout if args.log_stream_stdout else stderr handler = StreamHandler(stream=stream) handler.setFormatter(formatter) logger = getLogger() logger.addHandler(handler) if args.log_syslog: fmt = ( 'octodns[%(process)-5s:%(thread)d]: %(name)s ' '%(levelname)-5s %(message)s' ) handler = SysLogHandler( address=args.syslog_device, facility=args.syslog_facility ) handler.setFormatter(Formatter(fmt=fmt)) logger.addHandler(handler) logger.level = default_log_level if args.debug: logger.level = DEBUG elif args.quiet: logger.level = WARNING # we still want plans to come out during quite so set the plan # logger output to info in case the PlanLogger is being used getLogger('Plan').setLevel(INFO) # TODO: these should move out of octoDNS core... # boto is noisy, set it to warn getLogger('botocore').level = WARNING # DynectSession is noisy too getLogger('DynectSession').level = WARNING