ATLAS Offline Software
Loading...
Searching...
No Matches
python.trfValidation.athenaLogFileReport Class Reference

Logfile suitable for scanning logfiles with an athena flavour, i.e., lines of the form "SERVICE LOGLEVEL MESSAGE". More...

Inheritance diagram for python.trfValidation.athenaLogFileReport:
Collaboration diagram for python.trfValidation.athenaLogFileReport:

Public Member Functions

 __init__ (self, logfile, substepName=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'], ignoreList=None)
 Class constructor.
 python (self)
 Produce a python dictionary summary of the log file report for inclusion in the executor report.
 resetReport (self)
 knowledgeFileHandler (self, knowledgefile)
 Generally, a knowledge file consists of non-standard logging error/abnormal lines which are left out during log scan and could help diagnose job failures.
 scanLogFile (self, resetReport=False)
 dbMonitor (self)
 Return data volume and time spend to retrieve information from the database.
 worstError (self)
 Return the worst error found in the logfile (first error of the most serious type).
 firstError (self, floor='ERROR')
 Return the first error found in the logfile above a certain loglevel.
 eventLoopWarnings (self)
 moreDetails (self, log, firstline, firstLineCount, knowledgeFile, offset=0)
 coreDumpSvcParser (self, log, lineGenerator, firstline, firstLineCount)
 Attempt to suck a core dump report from the current logfile This function scans logs in two different directions: 1) downwards, to exctract information after CoreDumpSvc; and 2) upwards, to find abnormal lines.
 g494ExceptionParser (self, lineGenerator, firstline, firstLineCount)
 g4ExceptionParser (self, lineGenerator, firstline, firstLineCount, g4ExceptionLineDepth)
 pythonExceptionParser (self, log, lineGenerator, firstline, firstLineCount)
 badAllocExceptionParser (self, lineGenerator, firstline, firstLineCount)
 rootSysErrorParser (self, lineGenerator, firstline, firstLineCount)
 __str__ (self)

Protected Attributes

 _ignoreList = ignoreList
 _regExp = re.compile(r'(?P<service>[^\s]+\w)(.*)\s+(?P<level>' + '|'.join(stdLogLevels) + r')\s+(?P<message>.*)')
 _metaPat = re.compile(r"MetaData:\s+(.*?)\s*=\s*(.*)$")
dict _metaData = {}
list _eventLoopWarnings = []
 _substepName = substepName
dict _levelCounter = {}
dict _errorDetails = {}
int _dbbytes = 0
float _dbtime = 0.0
list _logfile = [logfile, ]
 _msgLimit = msgLimit
 _msgDetails = msgDetailLevel
 _re = None

Detailed Description

Logfile suitable for scanning logfiles with an athena flavour, i.e., lines of the form "SERVICE LOGLEVEL MESSAGE".

Definition at line 141 of file trfValidation.py.

Constructor & Destructor Documentation

◆ __init__()

python.trfValidation.athenaLogFileReport.__init__ ( self,
logfile,
substepName = None,
msgLimit = 10,
msgDetailLevel = stdLogLevels['ERROR'],
ignoreList = None )

Class constructor.

Parameters
logfileLogfile (or list of logfiles) to scan
substepNameName of the substep executor, that has requested this log scan
msgLimitThe number of messages in each category on which a

Definition at line 146 of file trfValidation.py.

