]> mj.ucw.cz Git - moe.git/blobdiff - t/moe/log.py
Make logs global (class was stupid)
[moe.git] / t / moe / log.py
index 592fb846b047bd7b1952c3e6866080aa1074b67d..f98ee3f3217a49272d3627ca6394efea3231d7e6 100644 (file)
 #!/usr/bin/env python
 
-import sys
-import os
-import traceback
+"""
 
-orig_stdout_fd = os.dup(1)
-orig_stderr_fd = os.dup(2)
-progress_file = os.fdopen(orig_stdout_fd, "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)
+Defines several logs:
 
-    def say(self, msg):
-       if self.log_file:
-           self.log_file.write(msg)
+`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`
 
-    def verbose(self, msg):
-       if self.verbosity and self.log_file:
-           self.log_file.write(msg)
+.. 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 progress(self, msg):
-       if self.progress_file:
-           self.progress_file.write(msg)
 
-    def shout(self, msg):
-       self.say(msg)
-       self.progress(msg)
+# Global logs to be imported by every module
 
-    def flush(self):
-       self.log_file.flush()
+__all__ = ['log', 'userlog', 'testlog', 'pipelog' ]
 
-default = MoeLog()
+log = None
+userlog = None
+testlog = None
+pipelog = None
 
-def fatal_exception():
-    os.dup2(orig_stderr_fd, 2)
-    traceback.print_exc()
-    sys.exit(1)
+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