"""Base error class for all command errors"""
pass
-def makeLogger(options):
+def makeLogger(options, numeric_args):
+ context = " ".join(numeric_args)
logger = logging.getLogger("main")
logger.setLevel(logging.INFO)
stdout = logging.StreamHandler(sys.stdout)
- stdout.setFormatter(logging.Formatter(" " * int(options.indent) + '%(message)s'))
- logger.addHandler(stdout)
+ stdout.setFormatter(logging.Formatter(" " * int(options.indent) + '%(levelname)s: %(message)s'))
+ dateFormat = "%H:%M:%S"
+ if options.context:
+ logformatter = logging.Formatter("%(asctime)s %(levelname)s -- " + context + ": %(message)s", dateFormat)
+ else:
+ logformatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s", dateFormat)
+ if not options.quiet: logger.addHandler(stdout)
if options.log_file:
file = logging.FileHandler(options.log_file)
+ file.setFormatter(logformatter)
logger.addHandler(file)
if options.debug:
logger.setLevel(logging.DEBUG)
"""Takes parsed options, and breaks them back into a command
line string that we can pass into a subcommand"""
args = []
- grab["log_file"] = "--log-file"
- grab["debug"] = "--debug"
+ grab["log_file"]= "--log-file"
+ grab["debug"] = "--debug"
grab["verbose"] = "--verbose"
- grab["indent"] = "--indent"
+ grab["indent"] = "--indent"
+ grab["quiet"] = "--quiet"
#grab["log_db"] = "--log-db"
for k,flag in grab.items():
value = getattr(options, k)
if k == "indent":
value += 4
args.append(str(value))
+ args.append("--context") # always have context for a subcommand
return args
class NullLogHandler(logging.Handler):
default=False, help="Turns on verbose output")
self.add_option("--debug", dest="debug", action="store_true",
default=False, help="Turns on debugging output")
+ self.add_option("-q", "--quiet", dest="quiet", action="store_true",
+ default=False, help="Turns off output to stdout")
self.add_option("--log-file", dest="log_file",
default=None, help="Logs verbose output to file")
self.add_option("--indent", dest="indent",
default=0, help="Indents stdout, useful for nested calls")
+ self.add_option("--context", dest="context", action="store_true",
+ default=False, help="Adds context to logs, useful for parallel processing")
def parse_all(self, argv, logger):
options, numeric_args = self.parse_args(argv)
- return options, numeric_args, logger and logger or makeLogger(options)
+ return options, numeric_args, logger and logger or makeLogger(options, numeric_args)
parser.error("too many arguments")
elif not args:
parser.error("must specify application to migrate")
- if options.verbose or options.dry_run:
+ if options.dry_run:
options.no_parallelize = True
app = args[0]
errors = {}
name = e.name
if name not in errors: errors[name] = []
errors[name].append(d)
- logger.error("ERROR [%s] in %s" % (name, d.location))
+ logger.error("%s in %s" % (name, d.location))
return (on_success, on_error)
on_success, on_error = make_on_pair(d)
sh.wait() # wait for a parallel processing slot to be available
user=user, on_success=on_success, on_error=on_error)
sh.join()
for name, deploys in errors.items():
- logger.warning("ERROR [%s] from %d installs" % (name, len(deploys)))
+ logger.warning("%s from %d installs" % (name, len(deploys)))
def call(self, *args, **kwargs):
kwargs.setdefault("python", None)
if self.dry or self.logger:
- self.logger.info("$ " + ' '.join(args))
+ self.logger.info("Running `" + ' '.join(args) + "`")
if self.dry:
return
if kwargs["python"] is None and is_python(args):
raise eclass(proc.returncode, args, stdout, stderr)
return (stdout, stderr)
def log(self, stdout, stderr):
- if self.logger and stdout: self.logger.info(stdout)
- if self.logger and stderr: self.logger.info("STDERR: " + stderr)
+ if self.logger and stdout:
+ self.logger.debug("STDOUT: " + stdout)
+ if self.logger and stderr:
+ self.logger.debug("STDERR: " + stderr)
def callAsUser(self, *args, **kwargs):
user = kwargs.pop("user", None)
kwargs.setdefault("python", is_python(args))