ATLAS Offline Software
Public Member Functions | Private Attributes | List of all members
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

def __init__ (self, logfile, substepName=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'], ignoreList=None)
 Class constructor. More...
 
def python (self)
 Produce a python dictionary summary of the log file report for inclusion in the executor report. More...
 
def resetReport (self)
 
def 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. More...
 
def scanLogFile (self, resetReport=False)
 
def dbMonitor (self)
 Return data volume and time spend to retrieve information from the database. More...
 
def worstError (self)
 Return the worst error found in the logfile (first error of the most serious type) More...
 
def firstError (self, floor='ERROR')
 Return the first error found in the logfile above a certain loglevel. More...
 
def eventLoopWarnings (self)
 
def moreDetails (self, log, firstline, firstLineCount, knowledgeFile, offset=0)
 
def 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. More...
 
def g494ExceptionParser (self, lineGenerator, firstline, firstLineCount)
 
def g4ExceptionParser (self, lineGenerator, firstline, firstLineCount, g4ExceptionLineDepth)
 
def pythonExceptionParser (self, log, lineGenerator, firstline, firstLineCount)
 
def badAllocExceptionParser (self, lineGenerator, firstline, firstLineCount)
 
def rootSysErrorParser (self, lineGenerator, firstline, firstLineCount)
 
def __str__ (self)
 
def scanLogFile (self)
 
def firstError (self)
 

Private Attributes

 _ignoreList
 
 _regExp
 
 _metaPat
 
 _metaData
 
 _eventLoopWarnings
 
 _substepName
 
 _msgLimit
 
 _levelCounter
 
 _errorDetails
 
 _dbbytes
 
 _dbtime
 
 _logfile
 
 _msgDetails
 
 _re
 

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.

Constructor & Destructor Documentation

◆ __init__()

def 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__()

def python.trfValidation.athenaLogFileReport.__str__ (   self)

Reimplemented from python.trfValidation.logFileReport.

Definition at line 705 of file trfValidation.py.

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

◆ badAllocExceptionParser()

def 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()

def 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 

◆ dbMonitor()

def 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()

def 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 

◆ firstError() [1/2]

def python.trfValidation.logFileReport.firstError (   self)
inherited

Definition at line 201 of file trfValidation.py.

201  def firstError(self):
202  pass
203 

◆ firstError() [2/2]

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

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

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()

def 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()

def 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()

def 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()

def 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()

def 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()

def 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()

def 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()

def 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() [1/2]

def python.trfValidation.logFileReport.scanLogFile (   self)
inherited

Definition at line 195 of file trfValidation.py.

195  def scanLogFile(self):
196  pass
197 

◆ scanLogFile() [2/2]

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

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 

◆ worstError()

def 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
private

Definition at line 263 of file trfValidation.py.

◆ _dbtime

python.trfValidation.athenaLogFileReport._dbtime
private

Definition at line 264 of file trfValidation.py.

◆ _errorDetails

python.trfValidation.athenaLogFileReport._errorDetails
private

Definition at line 257 of file trfValidation.py.

◆ _eventLoopWarnings

python.trfValidation.athenaLogFileReport._eventLoopWarnings
private

Definition at line 231 of file trfValidation.py.

◆ _ignoreList

python.trfValidation.athenaLogFileReport._ignoreList
private

Definition at line 218 of file trfValidation.py.

◆ _levelCounter

python.trfValidation.athenaLogFileReport._levelCounter
private

Definition at line 253 of file trfValidation.py.

◆ _logfile

python.trfValidation.logFileReport._logfile
privateinherited

Definition at line 181 of file trfValidation.py.

◆ _metaData

python.trfValidation.athenaLogFileReport._metaData
private

Definition at line 230 of file trfValidation.py.

◆ _metaPat

python.trfValidation.athenaLogFileReport._metaPat
private

Definition at line 229 of file trfValidation.py.

◆ _msgDetails

python.trfValidation.logFileReport._msgDetails
privateinherited

Definition at line 186 of file trfValidation.py.

◆ _msgLimit

python.trfValidation.athenaLogFileReport._msgLimit
private

Definition at line 233 of file trfValidation.py.

◆ _re

python.trfValidation.logFileReport._re
privateinherited

Definition at line 187 of file trfValidation.py.

◆ _regExp

python.trfValidation.athenaLogFileReport._regExp
private
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
private

Definition at line 232 of file trfValidation.py.


The documentation for this class was generated from the following file:
vtune_athena.format
format
Definition: vtune_athena.py:14
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
search
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:738
XMLtoHeader.count
count
Definition: XMLtoHeader.py:84
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
python.MadGraphUtils.python
string python
Definition: MadGraphUtils.py:20
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.processes.powheg.ZZ.ZZ.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZ.py:18
Trk::open
@ open
Definition: BinningType.h:40
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
str
Definition: BTagTrackIpAccessor.cxx:11
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
match
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition: hcg.cxx:356
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65