146 def __init__(self, logfile, substepName=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'], ignoreList=None):
147 if ignoreList:
148 self._ignoreList = ignoreList
149 else:
150 self._ignoreList = ignorePatterns()
151
152
157 self._regExp = re.compile(r'(?P<service>[^\s]+\w)(.*)\s+(?P<level>' + '|'.join(stdLogLevels) + r')\s+(?P<message>.*)')
158
159 self._metaPat = re.compile(r"MetaData:\s+(.*?)\s*=\s*(.*)$")
160 self._metaData = {}
161 self._eventLoopWarnings = []
162 self._substepName = substepName
163 self._msgLimit = msgLimit
164
165 self.resetReport()
166
167 super(athenaLogFileReport, self).__init__(logfile, msgLimit, msgDetailLevel)
168

Member Function Documentation

◆ __str__()

python.trfValidation.athenaLogFileReport.__str__ ( self)

Definition at line 635 of file trfValidation.py.

635 def __str__(self):
636 return str(self._levelCounter) + str(self._errorDetails)
637
638

◆ badAllocExceptionParser()

python.trfValidation.athenaLogFileReport.badAllocExceptionParser ( self,
lineGenerator,
firstline,
firstLineCount )

Definition at line 623 of file trfValidation.py.

623 def badAllocExceptionParser(self, lineGenerator, firstline, firstLineCount):
624 badAllocExceptionReport = 'terminate after \'std::bad_alloc\'.'
625
626 msg.debug('Identified bad_alloc - adding to error detail report')
627 self._levelCounter['CATASTROPHE'] += 1
628 self._errorDetails['CATASTROPHE'].append({'message': badAllocExceptionReport, 'firstLine': firstLineCount, 'count': 1})
629

◆ coreDumpSvcParser()

python.trfValidation.athenaLogFileReport.coreDumpSvcParser ( self,
log,
lineGenerator,
firstline,
firstLineCount )

Attempt to suck a core dump report from the current logfile This function scans logs in two different directions: 1) downwards, to exctract information after CoreDumpSvc; and 2) upwards, to find abnormal lines.

Note
: Current downwards scan just eats lines until a 'normal' line is seen. There is a slight problem here in that the end of core dump trigger line will not get parsed TODO: fix this (OTOH core dump is usually the very last thing and fatal!)

Definition at line 469 of file trfValidation.py.

469 def coreDumpSvcParser(self, log, lineGenerator, firstline, firstLineCount):
470 _eventCounter = _run = _event = _currentAlgorithm = _functionLine = _currentFunction = None
471 coreDumpReport = 'Core dump from CoreDumpSvc'
472 # Number of lines to ignore above 'core dump' when looking for abnormal lines
473 offset = 1
474 coreDumpDetailsReport = {}
475
476 for line, linecounter in lineGenerator:
477 m = self._regExp.match(line)
478 if m is None:
479 if 'Caught signal 11(Segmentation fault)' in line:
480 coreDumpReport = 'Segmentation fault'
481 if 'Event counter' in line:
482 _eventCounter = line
483
484 #Lookup: 'EventID: [Run,Evt,Lumi,Time,BunchCross,DetMask] = [267599,7146597,1,1434123751:0,0,0x0,0x0,0x0]'
485 if 'EventID' in line:
486 match = re.findall(r'\‍[.*?\‍]', line)
487 if match and match.__len__() >= 2: # Assuming the line contains at-least one key-value pair.
488 brackets = "[]"
489 commaDelimer = ','
490 keys = (match[0].strip(brackets)).split(commaDelimer)
491 values = (match[1].strip(brackets)).split(commaDelimer)
492
493 if 'Run' in keys:
494 _run = 'Run: ' + values[keys.index('Run')]
495
496 if 'Evt' in keys:
497 _event = 'Evt: ' + values[keys.index('Evt')]
498
499 if 'Current algorithm' in line:
500 _currentAlgorithm = line
501 if '<signal handler called>' in line:
502 _functionLine = linecounter+1
503 if _functionLine and linecounter is _functionLine:
504 if ' in ' in line:
505 _currentFunction = 'Current Function: ' + line.split(' in ')[1].split()[0]
506 else:
507 _currentFunction = 'Current Function: ' + line.split()[1]
508 else:
509 # Can this be done - we want to push the line back into the generator to be
510 # reparsed in the normal way (might need to make the generator a class with the
511 # __exec__ method supported (to get the line), so that we can then add a
512 # pushback onto an internal FIFO stack
513 # lineGenerator.pushback(line)
514 break
515 _eventCounter = 'Event counter: unknown' if not _eventCounter else _eventCounter
516 _run = 'Run: unknown' if not _run else _run
517 _event = 'Evt: unknown' if not _event else _event
518 _currentAlgorithm = 'Current algorithm: unknown' if not _currentAlgorithm else _currentAlgorithm
519 _currentFunction = 'Current Function: unknown' if not _currentFunction else _currentFunction
520 coreDumpReport = '{0}: {1}; {2}; {3}; {4}; {5}'.format(coreDumpReport, _eventCounter, _run, _event, _currentAlgorithm, _currentFunction)
521
522 coreDumpDetailsReport = self.moreDetails(log, firstline, firstLineCount, 'knowledgeFile.db', offset)
523 abnormalLines = coreDumpDetailsReport['abnormalLines']
524
525 # concatenate an extract of first seen abnormal line to the core dump message
526 if 'message0' in abnormalLines.keys():
527 coreDumpReport += '; Abnormal line seen just before core dump: ' + abnormalLines['message0'][0:30] + '...[truncated] ' + '(see the jobReport)'
528
529 # Core dumps are always fatal...
530 msg.debug('Identified core dump - adding to error detail report')
531 self._levelCounter['FATAL'] += 1
532 self._errorDetails['FATAL'].append({'moreDetails': coreDumpDetailsReport, 'message': coreDumpReport, 'firstLine': firstLineCount, 'count': 1})
533
534
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:359

