X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=t%2Fmoe%2Flog.py;h=3fcac226d3f286bc1666b0aa881de78455197ab3;hb=1ed60150aa8d007acd895d0ab7274ba9eb8b0f2a;hp=56dbe8f1f8dfa92d87b354ab9c21e60e5445a834;hpb=5701572b35e7ebc7c2d96cc603cd720fb2649ac4;p=eval.git diff --git a/t/moe/log.py b/t/moe/log.py index 56dbe8f..3fcac22 100644 --- a/t/moe/log.py +++ b/t/moe/log.py @@ -1,39 +1,107 @@ #!/usr/bin/env python -import sys -import os +""" -progress_file = os.fdopen(os.dup(1), "w", 0) +`Loggers` is a collection of logggers for :class:`~moe.eval.Eval`, initializing 4 subloggers (see class description). -class MoeLog: +Use as `e.log.debug(...)` for main log that goes both to `test` and `main` log, +`e.log.test.debug(...)` for individual logs. - def __init__(self): - self.verbosity = 0 - self.progress_file = progress_file - self.log_file = None +.. :data:: DDEBUG = 5 + Very verbose debugging level - def open(self, name): - self.log_file = open(name, "w") - os.dup2(self.log_file.fileno(), 1) - os.dup2(self.log_file.fileno(), 2) +""" - def say(self, msg): - if self.log_file: - self.log_file.write(msg) - def verbose(self, msg): - if self.verbosity and self.log_file: - self.log_file.write(msg) +import sys, os +import logging +from logging import Logger, StreamHandler, Formatter - def progress(self, msg): - if self.progress_file: - self.progress_file.write(msg) +logging.addLevelName(5,'DDEBUG') - def shout(self, msg): - self.say(msg) - self.progress(msg) - def flush(self): - self.log_file.flush() +class Loggers(Logger): + """Defines several logs: -default = MoeLog() + `self` + root log, which sends messages to `eval` and `test` logs + `self.eval` + main log, initially a duplicated fd 2 (stderr) + `self.user` + public progress log, initially a duplicated fd 1 (stdout) + `self.test` + per-test log, initially no handler, to be directed to file like `{TEST}.log` + + .. note:: Currently, the logs and fd's get never closed. + .. warning:: `Loggers.open_eval_log` changes global fd's 1 and 2 by default. + """ + def __init__(self): + "Initialize loggers as described in class description." + Logger.__init__(self, '') + # Duplicate the fd's + self.orig_stdout_fd = os.dup(1) + self.orig_stdout_file = os.fdopen(self.orig_stdout_fd, 'w', 0) + self.orig_stderr_fd = os.dup(2) + self.orig_stderr_file = os.fdopen(self.orig_stderr_fd, 'w', 0) + # Eval main logger + self.eval = Logger('eval') + self.eval.addHandler(StreamHandler(self.orig_stderr_file)) + # per-test logger + self.test = Logger('test') + self.test_handler = None + self.test_file = None + # user progress logger + self.user = Logger('user') + self.user.addHandler(StreamHandler(self.orig_stdout_file)) + + self.addHandler(self.test) + self.addHandler(self.eval) + self.debug('Logging initialized.') + + def open_user_log(self, filename, level=logging.INFO): + """Open user (progress) logfile. Leaves logging to stdout active.""" + h = StreamHandler(open(filename, 'w', 0)) + h.setFormatter(Formatter('%(message)s')) + self.user.setLevel(level) + self.user.addHandler(h) + self.user.debug('Logging started') + + def open_eval_log(self, filename, level, redirect_fds = True): + """Open main logfile. + Leaves logging to stderr active. If told to, redirects fd's 1 and 2 to this file. + Sets level of both `self.eval` and `self`.""" + self.eval_file = open(filename, 'w', 0) + self.eval_handler = StreamHandler(self.eval_file) + self.eval_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s')) + self.eval.addHandler(self.eval_handler) + if redirect_fds: + os.dup2(self.eval_file.fileno(), 1) + os.dup2(self.eval_file.fileno(), 2) + self.eval.setLevel(level) + self.setLevel(level) + self.eval.debug('Logging started') + + + def open_test_log(self, filename, level): + """Open per-test log file, like "{TEST}.log". Also set handler level to `level`.""" + self.debug('Opening per-test log %s' % filename) + if self.test_handler: + self.close_test_log() + self.test_file = open(filename, 'w') + self.test_handler = StreamHandler(self.test_file) + self.test.addHandler(self.test_handler) + self.test.setLevel(level) + self.test_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s')) + self.test.debug('Logging started') + + def close_test_log(self): + """Close per-test logfile, leaving only the null handler.""" + if self.test_handler: + self.test.info('Closing logfile' % filename) + self.test.removeHandler(self.test_handler) + self.test_handler = None + self.test_file.close() + + def ddebug(self, msg, *args, **kwargs): + """Log with priority 5 (normal DEBUG is 10)""" + self.log(5, msg, *args, **kwargs)