#!/usr/bin/env python
-import sys
+"""
-def say(msg):
- sys.stdout.write(msg + "\n")
+`Loggers` is a collection of logggers for :class:`~moe.eval.Eval`, initializing 4 subloggers (see class description).
-def verbose(msg):
- sys.stdout.write(msg)
+Use as `e.log.debug(...)` for main log that goes both to `test` and `main` log,
+`e.log.test.debug(...)` for individual logs.
-def progress(msg):
- sys.stdout.write(msg)
+.. :data:: DDEBUG = 5
+ Very verbose debugging level
+
+Defines several logs:
+
+`log`
+ main log, initially a duplicated fd 2 (stderr)
+`userlog`
+ public progress log, initially a duplicated fd 1 (stdout)
+`testlog`
+ 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.
+"""
+
+
+# Global logs to be imported by every module
+
+__all__ = ['log', 'userlog', 'testlog', 'pipelog' ]
+
+log = None
+userlog = None
+testlog = None
+pipelog = None
+
+orig_stdout_fd = None
+orig_stdout_file = None
+orig_stderr_fd = None
+orig_stderr_file = None
+testlog_file = None
+
+import logging, sys
+
+def __init__():
+ """Very basic loggers setup to stderr."""
+
+ global orig_stdout_fd, orig_stdout_file, orig_stderr_fd, orig_stderr_file
+ global log, userlog,
+
+ orig_stdout_fd = os.dup(1)
+ orig_stdout_file = os.fdopen(orig_stdout_fd, 'w', 0)
+ orig_stderr_fd = os.dup(2)
+ orig_stderr_file = os.fdopen(orig_stderr_fd, 'w', 0)
+
+ log = logging.getLogger('mainlog')
+ log.addHandler(StreamHandler(orig_stderr_file))
+
+ userlog = logging.getLogger('userlog')
+ userlog.addHandler(StreamHandler(orig_stdout_file))
+
+ testlog = log
+ pipelog = log
+
+ logging.addLevelName(5,'DDEBUG')
+
+ log.debug('Logging initialized.')
+
+
+def open_user_log(filename, level=logging.INFO):
+ """Open user (progress) logfile. Leaves logging to stdout active."""
+ h = StreamHandler(open(filename, 'w', 0))
+ h.setFormatter(Formatter('%(message)s'))
+ userlog.setLevel(level)
+ userlog.addHandler(h)
+
+ log.debug('User logging to %r started', filename)
+
+def open_eval_log(filename, redirect_fds = True):
+ """Open main logfile.
+ Leaves logging to stderr active. If told to, redirects fd's 1 and 2 to this file."""
+
+ eval_file = open(filename, 'w', 0)
+ h = StreamHandler(self.eval_file)
+ h.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
+ log.addHandler(h)
+ log.debug('Opened eval logfile %r')
+
+ if redirect_fds:
+ os.dup2(eval_file.fileno(), 1)
+ os.dup2(eval_file.fileno(), 2)
+ log.debug('Redirected fds 1,2 -> eval logfile')
+
+
+def open_test_log(filename, level):
+ """Open per-test log file, usually "{TEST}.log", set its level."""
+
+ log.debug('Opening per-test log %r', filename)
+
+ global testlog, testlog_file
+ assert testlog_file is None
+
+ testlog = logging.getLogger('testlog')
+ testlog.setLevel(level)
+ for h in testlog.handlers:
+ testlog.removeHandler(h)
+
+ testlog_file = open(filename, 'w')
+ h = StreamHandler(self.testlog_file)
+ h.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
+ testlog.addHandler(h)
+
+ testlog.debug('Logging started')
+
+def close_test_log():
+ """Close per-test logfile, set `testlog` to `log`."""
+ assert testlog_file is not None
+ testlog_file.close()
+ testlog = log