◆ dbMonitor()

python.trfValidation.athenaLogFileReport.dbMonitor ( self)

Return data volume and time spend to retrieve information from the database.

Definition at line 375 of file trfValidation.py.

375 def dbMonitor(self):
376 return {'bytes' : self._dbbytes, 'time' : self._dbtime} if self._dbbytes > 0 or self._dbtime > 0 else None
377

◆ eventLoopWarnings()

python.trfValidation.athenaLogFileReport.eventLoopWarnings ( self)

Definition at line 408 of file trfValidation.py.

408 def eventLoopWarnings(self):
409 eventLoopWarnings = []
410 for item in self._eventLoopWarnings:
411 if item in [element['item'] for element in eventLoopWarnings]:
412 continue
413 count = self._eventLoopWarnings.count(item)
414 eventLoopWarnings.append({'item':item, 'count': count})
415 return eventLoopWarnings
416
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148

◆ firstError()

python.trfValidation.athenaLogFileReport.firstError ( self,
floor = 'ERROR' )

Return the first error found in the logfile above a certain loglevel.

Reimplemented from python.trfValidation.logFileReport.

Definition at line 394 of file trfValidation.py.

394 def firstError(self, floor='ERROR'):
395 firstLine = firstError = None
396 firstLevel = stdLogLevels[floor]
397 firstName = floor
398 for lvl, count in self._levelCounter.items():
399 if (count > 0 and stdLogLevels.get(lvl, 0) >= stdLogLevels[floor] and
400 (firstError is None or self._errorDetails[lvl][0]['firstLine'] < firstLine)):
401 firstLine = self._errorDetails[lvl][0]['firstLine']
402 firstLevel = stdLogLevels[lvl]
403 firstName = lvl
404 firstError = self._errorDetails[lvl][0]
405
406 return {'level': firstName, 'nLevel': firstLevel, 'firstError': firstError}
407

◆ g494ExceptionParser()

python.trfValidation.athenaLogFileReport.g494ExceptionParser ( self,
lineGenerator,
firstline,
firstLineCount )

Definition at line 535 of file trfValidation.py.

