BmnRoot
Loading...
Searching...
No Matches
log_time.py
Go to the documentation of this file.
1import argparse
2import datetime
3import matplotlib.pyplot as plt
4import numpy as np
5import os
6import psycopg2
7import re
8
9import log_time.config as config
10
11from exceptions import NoDataException
12
13
15 def __init__(self, config_dict):
16
17 self.EXTENSIONS = config_dict.get('extensions')
18 self.SUCCESS = int(config_dict.get('success', "1"))
19 self.FAILURE = config_dict.get('failure', "")
20 self.DB_USER = config_dict.get('db_user')
21 self.DB_PASS = config_dict.get('db_pass')
22 self.DB_NAME = config_dict.get('db_name')
23 self.DB_HOST = config_dict.get('db_host')
24
25 self.DPI = config_dict.get('dpi', config.DPI)
26 self.FOLDERS_IGNORE = config.FOLDERS_IGNORE
27 self.FOLDERS_IGNORE.extend(config_dict.get('folders_ignore', config.FOLDERS_IGNORE))
28
29
30 # ### Old implementation ###
31 # def get_event_count(self, run_num):
32 # conn = psycopg2.connect(dbname=self.DB_NAME, user=self.DB_USER,
33 # password=self.DB_PASS, host=self.DB_HOST)
34 # cursor = conn.cursor()
35 # cursor.execute(f'SELECT event_count FROM run_ WHERE run_number = {run_num}')
36 # count = cursor.fetchone()
37 # if count is None:
38 # return None
39 # count = count[0]
40 # cursor.close()
41 # conn.close()
42 # return count
43
44 def get_event_count(self, run_num):
45 """ Returns events_count from DB (or None) and a warning flag (if there where multiple runs with same num) """
46 conn = psycopg2.connect(dbname=self.DB_NAME, user=self.DB_USER,
47 password=self.DB_PASS, host=self.DB_HOST)
48 cursor = conn.cursor()
49 cursor.execute(f"SELECT period_number, event_count FROM run_ WHERE run_number = {run_num}")
50 resp = cursor.fetchall()
51 cursor.close()
52 conn.close()
53 # print(resp)
54 if resp is None or len(resp) == 0:
55 return (None, False)
56 if len(resp) == 1:
57 count = resp[0][1]
58 return (count, False)
59 else:
60 # Look for maximum period number with given run_num
61 count = max(resp, key = lambda tup: tup[0])[1]
62 return (count, True)
63
64
65 def is_file_to_parse(self, root, file):
66 # filepath = os.path.join(root, file)
67 correct_ext = any([file.endswith(ext) for ext in self.EXTENSIONS]) or ("*" in self.EXTENSIONS)
68 correct_folder = all([elem not in os.path.join(root, file) for elem in self.FOLDERS_IGNORE])
69 return correct_ext and correct_folder
70
71
72 def parse_dir(self, _dir, recursive):
73 time_arr = []
74 time_per_events_arr = []
75 unsuccessful_arr = []
76 unsuccessful_arr_files = []
77 successful_arr_files = []
78 if recursive:
79 files_to_walk = os.walk(_dir)
80 else:
81 files_to_walk = [next(os.walk(_dir))]
82
83 files_parsed = 0
84 for root, dirs, files in files_to_walk:
85 for file in files:
86 if self.is_file_to_parseis_file_to_parse(root, file):
87 try:
88 time, is_successful, failure_marker, run_number, log_event_number, file_processing = self.parse_logparse_log(os.path.join(root, file))
89 #print(''.join(filter(None, ('time = ',str(time),'. is_successful=',str(is_successful),'. run_number=',str(run_number),'. log_event_number=',str(log_event_number),'. file_processing=',str(file_processing)))))
90 except PermissionError:
91 print(f"Permission denied - skipping file {os.path.join(root, file)}")
92 continue
93 except Exception as ex:
94 print(f"Error while processing: {ex} - skipping file {os.path.join(root, file)}")
95 continue
96 files_parsed += 1
97 print("+", end="", flush=True)
98
99 if failure_marker:
100 print(f"\n Failure marker was found for file - skipping {os.path.join(root, file)}")
101 time = None
102 is_successful = -1
103 if time is not None:
104 if is_successful >= self.SUCCESS:
105 time_arr.append(time)
106 event_count = None
107 warn_flag = False
108 if run_number is not None:
109 event_count, warn_flag = self.get_event_countget_event_count(run_number)
110 if event_count is not None and event_count == 0:
111 event_count = None
112 if event_count is None and (log_event_number is not None and log_event_number != 0):
113 event_count = log_event_number
114 if event_count is not None:
115 if warn_flag:
116 print(f"Warning: more than one run records: the latest period number is selected for {os.path.join(root, file)}")
117 time_per_events_arr.append(time / event_count)
118 else:
119 print(f"\nCan't get event count from the database for file {os.path.join(root, file)}")
120 else:
121 print(f"\n The log shows that the task was not ended successfully - skipping {os.path.join(root, file)}")
122 elif is_successful >= self.SUCCESS:
123 print(f"\nCan not parse time in successfully ended log file {os.path.join(root, file)}")
124
125 if is_successful < self.SUCCESS:
126 unsuccessful_arr.append(os.path.join(root, file))
127 if file_processing != None:
128 unsuccessful_arr_files.append(file_processing)
129 else:
130 print(f"\nUnsuccessfully processed file name was not defined in {os.path.join(root, file)}.")
131 else:
132 if file_processing != None:
133 successful_arr_files.append(file_processing)
134 else:
135 print(f"\nSuccessfully processed file name was not defined in {os.path.join(root, file)}.")
136
137 if time_arr == []:
138 raise NoDataException
139
140 print(f"\n\nTotal files parsed: {files_parsed}")
141 return np.array(time_arr), np.array(time_per_events_arr), unsuccessful_arr, unsuccessful_arr_files, successful_arr_files, files_parsed
142
143
144 def compute(self, _dir, recursive):
145 arr, arr_per_event, unsuccessful_arr, unsuccessful_arr_files, successful_arr_files, files_parsed = self.parse_dirparse_dir(_dir, recursive)
146 if len(arr) == 0:
147 unit = config.UNITS[0]
148 title = f"Array of time values is empty."
149 else:
150 arr, unit = self.convert_unitsconvert_units(arr)
151 title = f"Time, {unit}. Mean = {np.mean(arr):.3f} {unit}, overall {len(arr)} files."
152
153 if len(arr_per_event) == 0:
154 unit_per_event = config.UNITS[0]
155 title_per_event = f"Array of time values per event is empty."
156 else:
157 arr_per_event, unit_per_event = self.convert_unitsconvert_units(arr_per_event)
158 title_per_event = f"Time per event, {unit_per_event}. Mean = {np.mean(arr_per_event):.3f} {unit_per_event}, " \
159 f"overall {len(arr_per_event)} files."
160
161 print()
162 if len(unsuccessful_arr) == 0:
163 print("All runs ended successfully.\n")
164 else:
165 print("Unsuccessfully ended runs:")
166 for elem in unsuccessful_arr:
167 print(elem)
168 if config.UNSUCCESSFUL_LOG_FILE is not None:
169 print()
170 with open(config.UNSUCCESSFUL_LOG_FILE, "wt") as f:
171 for elem in sorted(unsuccessful_arr_files):
172 f.write(elem + "\n")
173 print(f"Unsuccessfully processed files list ({len(unsuccessful_arr_files)}/{files_parsed}, {(100*len(unsuccessful_arr_files)/files_parsed):.1f}%)"\
174 f" was saved to {config.UNSUCCESSFUL_LOG_FILE}")
175 if config.SUCCESSFUL_LOG_FILE is not None:
176 with open(config.SUCCESSFUL_LOG_FILE, "wt") as f:
177 for elem in sorted(successful_arr_files):
178 f.write(elem + "\n")
179 print(f"Successfully processed files list ({len(successful_arr_files)}/{files_parsed}, {(100*len(successful_arr_files)/files_parsed):.1f}%)"\
180 f" was saved to {config.SUCCESSFUL_LOG_FILE}")
181
182 print()
183 print("Obtained characteristics:")
184 if arr.size == 0:
185 print(" Array of time values is empty.")
186 else:
187 print(f" Mean time = {np.mean(arr):.3f} {unit}.")
188 print(f" Summary time = {np.sum(arr):.3f} {unit}.")
189 if arr_per_event.size == 0:
190 print(" Array of time values per event is empty.")
191 else:
192 print(f" Mean time per event = {np.mean(arr_per_event):.3f} {unit_per_event}.")
193
194 return (arr, unit, title, arr_per_event, unit_per_event, title_per_event)
195
196
197 """
198 Defines units for the given array closest to the mean value
199 and converts the array to the units.
200
201 Parameters
202 ----------
203 arr : numpy.ndarray
204 Array to be converted to the mean units.
205
206 Returns
207 -------
208 arr : numpy.ndarray
209 array converted to the mean units.
210 unit : str
211 Unit of the converted array.
212 """
213 def convert_units(self, arr):
214 if arr.size == 0:
215 return arr, config.UNITS[0]
216 mean = np.mean(arr)
217 u = len(config.UNITS) - 1
218 for i, unit in enumerate(config.UNITS):
219 mean = mean / config.SIZE[i]
220 if mean < config.SIZE[i+1]:
221 u = i
222 break
223 for i in range (u + 1):
224 arr = arr / config.SIZE[i]
225 return arr, config.UNITS[u]
226
227
228 def convert_month(self, month):
229 res = config.MONTH_ARR[month]
230 return res
231
232
233 """
234 Parse date from regex match result and return datetime object.
235
236 Parameters
237 ----------
238 result : regex match object
239 Contains year, month, day, time and time12 groups.
240
241 Returns
242 -------
243 datetime object
244 """
245 def get_date(self, result):
246 start = f'{result.group("year")}-{self.convert_month(result.group("month"))}-{result.group("day")}'
247 time = result.group('time')
248 if result.group('time12'):
249 start = f'{start} {time} {result.group("time12")}'
250 print(start)
251 return datetime.datetime.strptime(start, "%Y-%m-%d %I:%M:%S %p")
252 else:
253 start = f'{start} {time}'
254 return datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
255
256
257 def parse_log(self, log_file):
258 is_successful = 0
259 failure_marker = False
260 start = None
261 end = None
262 run_number = None
263 event_number = None
264 file_processing = None
265 with open(log_file, 'r') as f:
266 for line in f:
267 if config.START in line:
268 result = re.search(config.START_REGEX, line)
269 if result != None:
270 start = self.get_dateget_date(result)
271 else:
272 print(f"Error while parsing start datetime in log file: {log_file}")
273 if config.END in line:
274 result = re.search(config.END_REGEX, line)
275 if result != None:
276 end = self.get_dateget_date(result)
277 else:
278 print(f"Error while parsing end datetime in log file: {log_file}")
279 if config.SUCCESS in line:
280 is_successful += 1
281 if self.FAILURE != "" and self.FAILURE in line:
282 failure_marker = True
283 if config.RUN_EXTENSION in line and run_number == None:
284 result = re.search(config.RUN_REGEX, line)
285 if result != None:
286 run_number = int(result.group(1))
287 if event_number == None:
288 result = re.search(config.EVENT_REGEX, line)
289 if result != None:
290 event_number = int(result.group(1))
291 if file_processing == None:
292 if line.startswith(config.PROCESSING_LINE_START):
293 result = re.search(config.PROCESSING_REGEX, line)
294 if result != None:
295 if len(result.groups()) > 0:
296 file_processing = result.groups()[0]
297 # print("file_processing = ", file_processing)
298 if start == None or end == None:
299 delta = None
300 else:
301 delta = (end - start).total_seconds()
302 # TODO add verbose output option
303 #print(f"Log file {log_file}, delta {delta}, is_successful {is_successful}, run_num {run_num}")
304
305 return delta, is_successful, failure_marker, run_number, event_number, file_processing
friend F32vec4 max(const F32vec4 &a, const F32vec4 &b)
Definition P4_F32vec4.h:31
__init__(self, config_dict)
Definition log_time.py:15
compute(self, _dir, recursive)
Definition log_time.py:144
get_event_count(self, run_num)
Definition log_time.py:44
parse_log(self, log_file)
Definition log_time.py:257
parse_dir(self, _dir, recursive)
Definition log_time.py:72
convert_month(self, month)
Definition log_time.py:228
get_date(self, result)
Definition log_time.py:245
is_file_to_parse(self, root, file)
Definition log_time.py:65