1 import logging
, os
, sys
, time
3 # set up a simple catchall configuration for use during import time. some code
4 # may log messages at import time and we don't want those to get completely
5 # thrown away. we'll clear this out when actual configuration takes place.
6 logging
.basicConfig(level
=logging
.DEBUG
)
8 class AllowBelowSeverity(logging
.Filter
):
10 Allows only records less severe than a given level (the opposite of what
11 the normal logging level filtering does.
13 def __init__(self
, level
):
17 def filter(self
, record
):
18 return record
.levelno
< self
.level
21 class LoggingConfig(object):
22 global_level
= logging
.DEBUG
23 stdout_level
= logging
.INFO
24 stderr_level
= logging
.ERROR
26 file_formatter
= logging
.Formatter(
27 fmt
='%(asctime)s %(levelname)-5.5s|%(module)10.10s:%(lineno)4.4d| '
29 datefmt
='%m/%d %H:%M:%S')
31 console_formatter
= logging
.Formatter(
32 fmt
='%(asctime)s %(levelname)-5.5s| %(message)s',
35 def __init__(self
, use_console
=True):
36 self
.logger
= logging
.getLogger()
37 self
.global_level
= logging
.DEBUG
38 self
.use_console
= use_console
42 def get_timestamped_log_name(cls
, base_name
):
43 return '%s.log.%s' % (base_name
, time
.strftime('%Y-%m-%d-%H.%M.%S'))
47 def get_autotest_root(cls
):
48 common_lib_dir
= os
.path
.dirname(__file__
)
49 return os
.path
.abspath(os
.path
.join(common_lib_dir
, '..', '..'))
53 def get_server_log_dir(cls
):
54 return os
.path
.join(cls
.get_autotest_root(), 'logs')
57 def add_stream_handler(self
, stream
, level
=logging
.DEBUG
):
58 handler
= logging
.StreamHandler(stream
)
59 handler
.setLevel(level
)
60 handler
.setFormatter(self
.console_formatter
)
61 self
.logger
.addHandler(handler
)
65 def add_console_handlers(self
):
66 stdout_handler
= self
.add_stream_handler(sys
.stdout
,
67 level
=self
.stdout_level
)
68 # only pass records *below* STDERR_LEVEL to stdout, to avoid duplication
69 stdout_handler
.addFilter(AllowBelowSeverity(self
.stderr_level
))
71 self
.add_stream_handler(sys
.stderr
, self
.stderr_level
)
74 def add_file_handler(self
, file_path
, level
=logging
.DEBUG
, log_dir
=None):
76 file_path
= os
.path
.join(log_dir
, file_path
)
77 handler
= logging
.FileHandler(file_path
)
78 handler
.setLevel(level
)
79 handler
.setFormatter(self
.file_formatter
)
80 self
.logger
.addHandler(handler
)
84 def _add_file_handlers_for_all_levels(self
, log_dir
, log_name
):
85 for level
in (logging
.DEBUG
, logging
.INFO
, logging
.WARNING
,
87 file_name
= '%s.%s' % (log_name
, logging
.getLevelName(level
))
88 self
.add_file_handler(file_name
, level
=level
, log_dir
=log_dir
)
91 def add_debug_file_handlers(self
, log_dir
, log_name
=None):
92 raise NotImplementedError
95 def _clear_all_handlers(self
):
96 for handler
in list(self
.logger
.handlers
):
97 self
.logger
.removeHandler(handler
)
98 # Attempt to close the handler. If it's already closed a KeyError
99 # will be generated. http://bugs.python.org/issue8581
106 def configure_logging(self
, use_console
=True, verbose
=False):
107 self
._clear
_all
_handlers
() # see comment at top of file
108 self
.logger
.setLevel(self
.global_level
)
111 self
.stdout_level
= logging
.DEBUG
113 self
.add_console_handlers()
116 class TestingConfig(LoggingConfig
):
117 def add_stream_handler(self
, *args
, **kwargs
):
121 def add_file_handler(self
, *args
, **kwargs
):
125 def configure_logging(self
, **kwargs
):