root / snf-tools / synnefo_tools / burnin / logger.py @ 3e5bbd85
History | View | Annotate | Download (15.5 kB)
1 | 4c52d5bf | Ilias Tsitsimpis | # Copyright 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 4c52d5bf | Ilias Tsitsimpis | #
|
3 | 4c52d5bf | Ilias Tsitsimpis | # Redistribution and use in source and binary forms, with or
|
4 | 4c52d5bf | Ilias Tsitsimpis | # without modification, are permitted provided that the following
|
5 | 4c52d5bf | Ilias Tsitsimpis | # conditions are met:
|
6 | 4c52d5bf | Ilias Tsitsimpis | #
|
7 | 4c52d5bf | Ilias Tsitsimpis | # 1. Redistributions of source code must retain the above
|
8 | 4c52d5bf | Ilias Tsitsimpis | # copyright notice, this list of conditions and the following
|
9 | 4c52d5bf | Ilias Tsitsimpis | # disclaimer.
|
10 | 4c52d5bf | Ilias Tsitsimpis | #
|
11 | 4c52d5bf | Ilias Tsitsimpis | # 2. Redistributions in binary form must reproduce the above
|
12 | 4c52d5bf | Ilias Tsitsimpis | # copyright notice, this list of conditions and the following
|
13 | 4c52d5bf | Ilias Tsitsimpis | # disclaimer in the documentation and/or other materials
|
14 | 4c52d5bf | Ilias Tsitsimpis | # provided with the distribution.
|
15 | 4c52d5bf | Ilias Tsitsimpis | #
|
16 | 4c52d5bf | Ilias Tsitsimpis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 4c52d5bf | Ilias Tsitsimpis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 4c52d5bf | Ilias Tsitsimpis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 4c52d5bf | Ilias Tsitsimpis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 4c52d5bf | Ilias Tsitsimpis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 4c52d5bf | Ilias Tsitsimpis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 4c52d5bf | Ilias Tsitsimpis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 4c52d5bf | Ilias Tsitsimpis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 4c52d5bf | Ilias Tsitsimpis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 4c52d5bf | Ilias Tsitsimpis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 4c52d5bf | Ilias Tsitsimpis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 4c52d5bf | Ilias Tsitsimpis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 4c52d5bf | Ilias Tsitsimpis | #
|
29 | 4c52d5bf | Ilias Tsitsimpis | # The views and conclusions contained in the software and
|
30 | 4c52d5bf | Ilias Tsitsimpis | # documentation are those of the authors and should not be
|
31 | 4c52d5bf | Ilias Tsitsimpis | # interpreted as representing official policies, either expressed
|
32 | 4c52d5bf | Ilias Tsitsimpis | # or implied, of GRNET S.A.
|
33 | 4c52d5bf | Ilias Tsitsimpis | |
34 | 4c52d5bf | Ilias Tsitsimpis | """
|
35 | 4c52d5bf | Ilias Tsitsimpis | This is the logging class for burnin
|
36 | 4c52d5bf | Ilias Tsitsimpis |
|
37 | 4c52d5bf | Ilias Tsitsimpis | It supports logging both for the stdout/stderr as well as file logging at the
|
38 | 4c52d5bf | Ilias Tsitsimpis | same time.
|
39 | 4c52d5bf | Ilias Tsitsimpis |
|
40 | 4c52d5bf | Ilias Tsitsimpis | The stdout/stderr logger supports verbose levels and colors but the file
|
41 | 4c52d5bf | Ilias Tsitsimpis | logging doesn't (we use the info verbose level for our file logger).
|
42 | 4c52d5bf | Ilias Tsitsimpis |
|
43 | 4c52d5bf | Ilias Tsitsimpis | Our loggers have primitive support for handling parallel execution (even though
|
44 | 4c52d5bf | Ilias Tsitsimpis | burnin doesn't support it yet). To do so the stdout/stderr logger prepends the
|
45 | 4c52d5bf | Ilias Tsitsimpis | name of the test under execution to every line it prints. On the other hand the
|
46 | 4c52d5bf | Ilias Tsitsimpis | file logger waits to lock the file, then reads it, prints the message to the
|
47 | 4c52d5bf | Ilias Tsitsimpis | corresponding line and closes the file.
|
48 | 4c52d5bf | Ilias Tsitsimpis |
|
49 | 4c52d5bf | Ilias Tsitsimpis |
|
50 | 4c52d5bf | Ilias Tsitsimpis | """
|
51 | 4c52d5bf | Ilias Tsitsimpis | |
52 | 4c52d5bf | Ilias Tsitsimpis | import os |
53 | 4c52d5bf | Ilias Tsitsimpis | import sys |
54 | 4c52d5bf | Ilias Tsitsimpis | import os.path |
55 | 4c52d5bf | Ilias Tsitsimpis | import datetime |
56 | 4c52d5bf | Ilias Tsitsimpis | |
57 | 12ef696f | Ilias Tsitsimpis | from synnefo_tools.burnin import filelocker |
58 | 4c52d5bf | Ilias Tsitsimpis | |
59 | 4c52d5bf | Ilias Tsitsimpis | |
60 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
61 | 4c52d5bf | Ilias Tsitsimpis | # Constant variables
|
62 | 4c52d5bf | Ilias Tsitsimpis | LOCK_EXT = ".lock"
|
63 | 4c52d5bf | Ilias Tsitsimpis | SECTION_SEPARATOR = \ |
64 | 4c52d5bf | Ilias Tsitsimpis | "-- -------------------------------------------------------------------"
|
65 | 4c52d5bf | Ilias Tsitsimpis | SECTION_PREFIX = "-- "
|
66 | 06c9d4db | Ilias Tsitsimpis | SECTION_RUNNED = "Tests Run"
|
67 | 4c52d5bf | Ilias Tsitsimpis | SECTION_RESULTS = "Results"
|
68 | 4c52d5bf | Ilias Tsitsimpis | SECTION_NEW = "__ADD_NEW_SECTION__"
|
69 | 4c52d5bf | Ilias Tsitsimpis | SECTION_PASSED = " * Passed:"
|
70 | 4c52d5bf | Ilias Tsitsimpis | SECTION_FAILED = " * Failed:"
|
71 | 4c52d5bf | Ilias Tsitsimpis | |
72 | 4c52d5bf | Ilias Tsitsimpis | |
73 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
74 | 4c52d5bf | Ilias Tsitsimpis | # Helper functions
|
75 | 3e5bbd85 | Ilias Tsitsimpis | def _cyan(msg): |
76 | 3e5bbd85 | Ilias Tsitsimpis | """Bold High Intensity Cyan color"""
|
77 | 3e5bbd85 | Ilias Tsitsimpis | return "\x1b[1;96m" + str(msg) + "\x1b[0m" |
78 | 4c52d5bf | Ilias Tsitsimpis | |
79 | 4c52d5bf | Ilias Tsitsimpis | |
80 | 4c52d5bf | Ilias Tsitsimpis | def _yellow(msg): |
81 | 4c52d5bf | Ilias Tsitsimpis | """Yellow color"""
|
82 | 4c52d5bf | Ilias Tsitsimpis | return "\x1b[33m" + str(msg) + "\x1b[0m" |
83 | 4c52d5bf | Ilias Tsitsimpis | |
84 | 4c52d5bf | Ilias Tsitsimpis | |
85 | 4c52d5bf | Ilias Tsitsimpis | def _red(msg): |
86 | 4c52d5bf | Ilias Tsitsimpis | """Yellow color"""
|
87 | 4c52d5bf | Ilias Tsitsimpis | return "\x1b[31m" + str(msg) + "\x1b[0m" |
88 | 4c52d5bf | Ilias Tsitsimpis | |
89 | 4c52d5bf | Ilias Tsitsimpis | |
90 | 12ef696f | Ilias Tsitsimpis | def _magenta(msg): |
91 | 12ef696f | Ilias Tsitsimpis | """Magenta color"""
|
92 | 4c52d5bf | Ilias Tsitsimpis | return "\x1b[35m" + str(msg) + "\x1b[0m" |
93 | 4c52d5bf | Ilias Tsitsimpis | |
94 | 4c52d5bf | Ilias Tsitsimpis | |
95 | 12ef696f | Ilias Tsitsimpis | def _green(msg): |
96 | 12ef696f | Ilias Tsitsimpis | """Green color"""
|
97 | 12ef696f | Ilias Tsitsimpis | return "\x1b[32m" + str(msg) + "\x1b[0m" |
98 | 4c52d5bf | Ilias Tsitsimpis | |
99 | 4c52d5bf | Ilias Tsitsimpis | |
100 | 4c52d5bf | Ilias Tsitsimpis | def _format_message(msg, *args): |
101 | 4c52d5bf | Ilias Tsitsimpis | """Format the message using the args"""
|
102 | 6c78720b | Ilias Tsitsimpis | if args:
|
103 | 6c78720b | Ilias Tsitsimpis | return (msg % args) + "\n" |
104 | 6c78720b | Ilias Tsitsimpis | else:
|
105 | 6c78720b | Ilias Tsitsimpis | return msg + "\n" |
106 | 4c52d5bf | Ilias Tsitsimpis | |
107 | 4c52d5bf | Ilias Tsitsimpis | |
108 | 4c52d5bf | Ilias Tsitsimpis | def _list_to_string(lst, append=""): |
109 | 4c52d5bf | Ilias Tsitsimpis | """Convert a list of strings to string
|
110 | 4c52d5bf | Ilias Tsitsimpis |
|
111 | 4c52d5bf | Ilias Tsitsimpis | Append the value given in L{append} in front of all lines
|
112 | 4c52d5bf | Ilias Tsitsimpis | (except of the first line).
|
113 | 4c52d5bf | Ilias Tsitsimpis |
|
114 | 4c52d5bf | Ilias Tsitsimpis | """
|
115 | 4c52d5bf | Ilias Tsitsimpis | if isinstance(lst, list): |
116 | 4c52d5bf | Ilias Tsitsimpis | return append.join(lst).rstrip('\n') |
117 | 4c52d5bf | Ilias Tsitsimpis | else:
|
118 | 4c52d5bf | Ilias Tsitsimpis | return lst.rstrip('\n') |
119 | 4c52d5bf | Ilias Tsitsimpis | |
120 | 4c52d5bf | Ilias Tsitsimpis | |
121 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------
|
122 | 4c52d5bf | Ilias Tsitsimpis | def _locate_sections(contents): |
123 | 4c52d5bf | Ilias Tsitsimpis | """Locate the sections inside the logging file"""
|
124 | 4c52d5bf | Ilias Tsitsimpis | i = 0
|
125 | 4c52d5bf | Ilias Tsitsimpis | res = [] |
126 | 4c52d5bf | Ilias Tsitsimpis | for cnt in contents: |
127 | 4c52d5bf | Ilias Tsitsimpis | if SECTION_SEPARATOR in cnt: |
128 | 4c52d5bf | Ilias Tsitsimpis | res.append(i+1)
|
129 | 4c52d5bf | Ilias Tsitsimpis | i += 1
|
130 | 4c52d5bf | Ilias Tsitsimpis | return res
|
131 | 4c52d5bf | Ilias Tsitsimpis | |
132 | 4c52d5bf | Ilias Tsitsimpis | |
133 | 4c52d5bf | Ilias Tsitsimpis | def _locate_input(contents, section): |
134 | 4c52d5bf | Ilias Tsitsimpis | """Locate position to insert text
|
135 | 4c52d5bf | Ilias Tsitsimpis |
|
136 | 4c52d5bf | Ilias Tsitsimpis | Given a section location the next possition to insert text inside that
|
137 | 4c52d5bf | Ilias Tsitsimpis | section.
|
138 | 4c52d5bf | Ilias Tsitsimpis |
|
139 | 4c52d5bf | Ilias Tsitsimpis | """
|
140 | 4c52d5bf | Ilias Tsitsimpis | sect_locs = _locate_sections(contents) |
141 | 4c52d5bf | Ilias Tsitsimpis | if section == SECTION_NEW:
|
142 | 4c52d5bf | Ilias Tsitsimpis | # We want to add a new section
|
143 | 4c52d5bf | Ilias Tsitsimpis | # Just return the position of SECTION_RESULTS
|
144 | 4c52d5bf | Ilias Tsitsimpis | for obj in sect_locs: |
145 | 4c52d5bf | Ilias Tsitsimpis | if SECTION_RESULTS in contents[obj]: |
146 | 4c52d5bf | Ilias Tsitsimpis | return obj - 1 |
147 | 4c52d5bf | Ilias Tsitsimpis | else:
|
148 | 4c52d5bf | Ilias Tsitsimpis | # We will add our message in this location
|
149 | 4c52d5bf | Ilias Tsitsimpis | for (index, obj) in enumerate(sect_locs): |
150 | 4c52d5bf | Ilias Tsitsimpis | if section in contents[obj]: |
151 | 4c52d5bf | Ilias Tsitsimpis | return sect_locs[index+1] - 3 |
152 | 4c52d5bf | Ilias Tsitsimpis | |
153 | 4c52d5bf | Ilias Tsitsimpis | # We didn't find our section??
|
154 | 4c52d5bf | Ilias Tsitsimpis | sys.stderr.write("Section %s could not be found in logging file\n"
|
155 | 4c52d5bf | Ilias Tsitsimpis | % section) |
156 | 12ef696f | Ilias Tsitsimpis | sys.exit("Error in logger._locate_input")
|
157 | 4c52d5bf | Ilias Tsitsimpis | |
158 | 4c52d5bf | Ilias Tsitsimpis | |
159 | 4c52d5bf | Ilias Tsitsimpis | def _add_testsuite_results(contents, section, testsuite): |
160 | 4c52d5bf | Ilias Tsitsimpis | """Add the given testsuite to results
|
161 | 4c52d5bf | Ilias Tsitsimpis |
|
162 | 4c52d5bf | Ilias Tsitsimpis | Well we know that SECTION_FAILED is the last line and SECTION_PASSED is the
|
163 | 4c52d5bf | Ilias Tsitsimpis | line before, so we are going to cheat here and use this information.
|
164 | 4c52d5bf | Ilias Tsitsimpis |
|
165 | 4c52d5bf | Ilias Tsitsimpis | """
|
166 | 4c52d5bf | Ilias Tsitsimpis | if section == SECTION_PASSED:
|
167 | 06c9d4db | Ilias Tsitsimpis | line = contents[-2].rstrip()
|
168 | 06c9d4db | Ilias Tsitsimpis | if line.endswith(":"): |
169 | 06c9d4db | Ilias Tsitsimpis | new_line = line + " " + testsuite + "\n" |
170 | 06c9d4db | Ilias Tsitsimpis | else:
|
171 | 06c9d4db | Ilias Tsitsimpis | new_line = line + ", " + testsuite + "\n" |
172 | 4c52d5bf | Ilias Tsitsimpis | contents[-2] = new_line
|
173 | 4c52d5bf | Ilias Tsitsimpis | elif section == SECTION_FAILED:
|
174 | 06c9d4db | Ilias Tsitsimpis | line = contents[-1].rstrip()
|
175 | 06c9d4db | Ilias Tsitsimpis | if line.endswith(":"): |
176 | 06c9d4db | Ilias Tsitsimpis | new_line = line.rstrip() + " " + testsuite + "\n" |
177 | 06c9d4db | Ilias Tsitsimpis | else:
|
178 | 06c9d4db | Ilias Tsitsimpis | new_line = line.rstrip() + ", " + testsuite + "\n" |
179 | 4c52d5bf | Ilias Tsitsimpis | contents[-1] = new_line
|
180 | 4c52d5bf | Ilias Tsitsimpis | else:
|
181 | 4c52d5bf | Ilias Tsitsimpis | sys.stderr.write("Unknown section %s in _add_testsuite_results\n"
|
182 | 4c52d5bf | Ilias Tsitsimpis | % section) |
183 | 12ef696f | Ilias Tsitsimpis | sys.exit("Error in logger._add_testsuite_results")
|
184 | 4c52d5bf | Ilias Tsitsimpis | return contents
|
185 | 4c52d5bf | Ilias Tsitsimpis | |
186 | 4c52d5bf | Ilias Tsitsimpis | |
187 | 4c52d5bf | Ilias Tsitsimpis | def _write_log_file(file_location, section, message): |
188 | 4c52d5bf | Ilias Tsitsimpis | """Write something to our log file
|
189 | 4c52d5bf | Ilias Tsitsimpis |
|
190 | 4c52d5bf | Ilias Tsitsimpis | For this we have to get the lock, read and parse the file add the new
|
191 | 4c52d5bf | Ilias Tsitsimpis | message and re-write the file.
|
192 | 4c52d5bf | Ilias Tsitsimpis |
|
193 | 4c52d5bf | Ilias Tsitsimpis | """
|
194 | 4c52d5bf | Ilias Tsitsimpis | # Get the lock
|
195 | 4c52d5bf | Ilias Tsitsimpis | file_lock = os.path.splitext(file_location)[0] + LOCK_EXT
|
196 | 4c52d5bf | Ilias Tsitsimpis | with filelocker.lock(file_lock, filelocker.LOCK_EX):
|
197 | 4c52d5bf | Ilias Tsitsimpis | with open(file_location, "r+") as log_file: |
198 | 4c52d5bf | Ilias Tsitsimpis | contents = log_file.readlines() |
199 | 4c52d5bf | Ilias Tsitsimpis | if section == SECTION_PASSED or section == SECTION_FAILED: |
200 | 4c52d5bf | Ilias Tsitsimpis | # Add testsuite to results
|
201 | 4c52d5bf | Ilias Tsitsimpis | new_contents = \ |
202 | 4c52d5bf | Ilias Tsitsimpis | _add_testsuite_results(contents, section, message) |
203 | 4c52d5bf | Ilias Tsitsimpis | else:
|
204 | 4c52d5bf | Ilias Tsitsimpis | # Add message to its line
|
205 | 4c52d5bf | Ilias Tsitsimpis | input_loc = _locate_input(contents, section) |
206 | 4c52d5bf | Ilias Tsitsimpis | new_contents = \ |
207 | 4c52d5bf | Ilias Tsitsimpis | contents[:input_loc] + [message] + contents[input_loc:] |
208 | 4c52d5bf | Ilias Tsitsimpis | log_file.seek(0)
|
209 | 4c52d5bf | Ilias Tsitsimpis | log_file.write("".join(new_contents))
|
210 | 4c52d5bf | Ilias Tsitsimpis | |
211 | 4c52d5bf | Ilias Tsitsimpis | |
212 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
213 | 4c52d5bf | Ilias Tsitsimpis | # The Log class
|
214 | 4c52d5bf | Ilias Tsitsimpis | class Log(object): |
215 | 4c52d5bf | Ilias Tsitsimpis | """Burnin logger
|
216 | 4c52d5bf | Ilias Tsitsimpis |
|
217 | 4c52d5bf | Ilias Tsitsimpis | """
|
218 | 4c52d5bf | Ilias Tsitsimpis | # ----------------------------------
|
219 | 0c1833c8 | Ilias Tsitsimpis | # Too many arguments. pylint: disable-msg=R0913
|
220 | 4c52d5bf | Ilias Tsitsimpis | def __init__(self, output_dir, verbose=1, use_colors=True, |
221 | ee89df69 | Ilias Tsitsimpis | in_parallel=False, log_level=0, curr_time=None): |
222 | 4c52d5bf | Ilias Tsitsimpis | """Initialize our loggers
|
223 | 4c52d5bf | Ilias Tsitsimpis |
|
224 | 4c52d5bf | Ilias Tsitsimpis | The file to be used by our file logger will be created inside
|
225 | 4c52d5bf | Ilias Tsitsimpis | the L{output_dir} with name the current timestamp.
|
226 | 4c52d5bf | Ilias Tsitsimpis |
|
227 | 4c52d5bf | Ilias Tsitsimpis | @type output_dir: string
|
228 | 4c52d5bf | Ilias Tsitsimpis | @param output_dir: the directory to save the output file
|
229 | 4c52d5bf | Ilias Tsitsimpis | @type verbose: int
|
230 | 4c52d5bf | Ilias Tsitsimpis | @param verbose: the verbose level to use for stdout/stderr logger
|
231 | 4c52d5bf | Ilias Tsitsimpis | 0: verbose at minimum level (only which test we are running now)
|
232 | 4c52d5bf | Ilias Tsitsimpis | 1: verbose at info level (information about our running test)
|
233 | 4c52d5bf | Ilias Tsitsimpis | 2: verbose at debug level
|
234 | 4c52d5bf | Ilias Tsitsimpis | @type use_colors: boolean
|
235 | 4c52d5bf | Ilias Tsitsimpis | @param use_colors: use colors for out stdout/stderr logger
|
236 | 4c52d5bf | Ilias Tsitsimpis | @type in_parallel: boolean
|
237 | 4c52d5bf | Ilias Tsitsimpis | @param in_parallel: this signifies that burnin is running in parallel
|
238 | ee89df69 | Ilias Tsitsimpis | @type log_level: int
|
239 | ee89df69 | Ilias Tsitsimpis | @param log_level: logging level
|
240 | ee89df69 | Ilias Tsitsimpis | 0: log to console and file
|
241 | ee89df69 | Ilias Tsitsimpis | 1: log to file only and output the results to console
|
242 | ee89df69 | Ilias Tsitsimpis | 2: don't log
|
243 | ee89df69 | Ilias Tsitsimpis | @type curr_time: datetime.datetime()
|
244 | ee89df69 | Ilias Tsitsimpis | @param curr_time: The current time (used as burnin's run id)
|
245 | 4c52d5bf | Ilias Tsitsimpis |
|
246 | 4c52d5bf | Ilias Tsitsimpis | """
|
247 | 4c52d5bf | Ilias Tsitsimpis | self.verbose = verbose
|
248 | 4c52d5bf | Ilias Tsitsimpis | self.use_colors = use_colors
|
249 | 4c52d5bf | Ilias Tsitsimpis | self.in_parallel = in_parallel
|
250 | ee89df69 | Ilias Tsitsimpis | self.log_level = log_level
|
251 | 4c52d5bf | Ilias Tsitsimpis | |
252 | 12ef696f | Ilias Tsitsimpis | assert output_dir
|
253 | 12ef696f | Ilias Tsitsimpis | |
254 | 2afd10bf | Ilias Tsitsimpis | if curr_time is None: |
255 | 2afd10bf | Ilias Tsitsimpis | curr_time = datetime.datetime.now() |
256 | 4c52d5bf | Ilias Tsitsimpis | timestamp = datetime.datetime.strftime( |
257 | 2afd10bf | Ilias Tsitsimpis | curr_time, "%Y%m%d%H%M%S (%a %b %d %Y %H:%M)")
|
258 | 4c52d5bf | Ilias Tsitsimpis | file_name = timestamp + ".log"
|
259 | 4c52d5bf | Ilias Tsitsimpis | self.file_location = os.path.join(output_dir, file_name)
|
260 | 4c52d5bf | Ilias Tsitsimpis | |
261 | 2afd10bf | Ilias Tsitsimpis | self._write_to_stdout(None, "Starting burnin with id %s\n" % timestamp) |
262 | 4c52d5bf | Ilias Tsitsimpis | |
263 | 4c52d5bf | Ilias Tsitsimpis | # Create the logging file
|
264 | 828bbf06 | Ilias Tsitsimpis | self._create_logging_file(timestamp, output_dir)
|
265 | 4c52d5bf | Ilias Tsitsimpis | |
266 | 828bbf06 | Ilias Tsitsimpis | def _create_logging_file(self, timestamp, output_dir): |
267 | 4c52d5bf | Ilias Tsitsimpis | """Create the logging file"""
|
268 | ee89df69 | Ilias Tsitsimpis | if self.log_level > 1: |
269 | ee89df69 | Ilias Tsitsimpis | return
|
270 | 828bbf06 | Ilias Tsitsimpis | |
271 | 828bbf06 | Ilias Tsitsimpis | # Create file for logging
|
272 | 828bbf06 | Ilias Tsitsimpis | output_dir = os.path.expanduser(output_dir) |
273 | 828bbf06 | Ilias Tsitsimpis | if not os.path.exists(output_dir): |
274 | 828bbf06 | Ilias Tsitsimpis | self.debug(None, "Creating directory %s", output_dir) |
275 | 828bbf06 | Ilias Tsitsimpis | try:
|
276 | 828bbf06 | Ilias Tsitsimpis | os.makedirs(output_dir) |
277 | 828bbf06 | Ilias Tsitsimpis | except OSError as err: |
278 | 828bbf06 | Ilias Tsitsimpis | msg = ("Failed to create folder \"%s\" with error: %s\n"
|
279 | 828bbf06 | Ilias Tsitsimpis | % (output_dir, err)) |
280 | 828bbf06 | Ilias Tsitsimpis | sys.stderr.write(msg) |
281 | 828bbf06 | Ilias Tsitsimpis | sys.exit("Failed to create log folder")
|
282 | 828bbf06 | Ilias Tsitsimpis | |
283 | 4c52d5bf | Ilias Tsitsimpis | self.debug(None, "Using \"%s\" file for logging", self.file_location) |
284 | 4c52d5bf | Ilias Tsitsimpis | with open(self.file_location, 'w') as out_file: |
285 | 4c52d5bf | Ilias Tsitsimpis | out_file.write(SECTION_SEPARATOR + "\n")
|
286 | 828bbf06 | Ilias Tsitsimpis | out_file.write("%s%s with id %s:\n\n\n\n" %
|
287 | 4c52d5bf | Ilias Tsitsimpis | (SECTION_PREFIX, SECTION_RUNNED, timestamp)) |
288 | 4c52d5bf | Ilias Tsitsimpis | out_file.write(SECTION_SEPARATOR + "\n")
|
289 | 4c52d5bf | Ilias Tsitsimpis | out_file.write("%s%s:\n\n" % (SECTION_PREFIX, SECTION_RESULTS))
|
290 | 4c52d5bf | Ilias Tsitsimpis | out_file.write(SECTION_PASSED + "\n" + SECTION_FAILED + "\n") |
291 | 4c52d5bf | Ilias Tsitsimpis | |
292 | 4c52d5bf | Ilias Tsitsimpis | def __del__(self): |
293 | 4c52d5bf | Ilias Tsitsimpis | """Delete the Log object"""
|
294 | ee89df69 | Ilias Tsitsimpis | self.print_logfile_to_stdout()
|
295 | 4c52d5bf | Ilias Tsitsimpis | # Remove the lock file
|
296 | 12ef696f | Ilias Tsitsimpis | if hasattr(self, "file_location"): |
297 | 12ef696f | Ilias Tsitsimpis | file_lock = os.path.splitext(self.file_location)[0] + LOCK_EXT |
298 | 12ef696f | Ilias Tsitsimpis | try:
|
299 | 12ef696f | Ilias Tsitsimpis | os.remove(file_lock) |
300 | 12ef696f | Ilias Tsitsimpis | except OSError: |
301 | 12ef696f | Ilias Tsitsimpis | self.debug(None, "Couldn't delete lock file") |
302 | 4c52d5bf | Ilias Tsitsimpis | |
303 | 0c1833c8 | Ilias Tsitsimpis | def print_logfile_to_stdout(self): |
304 | 0c1833c8 | Ilias Tsitsimpis | """Print the contents of our log file to stdout"""
|
305 | ee89df69 | Ilias Tsitsimpis | if self.log_level == 1: |
306 | ee89df69 | Ilias Tsitsimpis | with open(self.file_location, 'r') as fin: |
307 | ee89df69 | Ilias Tsitsimpis | sys.stdout.write(fin.read()) |
308 | 0c1833c8 | Ilias Tsitsimpis | |
309 | 4c52d5bf | Ilias Tsitsimpis | # ----------------------------------
|
310 | 4c52d5bf | Ilias Tsitsimpis | # Logging methods
|
311 | 4c52d5bf | Ilias Tsitsimpis | def debug(self, section, msg, *args): |
312 | 4c52d5bf | Ilias Tsitsimpis | """Debug messages (verbose 2)
|
313 | 4c52d5bf | Ilias Tsitsimpis |
|
314 | 4c52d5bf | Ilias Tsitsimpis | We show debug messages only to stdout. The message will be formatted
|
315 | 4c52d5bf | Ilias Tsitsimpis | using the args.
|
316 | 4c52d5bf | Ilias Tsitsimpis |
|
317 | 4c52d5bf | Ilias Tsitsimpis | """
|
318 | 4c52d5bf | Ilias Tsitsimpis | msg = " (DD) " + _list_to_string(msg, append=" ") |
319 | 4c52d5bf | Ilias Tsitsimpis | if self.verbose >= 2: |
320 | 4c52d5bf | Ilias Tsitsimpis | colored_msg = self._color_message(None, msg, *args) |
321 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stdout(section, colored_msg)
|
322 | 4c52d5bf | Ilias Tsitsimpis | |
323 | 4c52d5bf | Ilias Tsitsimpis | def log(self, section, msg, *args): |
324 | 4c52d5bf | Ilias Tsitsimpis | """Normal messages (verbose 0)"""
|
325 | 4c52d5bf | Ilias Tsitsimpis | assert section, "Section can not be empty" |
326 | 4c52d5bf | Ilias Tsitsimpis | |
327 | 4c52d5bf | Ilias Tsitsimpis | msg = _list_to_string(msg) |
328 | 4c52d5bf | Ilias Tsitsimpis | |
329 | 4c52d5bf | Ilias Tsitsimpis | colored_msg = self._color_message(None, msg, *args) |
330 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stdout(section, colored_msg)
|
331 | 4c52d5bf | Ilias Tsitsimpis | |
332 | 4c52d5bf | Ilias Tsitsimpis | plain_msg = _format_message(msg, *args) |
333 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_file(section, plain_msg)
|
334 | 4c52d5bf | Ilias Tsitsimpis | |
335 | 4c52d5bf | Ilias Tsitsimpis | def info(self, section, msg, *args): |
336 | 4c52d5bf | Ilias Tsitsimpis | """Info messages (verbose 1)
|
337 | 4c52d5bf | Ilias Tsitsimpis |
|
338 | 4c52d5bf | Ilias Tsitsimpis | Prepare message and write it to file logger and stdout logger
|
339 | 4c52d5bf | Ilias Tsitsimpis |
|
340 | 4c52d5bf | Ilias Tsitsimpis | """
|
341 | 4c52d5bf | Ilias Tsitsimpis | assert section, "Section can not be empty" |
342 | 4c52d5bf | Ilias Tsitsimpis | |
343 | 4c52d5bf | Ilias Tsitsimpis | msg = " " + _list_to_string(msg, " ") |
344 | 4c52d5bf | Ilias Tsitsimpis | if self.verbose >= 1: |
345 | 4c52d5bf | Ilias Tsitsimpis | colored_msg = self._color_message(None, msg, *args) |
346 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stdout(section, colored_msg)
|
347 | 4c52d5bf | Ilias Tsitsimpis | |
348 | 4c52d5bf | Ilias Tsitsimpis | plain_msg = _format_message(msg, *args) |
349 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_file(section, plain_msg)
|
350 | 4c52d5bf | Ilias Tsitsimpis | |
351 | 4c52d5bf | Ilias Tsitsimpis | def warning(self, section, msg, *args): |
352 | 4c52d5bf | Ilias Tsitsimpis | """Warning messages"""
|
353 | 4c52d5bf | Ilias Tsitsimpis | assert section, "Section can not be empty" |
354 | 4c52d5bf | Ilias Tsitsimpis | |
355 | 4c52d5bf | Ilias Tsitsimpis | msg = " (WW) " + _list_to_string(msg, " ") |
356 | 4c52d5bf | Ilias Tsitsimpis | |
357 | 4c52d5bf | Ilias Tsitsimpis | colored_msg = self._color_message(_yellow, msg, *args)
|
358 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stderr(section, colored_msg)
|
359 | 4c52d5bf | Ilias Tsitsimpis | |
360 | 4c52d5bf | Ilias Tsitsimpis | plain_msg = _format_message(msg, *args) |
361 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_file(section, plain_msg)
|
362 | 4c52d5bf | Ilias Tsitsimpis | |
363 | 4c52d5bf | Ilias Tsitsimpis | def error(self, section, msg, *args): |
364 | 4c52d5bf | Ilias Tsitsimpis | """Error messages"""
|
365 | 4c52d5bf | Ilias Tsitsimpis | assert section, "Section can not be empty" |
366 | 4c52d5bf | Ilias Tsitsimpis | |
367 | 4c52d5bf | Ilias Tsitsimpis | msg = " (EE) " + _list_to_string(msg, " ") |
368 | 4c52d5bf | Ilias Tsitsimpis | |
369 | 4c52d5bf | Ilias Tsitsimpis | colored_msg = self._color_message(_red, msg, *args)
|
370 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stderr(section, colored_msg)
|
371 | 4c52d5bf | Ilias Tsitsimpis | |
372 | 4c52d5bf | Ilias Tsitsimpis | plain_msg = _format_message(msg, *args) |
373 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_file(section, plain_msg)
|
374 | 4c52d5bf | Ilias Tsitsimpis | |
375 | 4c52d5bf | Ilias Tsitsimpis | def _write_to_stdout(self, section, msg): |
376 | 4c52d5bf | Ilias Tsitsimpis | """Write to stdout"""
|
377 | ee89df69 | Ilias Tsitsimpis | if self.log_level > 0: |
378 | ee89df69 | Ilias Tsitsimpis | return
|
379 | ee89df69 | Ilias Tsitsimpis | if section is not None and self.in_parallel: |
380 | ee89df69 | Ilias Tsitsimpis | sys.stdout.write(section + ": " + msg)
|
381 | ee89df69 | Ilias Tsitsimpis | else:
|
382 | ee89df69 | Ilias Tsitsimpis | sys.stdout.write(msg) |
383 | 4c52d5bf | Ilias Tsitsimpis | |
384 | 4c52d5bf | Ilias Tsitsimpis | def _write_to_stderr(self, section, msg): |
385 | 4c52d5bf | Ilias Tsitsimpis | """Write to stderr"""
|
386 | ee89df69 | Ilias Tsitsimpis | if self.log_level > 0: |
387 | ee89df69 | Ilias Tsitsimpis | return
|
388 | ee89df69 | Ilias Tsitsimpis | if section is not None and self.in_parallel: |
389 | ee89df69 | Ilias Tsitsimpis | sys.stderr.write(section + ": " + msg)
|
390 | ee89df69 | Ilias Tsitsimpis | else:
|
391 | ee89df69 | Ilias Tsitsimpis | sys.stderr.write(msg) |
392 | 4c52d5bf | Ilias Tsitsimpis | |
393 | 4c52d5bf | Ilias Tsitsimpis | def _write_to_file(self, section, msg): |
394 | 4c52d5bf | Ilias Tsitsimpis | """Write to file"""
|
395 | ee89df69 | Ilias Tsitsimpis | if self.log_level > 1: |
396 | ee89df69 | Ilias Tsitsimpis | return
|
397 | 4c52d5bf | Ilias Tsitsimpis | _write_log_file(self.file_location, section, msg)
|
398 | 4c52d5bf | Ilias Tsitsimpis | |
399 | 4c52d5bf | Ilias Tsitsimpis | # ----------------------------------
|
400 | 4c52d5bf | Ilias Tsitsimpis | # Handle testsuites
|
401 | 4c52d5bf | Ilias Tsitsimpis | def testsuite_start(self, testsuite): |
402 | 4c52d5bf | Ilias Tsitsimpis | """Start a new testsuite
|
403 | 4c52d5bf | Ilias Tsitsimpis |
|
404 | 4c52d5bf | Ilias Tsitsimpis | Add a new section in the logging file
|
405 | 4c52d5bf | Ilias Tsitsimpis |
|
406 | 4c52d5bf | Ilias Tsitsimpis | """
|
407 | 4c52d5bf | Ilias Tsitsimpis | assert testsuite, "Testsuite name can not be emtpy" |
408 | 4c52d5bf | Ilias Tsitsimpis | |
409 | 4c52d5bf | Ilias Tsitsimpis | # Add a new section in the logging file
|
410 | 4c52d5bf | Ilias Tsitsimpis | test_runned = " * " + testsuite + "\n" |
411 | ee89df69 | Ilias Tsitsimpis | self._write_to_file(SECTION_RUNNED, test_runned)
|
412 | 4c52d5bf | Ilias Tsitsimpis | |
413 | 4c52d5bf | Ilias Tsitsimpis | new_section_entry = \ |
414 | 4c52d5bf | Ilias Tsitsimpis | SECTION_SEPARATOR + "\n" + SECTION_PREFIX + testsuite + "\n\n\n\n" |
415 | ee89df69 | Ilias Tsitsimpis | self._write_to_file(SECTION_NEW, new_section_entry)
|
416 | 4c52d5bf | Ilias Tsitsimpis | |
417 | 4c52d5bf | Ilias Tsitsimpis | # Add new section to the stdout
|
418 | 4c52d5bf | Ilias Tsitsimpis | msg = "Starting testsuite %s" % testsuite
|
419 | 12ef696f | Ilias Tsitsimpis | colored_msg = self._color_message(_magenta, msg)
|
420 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stdout(None, colored_msg) |
421 | 4c52d5bf | Ilias Tsitsimpis | |
422 | 4c52d5bf | Ilias Tsitsimpis | def testsuite_success(self, testsuite): |
423 | 4c52d5bf | Ilias Tsitsimpis | """A testsuite has successfully finished
|
424 | 4c52d5bf | Ilias Tsitsimpis |
|
425 | 4c52d5bf | Ilias Tsitsimpis | Update Results
|
426 | 4c52d5bf | Ilias Tsitsimpis |
|
427 | 4c52d5bf | Ilias Tsitsimpis | """
|
428 | 4c52d5bf | Ilias Tsitsimpis | assert testsuite, "Testsuite name can not be emtpy" |
429 | 4c52d5bf | Ilias Tsitsimpis | |
430 | 4c52d5bf | Ilias Tsitsimpis | # Add our testsuite to Results
|
431 | ee89df69 | Ilias Tsitsimpis | self._write_to_file(SECTION_PASSED, testsuite)
|
432 | 4c52d5bf | Ilias Tsitsimpis | |
433 | 4c52d5bf | Ilias Tsitsimpis | # Add success to stdout
|
434 | 4c52d5bf | Ilias Tsitsimpis | msg = "Testsuite %s passed" % testsuite
|
435 | 12ef696f | Ilias Tsitsimpis | colored_msg = self._color_message(_green, msg)
|
436 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stdout(None, colored_msg) |
437 | 4c52d5bf | Ilias Tsitsimpis | |
438 | 4c52d5bf | Ilias Tsitsimpis | def testsuite_failure(self, testsuite): |
439 | 4c52d5bf | Ilias Tsitsimpis | """A testsuite has failed
|
440 | 4c52d5bf | Ilias Tsitsimpis |
|
441 | 4c52d5bf | Ilias Tsitsimpis | Update Results
|
442 | 4c52d5bf | Ilias Tsitsimpis |
|
443 | 4c52d5bf | Ilias Tsitsimpis | """
|
444 | 4c52d5bf | Ilias Tsitsimpis | assert testsuite, "Testsuite name can not be emtpy" |
445 | 4c52d5bf | Ilias Tsitsimpis | |
446 | 4c52d5bf | Ilias Tsitsimpis | # Add our testsuite to Results
|
447 | ee89df69 | Ilias Tsitsimpis | self._write_to_file(SECTION_FAILED, testsuite)
|
448 | 4c52d5bf | Ilias Tsitsimpis | |
449 | 4c52d5bf | Ilias Tsitsimpis | # Add success to stdout
|
450 | 4c52d5bf | Ilias Tsitsimpis | msg = "Testsuite %s failed" % testsuite
|
451 | 12ef696f | Ilias Tsitsimpis | colored_msg = self._color_message(_red, msg)
|
452 | 4c52d5bf | Ilias Tsitsimpis | self._write_to_stdout(None, colored_msg) |
453 | 4c52d5bf | Ilias Tsitsimpis | |
454 | 4c52d5bf | Ilias Tsitsimpis | # ----------------------------------
|
455 | 4c52d5bf | Ilias Tsitsimpis | # Colors
|
456 | 4c52d5bf | Ilias Tsitsimpis | def _color_message(self, color_fun, msg, *args): |
457 | 4c52d5bf | Ilias Tsitsimpis | """Color a message before printing it
|
458 | 4c52d5bf | Ilias Tsitsimpis |
|
459 | 4c52d5bf | Ilias Tsitsimpis | The color_fun parameter is used when we want the whole message to be
|
460 | 4c52d5bf | Ilias Tsitsimpis | colored.
|
461 | 4c52d5bf | Ilias Tsitsimpis |
|
462 | 4c52d5bf | Ilias Tsitsimpis | """
|
463 | 4c52d5bf | Ilias Tsitsimpis | if self.use_colors: |
464 | 4c52d5bf | Ilias Tsitsimpis | if callable(color_fun): |
465 | 6c78720b | Ilias Tsitsimpis | if args:
|
466 | 6c78720b | Ilias Tsitsimpis | return color_fun((msg % args)) + "\n" |
467 | 6c78720b | Ilias Tsitsimpis | else:
|
468 | 6c78720b | Ilias Tsitsimpis | return color_fun(msg) + "\n" |
469 | 4c52d5bf | Ilias Tsitsimpis | else:
|
470 | 3e5bbd85 | Ilias Tsitsimpis | args = tuple([_cyan(arg) for arg in args]) |
471 | 4c52d5bf | Ilias Tsitsimpis | return _format_message(msg, *args)
|
472 | 4c52d5bf | Ilias Tsitsimpis | else:
|
473 | 4c52d5bf | Ilias Tsitsimpis | return _format_message(msg, *args) |