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 Types

typedef HLT::TypeInformation::for_each_type_c< typenameEDMLIST::map, my_functor, my_result<>, my_arg< HLT::TypeInformation::get_cont, CONTAINER > >::type result

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 211 of file trfValidation.py.

Member Typedef Documentation

◆ result

Definition at line 90 of file EDM_MasterSearch.h.

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 216 of file trfValidation.py.

216 def __init__(self, logfile, substepName=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'], ignoreList=None):
217 if ignoreList:
218 self._ignoreList = ignoreList
219 else:
220 self._ignoreList = ignorePatterns()
221
222
227 self._regExp = re.compile(r'(?P<service>[^\s]+\w)(.*)\s+(?P<level>' + '|'.join(stdLogLevels) + r')\s+(?P<message>.*)')
228
229 self._metaPat = re.compile(r"MetaData:\s+(.*?)\s*=\s*(.*)$")
230 self._metaData = {}
231 self._eventLoopWarnings = []
232 self._substepName = substepName
233 self._msgLimit = msgLimit
234
235 self.resetReport()
236
237 super(athenaLogFileReport, self).__init__(logfile, msgLimit, msgDetailLevel)
238

Member Function Documentation

◆ __str__()

python.trfValidation.athenaLogFileReport.__str__ ( self)

Definition at line 705 of file trfValidation.py.

705 def __str__(self):
706 return str(self._levelCounter) + str(self._errorDetails)
707
708

◆ badAllocExceptionParser()

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

Definition at line 693 of file trfValidation.py.

693 def badAllocExceptionParser(self, lineGenerator, firstline, firstLineCount):
694 badAllocExceptionReport = 'terminate after \'std::bad_alloc\'.'
695
696 msg.debug('Identified bad_alloc - adding to error detail report')
697 self._levelCounter['CATASTROPHE'] += 1
698 self._errorDetails['CATASTROPHE'].append({'message': badAllocExceptionReport, 'firstLine': firstLineCount, 'count': 1})
699

◆ 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 539 of file trfValidation.py.

539 def coreDumpSvcParser(self, log, lineGenerator, firstline, firstLineCount):
540 _eventCounter = _run = _event = _currentAlgorithm = _functionLine = _currentFunction = None
541 coreDumpReport = 'Core dump from CoreDumpSvc'
542 # Number of lines to ignore above 'core dump' when looking for abnormal lines
543 offset = 1
544 coreDumpDetailsReport = {}
545
546 for line, linecounter in lineGenerator:
547 m = self._regExp.match(line)
548 if m is None:
549 if 'Caught signal 11(Segmentation fault)' in line:
550 coreDumpReport = 'Segmentation fault'
551 if 'Event counter' in line:
552 _eventCounter = line
553
554 #Lookup: 'EventID: [Run,Evt,Lumi,Time,BunchCross,DetMask] = [267599,7146597,1,1434123751:0,0,0x0,0x0,0x0]'
555 if 'EventID' in line:
556 match = re.findall(r'\[.*?\]', line)
557 if match and match.__len__() >= 2: # Assuming the line contains at-least one key-value pair.
558 brackets = "[]"
559 commaDelimer = ','
560 keys = (match[0].strip(brackets)).split(commaDelimer)
561 values = (match[1].strip(brackets)).split(commaDelimer)
562
563 if 'Run' in keys:
564 _run = 'Run: ' + values[keys.index('Run')]
565
566 if 'Evt' in keys:
567 _event = 'Evt: ' + values[keys.index('Evt')]
568
569 if 'Current algorithm' in line:
570 _currentAlgorithm = line
571 if '<signal handler called>' in line:
572 _functionLine = linecounter+1
573 if _functionLine and linecounter is _functionLine:
574 if ' in ' in line:
575 _currentFunction = 'Current Function: ' + line.split(' in ')[1].split()[0]
576 else:
577 _currentFunction = 'Current Function: ' + line.split()[1]
578 else:
579 # Can this be done - we want to push the line back into the generator to be
580 # reparsed in the normal way (might need to make the generator a class with the
581 # __exec__ method supported (to get the line), so that we can then add a
582 # pushback onto an internal FIFO stack
583 # lineGenerator.pushback(line)
584 break
585 _eventCounter = 'Event counter: unknown' if not _eventCounter else _eventCounter
586 _run = 'Run: unknown' if not _run else _run
587 _event = 'Evt: unknown' if not _event else _event
588 _currentAlgorithm = 'Current algorithm: unknown' if not _currentAlgorithm else _currentAlgorithm
589 _currentFunction = 'Current Function: unknown' if not _currentFunction else _currentFunction
590 coreDumpReport = '{0}: {1}; {2}; {3}; {4}; {5}'.format(coreDumpReport, _eventCounter, _run, _event, _currentAlgorithm, _currentFunction)
591
592 coreDumpDetailsReport = self.moreDetails(log, firstline, firstLineCount, 'knowledgeFile.db', offset)
593 abnormalLines = coreDumpDetailsReport['abnormalLines']
594
595 # concatenate an extract of first seen abnormal line to the core dump message
596 if 'message0' in abnormalLines.keys():
597 coreDumpReport += '; Abnormal line seen just before core dump: ' + abnormalLines['message0'][0:30] + '...[truncated] ' + '(see the jobReport)'
598
599 # Core dumps are always fatal...
600 msg.debug('Identified core dump - adding to error detail report')
601 self._levelCounter['FATAL'] += 1
602 self._errorDetails['FATAL'].append({'moreDetails': coreDumpDetailsReport, 'message': coreDumpReport, 'firstLine': firstLineCount, 'count': 1})
603
604
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:357

◆ dbMonitor()

python.trfValidation.athenaLogFileReport.dbMonitor ( self)

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

Definition at line 445 of file trfValidation.py.

445 def dbMonitor(self):
446 return {'bytes' : self._dbbytes, 'time' : self._dbtime} if self._dbbytes > 0 or self._dbtime > 0 else None
447

◆ eventLoopWarnings()

python.trfValidation.athenaLogFileReport.eventLoopWarnings ( self)

Definition at line 478 of file trfValidation.py.

478 def eventLoopWarnings(self):
479 eventLoopWarnings = []
480 for item in self._eventLoopWarnings:
481 if item in [element['item'] for element in eventLoopWarnings]:
482 continue
483 count = self._eventLoopWarnings.count(item)
484 eventLoopWarnings.append({'item':item, 'count': count})
485 return eventLoopWarnings
486
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146

◆ 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 464 of file trfValidation.py.

464 def firstError(self, floor='ERROR'):
465 firstLine = firstError = None
466 firstLevel = stdLogLevels[floor]
467 firstName = floor
468 for lvl, count in self._levelCounter.items():
469 if (count > 0 and stdLogLevels.get(lvl, 0) >= stdLogLevels[floor] and
470 (firstError is None or self._errorDetails[lvl][0]['firstLine'] < firstLine)):
471 firstLine = self._errorDetails[lvl][0]['firstLine']
472 firstLevel = stdLogLevels[lvl]
473 firstName = lvl
474 firstError = self._errorDetails[lvl][0]
475
476 return {'level': firstName, 'nLevel': firstLevel, 'firstError': firstError}
477

◆ g494ExceptionParser()

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

Definition at line 605 of file trfValidation.py.

605 def g494ExceptionParser(self, lineGenerator, firstline, firstLineCount):
606 g4Report = firstline
607 g4lines = 1
608 if 'Aborting execution' not in g4Report:
609 for line, linecounter in lineGenerator:
610 g4Report += os.linesep + line
611 g4lines += 1
612 # Test for the closing string
613 if '*** ' in line:
614 break
615 if g4lines >= 25:
616 msg.warning('G4 exception closing string not found within {0} log lines of line {1}'.format(g4lines, firstLineCount))
617 break
618
619 # G4 exceptions can be fatal or they can be warnings...
620 msg.debug('Identified G4 exception - adding to error detail report')
621 if "just a warning" in g4Report:
622 if self._levelCounter['WARNING'] <= self._msgLimit:
623 self._levelCounter['WARNING'] += 1
624 self._errorDetails['WARNING'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
625 elif self._levelCounter['WARNING'] == self._msgLimit + 1:
626 msg.warning("Found message number {0} at level WARNING - this and further messages will be supressed from the report".format(self._levelCounter['WARNING']))
627 else:
628 self._levelCounter['FATAL'] += 1
629 self._errorDetails['FATAL'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
630

◆ g4ExceptionParser()

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

Definition at line 631 of file trfValidation.py.

631 def g4ExceptionParser(self, lineGenerator, firstline, firstLineCount, g4ExceptionLineDepth):
632 g4Report = firstline
633 g4lines = 1
634 for line, linecounter in lineGenerator:
635 g4Report += os.linesep + line
636 g4lines += 1
637 # Test for the closing string
638 if 'G4Exception-END' in line:
639 break
640 if g4lines >= g4ExceptionLineDepth:
641 msg.warning('G4 exception closing string not found within {0} log lines of line {1}'.format(g4lines, firstLineCount))
642 break
643
644 # G4 exceptions can be fatal or they can be warnings...
645 msg.debug('Identified G4 exception - adding to error detail report')
646 if "-------- WWWW -------" in g4Report:
647 if self._levelCounter['WARNING'] <= self._msgLimit:
648 self._levelCounter['WARNING'] += 1
649 self._errorDetails['WARNING'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
650 elif self._levelCounter['WARNING'] == self._msgLimit + 1:
651 msg.warning("Found message number {0} at level WARNING - this and further messages will be supressed from the report".format(self._levelCounter['WARNING']))
652 else:
653 self._levelCounter['FATAL'] += 1
654 self._errorDetails['FATAL'].append({'message': g4Report, 'firstLine': firstLineCount, 'count': 1})
655
656

◆ 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 268 of file trfValidation.py.

268 def knowledgeFileHandler(self, knowledgefile):
269 # load abnormal/error line(s) from the knowledge file(s)
270 linesList = []
271 fullName = trfUtils.findFile(os.environ['DATAPATH'], knowledgefile)
272 if not fullName:
273 msg.warning('Knowledge file {0} could not be found in DATAPATH'.format(knowledgefile))
274 else:
275 try:
276 with open(fullName) as knowledgeFileHandle:
277 msg.debug('Opened knowledge file {0} from here: {1}'.format(knowledgefile, fullName))
278
279 for line in knowledgeFileHandle:
280 if line.startswith('#') or line == '' or line =='\n':
281 continue
282 line = line.rstrip('\n')
283 linesList.append(line)
284 except OSError as e:
285 msg.warning('Failed to open knowledge file {0}: {1}'.format(fullName, e))
286 return linesList
287

◆ moreDetails()

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

Definition at line 487 of file trfValidation.py.

487 def moreDetails(self, log, firstline, firstLineCount, knowledgeFile, offset=0):
488 # Look for "abnormal" and "last normal" line(s)
489 # Make a list of last e.g. 50 lines before core dump
490 abnormalLinesList = self.knowledgeFileHandler(knowledgeFile)
491 linesToBeScanned = 50
492 seenAbnormalLines = []
493 abnormalLinesReport = {}
494 lastNormalLineReport = {}
495
496 linesList = []
497 myGen = trfUtils.lineByLine(log)
498 for line, linecounter in myGen:
499 if linecounter in range(firstLineCount - linesToBeScanned, firstLineCount-offset):
500 linesList.append([linecounter, line])
501 elif linecounter == firstLineCount:
502 break
503
504 for linecounter, line in reversed(linesList):
505 if re.findall(r'|'.join(abnormalLinesList), line):
506 seenLine = False
507 for dic in seenAbnormalLines:
508 # count repetitions or similar (e.g. first 15 char) abnormal lines
509 if dic['message'] == line or dic['message'][0:15] == line[0:15]:
510 dic['count'] += 1
511 seenLine = True
512 break
513 if seenLine is False:
514 seenAbnormalLines.append({'message': line, 'firstLine': linecounter, 'count': 1})
515 else:
516 if line != '':
517 lastNormalLineReport = {'message': line, 'firstLine': linecounter, 'count': 1}
518 break
519 else:
520 continue
521
522 # Write the list of abnormal lines into the abnormalLinesReport dictionary
523 # The keys of each abnormal line have a number suffix starting with 0
524 # e.g., first abnormal line's keys are :{'mesage0', 'firstLine0', 'count0'}
525
526 for a in range(len(seenAbnormalLines)):
527 abnormalLinesReport.update({'message{0}'.format(a): seenAbnormalLines[a]['message'], 'firstLine{0}'.format(a): seenAbnormalLines[a]['firstLine'],
528 'count{0}'.format(a): seenAbnormalLines[a]['count']})
529
530 return {'abnormalLines': abnormalLinesReport, 'lastNormalLine': lastNormalLineReport}
531
532

◆ 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 242 of file trfValidation.py.

242 def python(self):
243 errorDict = {'countSummary': {}, 'details': {}}
244 for level, count in self._levelCounter.items():
245 errorDict['countSummary'][level] = count
246 if self._levelCounter[level] > 0 and len(self._errorDetails[level]) > 0:
247 errorDict['details'][level] = []
248 for error in self._errorDetails[level]:
249 errorDict['details'][level].append(error)
250 return errorDict
251

◆ pythonExceptionParser()

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

Definition at line 657 of file trfValidation.py.

657 def pythonExceptionParser(self, log, lineGenerator, firstline, firstLineCount):
658 pythonExceptionReport = ""
659 lastLine = firstline
660 lastLine2 = firstline
661 pythonErrorLine = firstLineCount
662 pyLines = 1
663 for line, linecounter in lineGenerator:
664 if 'Py:Athena' in line and 'INFO leaving with code' in line:
665 if len(lastLine)> 0:
666 pythonExceptionReport = lastLine
667 pythonErrorLine = linecounter-1
668 else: # Sometimes there is a blank line after the exception
669 pythonExceptionReport = lastLine2
670 pythonErrorLine = linecounter-2
671 break
672 if pyLines >= 25:
673 msg.warning('Could not identify python exception correctly scanning {0} log lines after line {1}'.format(pyLines, firstLineCount))
674 pythonExceptionReport = "Unable to identify specific exception"
675 pythonErrorLine = firstLineCount
676 break
677 lastLine2 = lastLine
678 lastLine = line
679 pyLines += 1
680
681 pythonExceptionDetailsReport = self.moreDetails(log, firstline, firstLineCount, 'knowledgeFile.db')
682 abnormalLines = pythonExceptionDetailsReport['abnormalLines']
683
684 # concatenate an extract of first seen abnormal line to pythonExceptionReport
685 if 'message0' in abnormalLines.keys():
686 pythonExceptionReport += '; Abnormal line seen just before python exception: ' + abnormalLines['message0'][0:30] + '...[truncated] ' + '(see the jobReport)'
687
688 msg.debug('Identified python exception - adding to error detail report')
689 self._levelCounter['FATAL'] += 1
690 self._errorDetails['FATAL'].append({'moreDetails': pythonExceptionDetailsReport, 'message': pythonExceptionReport, 'firstLine': pythonErrorLine, 'count': 1})
691
692

◆ resetReport()

python.trfValidation.athenaLogFileReport.resetReport ( self)

Reimplemented from python.trfValidation.logFileReport.

Definition at line 252 of file trfValidation.py.

252 def resetReport(self):
253 self._levelCounter = {}
254 for level in list(stdLogLevels) + ['UNKNOWN', 'IGNORED']:
255 self._levelCounter[level] = 0
256
257 self._errorDetails = {}
258 self._eventLoopWarnings = []
259 for level in self._levelCounter:
260 self._errorDetails[level] = []
261 # Format:
262 # List of dicts {'message': errMsg, 'firstLine': lineNo, 'count': N}
263 self._dbbytes = 0
264 self._dbtime = 0.0
265

◆ rootSysErrorParser()

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

Definition at line 700 of file trfValidation.py.

700 def rootSysErrorParser(self, lineGenerator, firstline, firstLineCount):
701 msg.debug('Identified ROOT IO problem - adding to error detail report')
702 self._levelCounter['FATAL'] += 1
703 self._errorDetails['FATAL'].append({'message': firstline, 'firstLine': firstLineCount, 'count': 1})
704

◆ scanLogFile()

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

Reimplemented from python.trfValidation.logFileReport.

Definition at line 288 of file trfValidation.py.

288 def scanLogFile(self, resetReport=False):
289
290 nonStandardErrorsList = self.knowledgeFileHandler('nonStandardErrors.db')
291
292 if resetReport:
293 self.resetReport()
294
295 for log in self._logfile:
296 msg.debug('Now scanning logfile {0}'.format(log))
297 seenNonStandardError = ''
298 customLogParser = None
299 if log == 'log.generate':
300 from EvgenProdTools.EvgenParserTool import evgenParserTool
301 customLogParser = evgenParserTool()
302 # N.B. Use the generator so that lines can be grabbed by subroutines, e.g., core dump svc reporter
303 try:
304 myGen = trfUtils.lineByLine(log, substepName=self._substepName)
305 except IOError as e:
306 msg.error('Failed to open transform logfile {0}: {1:s}'.format(log, e))
307 # Return this as a small report
308 self._levelCounter['ERROR'] = 1
309 self._errorDetails['ERROR'] = {'message': str(e), 'firstLine': 0, 'count': 1}
310 return
311 # Detect whether we are in the event loop part of the log file
312 inEventLoop = False
313 for line, lineCounter in myGen:
314 if '===>>> start processing event' in line: inEventLoop = True
315 if 'Application Manager Stopped successfully' in line: inEventLoop = False
316
317 # In case we have enabled a custom log parser, run the line through it first
318 if customLogParser is not None:
319 customLogParser.processLine(line)
320 # Search for metadata strings
321 m = self._metaPat.search(line)
322 if m is not None:
323 key, value = m.groups()
324 self._metaData[key] = value
325
326 m = self._regExp.match(line)
327 if m is None:
328 # We didn't manage to get a recognised standard line from the file
329 # But we can check for certain other interesting things, like core dumps
330 if 'Core dump from CoreDumpSvc' in line:
331 msg.warning('Detected CoreDumpSvc report - activating core dump svc grabber')
332 self.coreDumpSvcParser(log, myGen, line, lineCounter)
333 continue
334 # Add the G4 exceptipon parsers
335 if 'G4Exception-START' in line:
336 msg.warning('Detected G4 exception report - activating G4 exception grabber')
337 self.g4ExceptionParser(myGen, line, lineCounter, 40)
338 continue
339 if '*** G4Exception' in line:
340 msg.warning('Detected G4 9.4 exception report - activating G4 exception grabber')
341 self.g494ExceptionParser(myGen, line, lineCounter)
342 continue
343 # Add the python exception parser
344 if 'Shortened traceback (most recent user call last)' in line:
345 msg.warning('Detected python exception - activating python exception grabber')
346 self.pythonExceptionParser(log, myGen, line, lineCounter)
347 continue
348 # Add parser for missed bad_alloc
349 if 'terminate called after throwing an instance of \'std::bad_alloc\'' in line:
350 msg.warning('Detected bad_alloc!')
351 self.badAllocExceptionParser(myGen, line, lineCounter)
352 continue
353 # Parser for ROOT reporting a stale file handle (see ATLASG-448)
354 # Amendment: Generalize the search (see ATLASRECTS-7121)
355 if 'Error in <TFile::ReadBuffer>' in line:
356 self.rootSysErrorParser(myGen, line, lineCounter)
357 continue
358
359 if 'Error in <TFile::WriteBuffer>' in line:
360 self.rootSysErrorParser(myGen, line, lineCounter)
361 continue
362 # Check if the line is among the non-standard logging errors from the knowledge file
363 if any(line in l for l in nonStandardErrorsList):
364 seenNonStandardError = line
365 continue
366
367 msg.debug('Non-standard line in %s: %s', log, line)
368 self._levelCounter['UNKNOWN'] += 1
369 continue
370
371 # Line was matched successfully
372 fields = {}
373 for matchKey in ('service', 'level', 'message'):
374 fields[matchKey] = m.group(matchKey)
375 msg.debug('Line parsed as: {0}'.format(fields))
376
377 # If this is a WARNING and we passed the start of the event loop,
378 # add it to special list
379 if (fields['level'] == 'WARNING') and inEventLoop:
380 self._eventLoopWarnings.append(fields)
381
382 # Check this is not in our ignore list
383 ignoreFlag = False
384 for ignorePat in self._ignoreList.structuredPatterns:
385 serviceMatch = ignorePat['service'].match(fields['service'])
386 levelMatch = (ignorePat['level'] == "" or ignorePat['level'] == fields['level'])
387 messageMatch = ignorePat['message'].match(fields['message'])
388 if serviceMatch and levelMatch and messageMatch:
389 msg.info('Error message "{0}" was ignored at line {1} (structured match)'.format(line, lineCounter))
390 ignoreFlag = True
391 break
392 if ignoreFlag is False:
393 for searchPat in self._ignoreList.searchPatterns:
394 if searchPat.search(line):
395 msg.info('Error message "{0}" was ignored at line {1} (search match)'.format(line, lineCounter))
396 ignoreFlag = True
397 break
398 if ignoreFlag:
399 # Got an ignore - message this to a special IGNORED error
400 fields['level'] = 'IGNORED'
401 else:
402 # Some special handling for specific errors (maybe generalise this if
403 # there end up being too many special cases)
404 # Upgrade bad_alloc to CATASTROPHE to allow for better automated handling of
405 # jobs that run out of memory
406 if 'std::bad_alloc' in fields['message']:
407 fields['level'] = 'CATASTROPHE'
408
409 # concatenate the seen non-standard logging error to the FATAL
410 if fields['level'] == 'FATAL':
411 if seenNonStandardError:
412 line += '; ' + seenNonStandardError
413
414 # Count this error
415 self._levelCounter[fields['level']] += 1
416
417 # Record some error details
418 # N.B. We record 'IGNORED' errors as these really should be flagged for fixing
419 if fields['level'] == 'IGNORED' or stdLogLevels[fields['level']] >= self._msgDetails:
420 if self._levelCounter[fields['level']] <= self._msgLimit:
421 detailsHandled = False
422 for seenError in self._errorDetails[fields['level']]:
423 if seenError['message'] == line:
424 seenError['count'] += 1
425 detailsHandled = True
426 break
427 if detailsHandled is False:
428 self._errorDetails[fields['level']].append({'message': line, 'firstLine': lineCounter, 'count': 1})
429 elif self._levelCounter[fields['level']] == self._msgLimit + 1:
430 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']))
431 else:
432 # Overcounted
433 pass
434 if 'Total payload read from IOVDb' in fields['message']:
435 msg.debug("Found COOL payload information at line {0}".format(line))
436 a = re.match(r'(\D+)(?P<bytes>\d+)(\D+)(?P<time>\d+[.]?\d*)(\D+)', fields['message'])
437 self._dbbytes += int(a.group('bytes'))
438 self._dbtime += float(a.group('time'))
439 # Finally, if we have a custom log parser, use it to update the metadata dictionary
440 if customLogParser is not None:
441 customLogParser.report()
442 self._metaData = customLogParser.updateMetadata( self._metaData )
443
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:739

◆ 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 449 of file trfValidation.py.

449 def worstError(self):
450 worst = stdLogLevels['DEBUG']
451 worstName = 'DEBUG'
452 for lvl, count in self._levelCounter.items():
453 if count > 0 and stdLogLevels.get(lvl, 0) > worst:
454 worstName = lvl
455 worst = stdLogLevels[lvl]
456 if len(self._errorDetails[worstName]) > 0:
457 firstError = self._errorDetails[worstName][0]
458 else:
459 firstError = None
460
461 return {'level': worstName, 'nLevel': worst, 'firstError': firstError}
462

Member Data Documentation

◆ _dbbytes

python.trfValidation.athenaLogFileReport._dbbytes = 0
protected

Definition at line 263 of file trfValidation.py.

◆ _dbtime

float python.trfValidation.athenaLogFileReport._dbtime = 0.0
protected

Definition at line 264 of file trfValidation.py.

◆ _errorDetails

python.trfValidation.athenaLogFileReport._errorDetails = {}
protected

Definition at line 257 of file trfValidation.py.

◆ _eventLoopWarnings

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

Definition at line 231 of file trfValidation.py.

◆ _ignoreList

python.trfValidation.athenaLogFileReport._ignoreList = ignoreList
protected

Definition at line 218 of file trfValidation.py.

◆ _levelCounter

python.trfValidation.athenaLogFileReport._levelCounter = {}
protected

Definition at line 253 of file trfValidation.py.

◆ _logfile

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

Definition at line 181 of file trfValidation.py.

◆ _metaData

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

Definition at line 230 of file trfValidation.py.

◆ _metaPat

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

Definition at line 229 of file trfValidation.py.

◆ _msgDetails

python.trfValidation.logFileReport._msgDetails = msgDetailLevel
protectedinherited

Definition at line 186 of file trfValidation.py.

◆ _msgLimit

python.trfValidation.logFileReport._msgLimit = msgLimit
protectedinherited

Definition at line 185 of file trfValidation.py.

◆ _re

python.trfValidation.logFileReport._re = None
protectedinherited

Definition at line 187 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 227 of file trfValidation.py.

◆ _substepName

python.trfValidation.athenaLogFileReport._substepName = substepName
protected

Definition at line 232 of file trfValidation.py.


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