535 def g494ExceptionParser(self, lineGenerator, firstline, firstLineCount):
536 g4Report = firstline
537 g4lines = 1
538 if 'Aborting execution' not in g4Report:
539 for line, linecounter in lineGenerator:
540 g4Report += os.linesep + line
541 g4lines += 1
542 # Test for the closing string
543 if '*** ' in line:
544 break
545 if g4lines >= 25:
546 msg.warning('G4 exception closing string not found within {0} log lines of line {1}'.format(g4lines, firstLineCount))
547 break
548
549 # G4 exceptions can be fatal or they can be warnings...
550 msg.debug('Identified G4 exception - adding to error detail report')
551 if "just a warning" in g4Report:
552 if self._levelCounter['WARNING'] <= self._msgLimit:
553 self._levelCounter['WARNING'] += 1
554 self._errorDetails['WARNING'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
555 elif self._levelCounter['WARNING'] == self._msgLimit + 1:
556 msg.warning("Found message number {0} at level WARNING - this and further messages will be supressed from the report".format(self._levelCounter['WARNING']))
557 else:
558 self._levelCounter['FATAL'] += 1
559 self._errorDetails['FATAL'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
560

◆ g4ExceptionParser()

python.trfValidation.athenaLogFileReport.g4ExceptionParser ( self,
lineGenerator,
firstline,
firstLineCount,
g4ExceptionLineDepth )

Definition at line 561 of file trfValidation.py.

561 def g4ExceptionParser(self, lineGenerator, firstline, firstLineCount, g4ExceptionLineDepth):
562 g4Report = firstline
563 g4lines = 1
564 for line, linecounter in lineGenerator:
565 g4Report += os.linesep + line
566 g4lines += 1
567 # Test for the closing string
568 if 'G4Exception-END' in line:
569 break
570 if g4lines >= g4ExceptionLineDepth:
571 msg.warning('G4 exception closing string not found within {0} log lines of line {1}'.format(g4lines, firstLineCount))
572 break
573
574 # G4 exceptions can be fatal or they can be warnings...
575 msg.debug('Identified G4 exception - adding to error detail report')
576 if "-------- WWWW -------" in g4Report:
577 if self._levelCounter['WARNING'] <= self._msgLimit:
578 self._levelCounter['WARNING'] += 1
579 self._errorDetails['WARNING'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
580 elif self._levelCounter['WARNING'] == self._msgLimit + 1:
581 msg.warning("Found message number {0} at level WARNING - this and further messages will be supressed from the report".format(self._levelCounter['WARNING']))
582 else:
583 self._levelCounter['FATAL'] += 1
584 self._errorDetails['FATAL'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
585
586

◆ knowledgeFileHandler()

python.trfValidation.athenaLogFileReport.knowledgeFileHandler ( self,
knowledgefile )

Generally, a knowledge file consists of non-standard logging error/abnormal lines which are left out during log scan and could help diagnose job failures.

Definition at line 198 of file trfValidation.py.

198 def knowledgeFileHandler(self, knowledgefile):
199 # load abnormal/error line(s) from the knowledge file(s)
200 linesList = []
201 fullName = trfUtils.findFile(os.environ['DATAPATH'], knowledgefile)
202 if not fullName:
203 msg.warning('Knowledge file {0} could not be found in DATAPATH'.format(knowledgefile))
204 else:
205 try:
206 with open(fullName) as knowledgeFileHandle:
207 msg.debug('Opened knowledge file {0} from here: {1}'.format(knowledgefile, fullName))
208
209 for line in knowledgeFileHandle:
210 if line.startswith('#') or line == '' or line =='\n':
211 continue
212 line = line.rstrip('\n')
213 linesList.append(line)
214 except OSError as e:
215 msg.warning('Failed to open knowledge file {0}: {1}'.format(fullName, e))
216 return linesList
217

◆ moreDetails()

python.trfValidation.athenaLogFileReport.moreDetails ( self,
log,
firstline,
firstLineCount,
knowledgeFile,
offset = 0 )

Definition at line 417 of file trfValidation.py.

417 def moreDetails(self, log, firstline, firstLineCount, knowledgeFile, offset=0):
418 # Look for "abnormal" and "last normal" line(s)
419 # Make a list of last e.g. 50 lines before core dump
420 abnormalLinesList = self.knowledgeFileHandler(knowledgeFile)
421 linesToBeScanned = 50
422 seenAbnormalLines = []
423 abnormalLinesReport = {}
424 lastNormalLineReport = {}
425
426 linesList = []
427 myGen = trfUtils.lineByLine(log)
428 for line, linecounter in myGen:
429 if linecounter in range(firstLineCount - linesToBeScanned, firstLineCount-offset):
430 linesList.append([linecounter, line])
431 elif linecounter == firstLineCount:
432 break
433
434 for linecounter, line in reversed(linesList):
435 if re.findall(r'|'.join(abnormalLinesList), line):
436 seenLine = False
437 for dic in seenAbnormalLines:
438 # count repetitions or similar (e.g. first 15 char) abnormal lines
439 if dic['message'] == line or dic['message'][0:15] == line[0:15]:
440 dic['count'] += 1
441 seenLine = True
442 break
443 if seenLine is False:
444 seenAbnormalLines.append({'message': line, 'firstLine': linecounter, 'count': 1})
445 else:
446 if line != '':
447 lastNormalLineReport = {'message': line, 'firstLine': linecounter, 'count': 1}
448 break
449 else:
450 continue
451
452 # Write the list of abnormal lines into the abnormalLinesReport dictionary
453 # The keys of each abnormal line have a number suffix starting with 0
454 # e.g., first abnormal line's keys are :{'mesage0', 'firstLine0', 'count0'}
455
456 for a in range(len(seenAbnormalLines)):
457 abnormalLinesReport.update({'message{0}'.format(a): seenAbnormalLines[a]['message'], 'firstLine{0}'.format(a): seenAbnormalLines[a]['firstLine'],
458 'count{0}'.format(a): seenAbnormalLines[a]['count']})
459
460 return {'abnormalLines': abnormalLinesReport, 'lastNormalLine': lastNormalLineReport}
461
462

◆ python()

python.trfValidation.athenaLogFileReport.python ( self)

Produce a python dictionary summary of the log file report for inclusion in the executor report.

Definition at line 172 of file trfValidation.py.

172 def python(self):
173 errorDict = {'countSummary': {}, 'details': {}}
174 for level, count in self._levelCounter.items():
175 errorDict['countSummary'][level] = count
176 if self._levelCounter[level] > 0 and len(self._errorDetails[level]) > 0:
177 errorDict['details'][level] = []
178 for error in self._errorDetails[level]:
179 errorDict['details'][level].append(error)
180 return errorDict
181

◆ pythonExceptionParser()

python.trfValidation.athenaLogFileReport.pythonExceptionParser ( self,
log,
lineGenerator,
firstline,
firstLineCount )

Definition at line 587 of file trfValidation.py.

587 def pythonExceptionParser(self, log, lineGenerator, firstline, firstLineCount):
588 pythonExceptionReport = ""
589 lastLine = firstline
590 lastLine2 = firstline
591 pythonErrorLine = firstLineCount
592 pyLines = 1
593 for line, linecounter in lineGenerator:
594 if 'Py:Athena' in line and 'INFO leaving with code' in line:
595 if len(lastLine)> 0:
596 pythonExceptionReport = lastLine
597 pythonErrorLine = linecounter-1
598 else: # Sometimes there is a blank line after the exception
599 pythonExceptionReport = lastLine2
600 pythonErrorLine = linecounter-2
601 break
602 if pyLines >= 25:
603 msg.warning('Could not identify python exception correctly scanning {0} log lines after line {1}'.format(pyLines, firstLineCount))
604 pythonExceptionReport = "Unable to identify specific exception"
605 pythonErrorLine = firstLineCount
606 break
607 lastLine2 = lastLine
608 lastLine = line
609 pyLines += 1
610
611 pythonExceptionDetailsReport = self.moreDetails(log, firstline, firstLineCount, 'knowledgeFile.db')
612 abnormalLines = pythonExceptionDetailsReport['abnormalLines']
613
614 # concatenate an extract of first seen abnormal line to pythonExceptionReport
615 if 'message0' in abnormalLines.keys():
616 pythonExceptionReport += '; Abnormal line seen just before python exception: ' + abnormalLines['message0'][0:30] + '...[truncated] ' + '(see the jobReport)'
617
618 msg.debug('Identified python exception - adding to error detail report')
619 self._levelCounter['FATAL'] += 1
620 self._errorDetails['FATAL'].append({'moreDetails': pythonExceptionDetailsReport, 'message': pythonExceptionReport, 'firstLine': pythonErrorLine, 'count': 1})
621
622

◆ resetReport()

python.trfValidation.athenaLogFileReport.resetReport ( self)

Reimplemented from python.trfValidation.logFileReport.

Definition at line 182 of file trfValidation.py.

182 def resetReport(self):
183 self._levelCounter = {}
184 for level in list(stdLogLevels) + ['UNKNOWN', 'IGNORED']:
185 self._levelCounter[level] = 0
186
187 self._errorDetails = {}
188 self._eventLoopWarnings = []
189 for level in self._levelCounter:
190 self._errorDetails[level] = []
191 # Format:
192 # List of dicts {'message': errMsg, 'firstLine': lineNo, 'count': N}
193 self._dbbytes = 0
194 self._dbtime = 0.0
195

◆ rootSysErrorParser()

python.trfValidation.athenaLogFileReport.rootSysErrorParser ( self,
lineGenerator,
firstline,
firstLineCount )

Definition at line 630 of file trfValidation.py.

630 def rootSysErrorParser(self, lineGenerator, firstline, firstLineCount):
631 msg.debug('Identified ROOT IO problem - adding to error detail report')
632 self._levelCounter['FATAL'] += 1
633 self._errorDetails['FATAL'].append({'message': firstline, 'firstLine': firstLineCount, 'count': 1})
634

◆ scanLogFile()

python.trfValidation.athenaLogFileReport.scanLogFile ( self,
resetReport = False )

Reimplemented from python.trfValidation.logFileReport.

Definition at line 218 of file trfValidation.py.

218 def scanLogFile(self, resetReport=False):
219
220 nonStandardErrorsList = self.knowledgeFileHandler('nonStandardErrors.db')
221
222 if resetReport:
223 self.resetReport()
224
225 for log in self._logfile:
226 msg.debug('Now scanning logfile {0}'.format(log))
227 seenNonStandardError = ''
228 customLogParser = None
229 if log == 'log.generate':
230 from EvgenProdTools.EvgenParserTool import evgenParserTool
231 customLogParser = evgenParserTool()
232 # N.B. Use the generator so that lines can be grabbed by subroutines, e.g., core dump svc reporter
233 try:
234 myGen = trfUtils.lineByLine(log, substepName=self._substepName)
235 except IOError as e:
236 msg.error('Failed to open transform logfile {0}: {1:s}'.format(log, e))
237 # Return this as a small report
238 self._levelCounter['ERROR'] = 1
239 self._errorDetails['ERROR'] = {'message': str(e), 'firstLine': 0, 'count': 1}
240 return
241 # Detect whether we are in the event loop part of the log file
242 inEventLoop = False
243 for line, lineCounter in myGen:
244 if '===>>> start processing event' in line: inEventLoop = True
245 if 'Application Manager Stopped successfully' in line: inEventLoop = False
246
247 # In case we have enabled a custom log parser, run the line through it first
248 if customLogParser is not None:
249 customLogParser.processLine(line)
250 # Search for metadata strings
251 m = self._metaPat.search(line)
252 if m is not None:
253 key, value = m.groups()
254 self._metaData[key] = value
255
256 m = self._regExp.match(line)
257 if m is None:
258 # We didn't manage to get a recognised standard line from the file
259 # But we can check for certain other interesting things, like core dumps
260 if 'Core dump from CoreDumpSvc' in line:
261 msg.warning('Detected CoreDumpSvc report - activating core dump svc grabber')
262 self.coreDumpSvcParser(log, myGen, line, lineCounter)
263 continue
264 # Add the G4 exceptipon parsers
265 if 'G4Exception-START' in line:
266 msg.warning('Detected G4 exception report - activating G4 exception grabber')
267 self.g4ExceptionParser(myGen, line, lineCounter, 40)
268 continue
269 if '*** G4Exception' in line:
270 msg.warning('Detected G4 9.4 exception report - activating G4 exception grabber')
271 self.g494ExceptionParser(myGen, line, lineCounter)
272 continue
273 # Add the python exception parser
274 if 'Shortened traceback (most recent user call last)' in line:
275 msg.warning('Detected python exception - activating python exception grabber')
276 self.pythonExceptionParser(log, myGen, line, lineCounter)
277 continue
278 # Add parser for missed bad_alloc
279 if 'terminate called after throwing an instance of \'std::bad_alloc\'' in line:
280 msg.warning('Detected bad_alloc!')
281 self.badAllocExceptionParser(myGen, line, lineCounter)
282 continue
283 # Parser for ROOT reporting a stale file handle (see ATLASG-448)
284 # Amendment: Generalize the search (see ATLASRECTS-7121)
285 if 'Error in <TFile::ReadBuffer>' in line:
286 self.rootSysErrorParser(myGen, line, lineCounter)
287 continue
288
289 if 'Error in <TFile::WriteBuffer>' in line:
290 self.rootSysErrorParser(myGen, line, lineCounter)
291 continue
292 # Check if the line is among the non-standard logging errors from the knowledge file
293 if any(line in l for l in nonStandardErrorsList):
294 seenNonStandardError = line
295 continue
296
297 msg.debug('Non-standard line in %s: %s', log, line)
298 self._levelCounter['UNKNOWN'] += 1
299 continue
300
301 # Line was matched successfully
302 fields = {}
303 for matchKey in ('service', 'level', 'message'):
304 fields[matchKey] = m.group(matchKey)
305 msg.debug('Line parsed as: {0}'.format(fields))
306
307 # If this is a WARNING and we passed the start of the event loop,
308 # add it to special list
309 if (fields['level'] == 'WARNING') and inEventLoop:
310 self._eventLoopWarnings.append(fields)
311
312 # Check this is not in our ignore list
313 ignoreFlag = False
314 for ignorePat in self._ignoreList.structuredPatterns:
315 serviceMatch = ignorePat['service'].match(fields['service'])
316 levelMatch = (ignorePat['level'] == "" or ignorePat['level'] == fields['level'])
317 messageMatch = ignorePat['message'].match(fields['message'])
318 if serviceMatch and levelMatch and messageMatch:
319 msg.info('Error message "{0}" was ignored at line {1} (structured match)'.format(line, lineCounter))
320 ignoreFlag = True
321 break
322 if ignoreFlag is False:
323 for searchPat in self._ignoreList.searchPatterns:
324 if searchPat.search(line):
325 msg.info('Error message "{0}" was ignored at line {1} (search match)'.format(line, lineCounter))
326 ignoreFlag = True
327 break
328 if ignoreFlag:
329 # Got an ignore - message this to a special IGNORED error
330 fields['level'] = 'IGNORED'
331 else:
332 # Some special handling for specific errors (maybe generalise this if
333 # there end up being too many special cases)
334 # Upgrade bad_alloc to CATASTROPHE to allow for better automated handling of
335 # jobs that run out of memory
336 if 'std::bad_alloc' in fields['message']:
337 fields['level'] = 'CATASTROPHE'
338
339 # concatenate the seen non-standard logging error to the FATAL
340 if fields['level'] == 'FATAL':
341 if seenNonStandardError:
342 line += '; ' + seenNonStandardError
343
344 # Count this error
345 self._levelCounter[fields['level']] += 1
346
347 # Record some error details
348 # N.B. We record 'IGNORED' errors as these really should be flagged for fixing
349 if fields['level'] == 'IGNORED' or stdLogLevels[fields['level']] >= self._msgDetails:
350 if self._levelCounter[fields['level']] <= self._msgLimit:
351 detailsHandled = False
352 for seenError in self._errorDetails[fields['level']]:
353 if seenError['message'] == line:
354 seenError['count'] += 1
355 detailsHandled = True
356 break
357 if detailsHandled is False:
358 self._errorDetails[fields['level']].append({'message': line, 'firstLine': lineCounter, 'count': 1})
359 elif self._levelCounter[fields['level']] == self._msgLimit + 1:
360 msg.warning("Found message number {0} at level {1} - this and further messages will be supressed from the report".format(self._levelCounter[fields['level']], fields['level']))
361 else:
362 # Overcounted
363 pass
364 if 'Total payload read from IOVDb' in fields['message']:
365 msg.debug("Found COOL payload information at line {0}".format(line))
366 a = re.match(r'(\D+)(?P<bytes>\d+)(\D+)(?P<time>\d+[.]?\d*)(\D+)', fields['message'])
367 self._dbbytes += int(a.group('bytes'))
368 self._dbtime += float(a.group('time'))
369 # Finally, if we have a custom log parser, use it to update the metadata dictionary
370 if customLogParser is not None:
371 customLogParser.report()
372 self._metaData = customLogParser.updateMetadata( self._metaData )
373
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition hcg.cxx:743

◆ worstError()

python.trfValidation.athenaLogFileReport.worstError ( self)

Return the worst error found in the logfile (first error of the most serious type).

Reimplemented from python.trfValidation.logFileReport.

Definition at line 379 of file trfValidation.py.

379 def worstError(self):
380 worst = stdLogLevels['DEBUG']
381 worstName = 'DEBUG'
382 for lvl, count in self._levelCounter.items():
383 if count > 0 and stdLogLevels.get(lvl, 0) > worst:
384 worstName = lvl
385 worst = stdLogLevels[lvl]
386 if len(self._errorDetails[worstName]) > 0:
387 firstError = self._errorDetails[worstName][0]
388 else:
389 firstError = None
390
391 return {'level': worstName, 'nLevel': worst, 'firstError': firstError}
392

Member Data Documentation

◆ _dbbytes

python.trfValidation.athenaLogFileReport._dbbytes = 0
protected

Definition at line 193 of file trfValidation.py.

◆ _dbtime

float python.trfValidation.athenaLogFileReport._dbtime = 0.0
protected

Definition at line 194 of file trfValidation.py.

◆ _errorDetails

python.trfValidation.athenaLogFileReport._errorDetails = {}
protected

Definition at line 187 of file trfValidation.py.

◆ _eventLoopWarnings

list python.trfValidation.athenaLogFileReport._eventLoopWarnings = []
protected

Definition at line 161 of file trfValidation.py.

◆ _ignoreList

python.trfValidation.athenaLogFileReport._ignoreList = ignoreList
protected

Definition at line 148 of file trfValidation.py.

◆ _levelCounter

python.trfValidation.athenaLogFileReport._levelCounter = {}
protected

Definition at line 183 of file trfValidation.py.

◆ _logfile

list python.trfValidation.logFileReport._logfile = [logfile, ]
protectedinherited

Definition at line 111 of file trfValidation.py.

◆ _metaData

dict python.trfValidation.athenaLogFileReport._metaData = {}
protected

Definition at line 160 of file trfValidation.py.

◆ _metaPat

python.trfValidation.athenaLogFileReport._metaPat = re.compile(r"MetaData:\s+(.*?)\s*=\s*(.*)$")
protected

Definition at line 159 of file trfValidation.py.

◆ _msgDetails

python.trfValidation.logFileReport._msgDetails = msgDetailLevel
protectedinherited

Definition at line 116 of file trfValidation.py.

◆ _msgLimit

python.trfValidation.logFileReport._msgLimit = msgLimit
protectedinherited

Definition at line 115 of file trfValidation.py.

◆ _re

python.trfValidation.logFileReport._re = None
protectedinherited

Definition at line 117 of file trfValidation.py.

◆ _regExp

python.trfValidation.athenaLogFileReport._regExp = re.compile(r'(?P<service>[^\s]+\w)(.*)\s+(?P<level>' + '|'.join(stdLogLevels) + r')\s+(?P<message>.*)')
protected
Note
This is the regular expression match for athena logfile lines Match first strips off any HH:MM:SS prefix the transform has added, then takes the next group of non-whitespace characters as the service, then then matches from the list of known levels, then finally, ignores any last pieces of whitespace prefix and takes the rest of the line as the message

Definition at line 157 of file trfValidation.py.

◆ _substepName

python.trfValidation.athenaLogFileReport._substepName = substepName
protected

Definition at line 162 of file trfValidation.py.


The documentation for this class was generated from the following file: