]> mj.ucw.cz Git - eval.git/blob - t/moe/log.py
Played with the documentation
[eval.git] / t / moe / log.py
1 #!/usr/bin/env python
2
3 """
4
5 `Loggers` is a collection of logggers for :class:`~moe.eval.Eval`, initializing 4 subloggers (see class description).
6
7 Use as `e.log.debug(...)` for main log that goes both to `test` and `main` log,
8 `e.log.test.debug(...)` for individual logs.
9
10 .. :data:: DDEBUG = 5
11         Very verbose debugging level
12
13 """
14
15
16 import sys, os
17 import logging 
18 from logging import Logger, StreamHandler
19
20 logging.addLevelName(5,'DDEBUG')
21
22
23 class Loggers(Logger):
24   """Defines several logs:
25
26   `self` 
27     root log, which sends messages to `eval` and `test` logs
28   `self.eval` 
29     main log, initially a duplicated fd 2 (stderr)
30   `self.user` 
31     public progress log, initially a duplicated fd 1 (stdout)
32   `self.test` 
33     per-test log, initially no handler, to be directed to file like `{TEST}.log`
34
35   .. note:: Currently, the logs and fd's get never closed. 
36   .. warning:: `Loggers.open_eval_log` changes global fd's 1 and 2 by default.
37   """
38   def __init__(self):
39     "Initialize loggers as described in class description."
40     Logger.__init__(self, '')
41     # Duplicate the fd's 
42     self.orig_stdout_fd = os.dup(1)
43     self.orig_stdout_file = os.fdopen(self.orig_stdout_fd, 'w', 0)
44     self.orig_stderr_fd = os.dup(2)
45     self.orig_stderr_file = os.fdopen(self.orig_stderr_fd, 'w', 0)
46     # Eval main logger  
47     self.eval = Logger('eval')
48     self.eval.addHandler(StreamHandler(self.orig_stderr_file))
49     # per-test logger
50     self.test = Logger('test')
51     self.test_handler = None
52     self.test_file = None
53     # user progress logger  
54     self.user = Logger('user')
55     self.eval.addHandler(StreamHandler(self.orig_stdout_file))
56  
57     self.addHandler(self.test)
58     self.addHandler(self.eval)
59     self.debug('Logging initialized.')
60
61   def open_user_log(self, filename, level=logging.INFO):
62     """Open user (progress) logfile. Leaves logging to stdout active."""
63     h = StreamHandler(open(filename, 'w', 0))
64     h.setFormatter(Formatter('%(message)s'))
65     self.user.setLevel(level)
66     self.user.addHandler(h)
67     self.user.debug('Logging started')
68
69   def open_eval_log(self, filename, level, redirect_fds = True):
70     """Open main logfile. 
71     Leaves logging to stderr active. If told to, redirects fd's 1 and 2 to this file.
72     Sets level of both `self.eval` and `self`."""
73     self.eval_file = open(filename, 'w', 0)
74     self.eval_handler = StreamHandler(self.eval_file)
75     self.eval_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
76     self.eval.addHandler(self.eval_handler)
77     if redirect_fds:
78       os.dup2(self.eval_file.fileno(), 1)
79       os.dup2(self.eval_file.fileno(), 2)
80     self.eval.setLevel(level)
81     self.setLevel(level)
82     self.eval.debug('Logging started')
83
84
85   def open_test_log(self, filename, level):
86     """Open per-test log file, like "{TEST}.log". Also set handler level to `level`."""
87     self.debug('Opening per-test log %s' % filename)
88     if self.test_handler:
89       self.close_test_log()
90     self.test_file = open(filename, 'w')
91     self.test_handler = StreamHandler(self.test_file)
92     self.test.addHandler(self.test_handler)
93     self.test.setLevel(level)
94     self.test_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
95     self.test.debug('Logging started')
96
97   def close_test_log(self):
98     """Close per-test logfile, leaving only the null handler."""
99     if self.test_handler:
100       self.test.info('Closing logfile' % filename)
101       self.test.removeHandler(self.test_handler)
102     self.test_handler = None
103     self.test_file.close()
104   
105   def ddebug(self, msg, *args, **kwargs):
106     """Log with priority 5 (normal DEBUG is 10)"""
107     self.log(5, msg, *args, **kwargs)