18msg = logging.getLogger(__name__)
20from PyJobTransforms.trfExeStepTools
import getExecutorStepEventCounts
25import PyJobTransforms.trfExceptions
as trfExceptions
36 def __init__(self, files=['atlas_error_mask.db'], extraSearch = []):
54 for patternFile
in files:
55 if patternFile ==
"None":
57 fullName = trfUtils.findFile(os.environ[
'DATAPATH'], patternFile)
59 msg.warning(
'Error pattern file {0} could not be found in DATAPATH'.format(patternFile))
62 with open(fullName)
as patternFileHandle:
63 msg.debug(
'Opened error file {0} from here: {1}'.format(patternFile, fullName))
65 for line
in patternFileHandle:
67 if line.startswith(
'#')
or line ==
'':
71 (who, level, message) = [ s.strip()
for s
in line.split(
',', 2) ]
75 reWho = re.compile(who)
76 reMessage = re.compile(message)
78 msg.warning(
'Could not parse this line as a valid error pattern: {0}'.format(line))
81 msg.warning(
'Could not parse valid regexp from {0}: {1}'.format(message, e))
84 msg.debug(
'Successfully parsed: who={0}, level={1}, message={2}'.format(who, level, message))
88 except OSError
as xxx_todo_changeme:
89 (errno, errMsg) = xxx_todo_changeme.args
90 msg.warning(
'Failed to open error pattern file {0}: {1} ({2})'.format(fullName, errMsg, errno))
94 for string
in searchStrings:
97 msg.debug(
'Successfully parsed additional logfile search string: {0}'.format(string))
99 msg.warning(
'Could not parse valid regexp from {0}: {1}'.format(string, e))
107 def __init__(self, logfile=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR']):
110 if isinstance(logfile, str):
146 def __init__(self, logfile, substepName=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'], ignoreList=None):
157 self.
_regExp = re.compile(
r'(?P<service>[^\s]+\w)(.*)\s+(?P<level>' +
'|'.join(stdLogLevels) +
r')\s+(?P<message>.*)')
159 self.
_metaPat = re.compile(
r"MetaData:\s+(.*?)\s*=\s*(.*)$")
167 super(athenaLogFileReport, self).
__init__(logfile, msgLimit, msgDetailLevel)
173 errorDict = {
'countSummary': {},
'details': {}}
175 errorDict[
'countSummary'][level] = count
177 errorDict[
'details'][level] = []
179 errorDict[
'details'][level].append(error)
184 for level
in list(stdLogLevels) + [
'UNKNOWN',
'IGNORED']:
201 fullName = trfUtils.findFile(os.environ[
'DATAPATH'], knowledgefile)
203 msg.warning(
'Knowledge file {0} could not be found in DATAPATH'.format(knowledgefile))
206 with open(fullName)
as knowledgeFileHandle:
207 msg.debug(
'Opened knowledge file {0} from here: {1}'.format(knowledgefile, fullName))
209 for line
in knowledgeFileHandle:
210 if line.startswith(
'#')
or line ==
'' or line ==
'\n':
212 line = line.rstrip(
'\n')
213 linesList.append(line)
215 msg.warning(
'Failed to open knowledge file {0}: {1}'.format(fullName, e))
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()
234 myGen = trfUtils.lineByLine(log, substepName=self.
_substepName)
236 msg.error(
'Failed to open transform logfile {0}: {1:s}'.format(log, e))
239 self.
_errorDetails[
'ERROR'] = {
'message': str(e),
'firstLine': 0,
'count': 1}
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
248 if customLogParser
is not None:
249 customLogParser.processLine(line)
253 key, value = m.groups()
260 if 'Core dump from CoreDumpSvc' in line:
261 msg.warning(
'Detected CoreDumpSvc report - activating core dump svc grabber')
265 if 'G4Exception-START' in line:
266 msg.warning(
'Detected G4 exception report - activating G4 exception grabber')
269 if '*** G4Exception' in line:
270 msg.warning(
'Detected G4 9.4 exception report - activating G4 exception grabber')
274 if 'Shortened traceback (most recent user call last)' in line:
275 msg.warning(
'Detected python exception - activating python exception grabber')
279 if 'terminate called after throwing an instance of \'std::bad_alloc\'' in line:
280 msg.warning(
'Detected bad_alloc!')
285 if 'Error in <TFile::ReadBuffer>' in line:
289 if 'Error in <TFile::WriteBuffer>' in line:
293 if any(line
in l
for l
in nonStandardErrorsList):
294 seenNonStandardError = line
297 msg.debug(
'Non-standard line in %s: %s', log, line)
303 for matchKey
in (
'service',
'level',
'message'):
304 fields[matchKey] = m.group(matchKey)
305 msg.debug(
'Line parsed as: {0}'.format(fields))
309 if (fields[
'level'] ==
'WARNING')
and inEventLoop:
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))
322 if ignoreFlag
is False:
324 if searchPat.search(line):
325 msg.info(
'Error message "{0}" was ignored at line {1} (search match)'.format(line, lineCounter))
330 fields[
'level'] =
'IGNORED'
336 if 'std::bad_alloc' in fields[
'message']:
337 fields[
'level'] =
'CATASTROPHE'
340 if fields[
'level'] ==
'FATAL':
341 if seenNonStandardError:
342 line +=
'; ' + seenNonStandardError
349 if fields[
'level'] ==
'IGNORED' or stdLogLevels[fields[
'level']] >= self.
_msgDetails:
351 detailsHandled =
False
353 if seenError[
'message'] == line:
354 seenError[
'count'] += 1
355 detailsHandled =
True
357 if detailsHandled
is False:
358 self.
_errorDetails[fields[
'level']].append({
'message': line,
'firstLine': lineCounter,
'count': 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']))
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'))
370 if customLogParser
is not None:
371 customLogParser.report()
380 worst = stdLogLevels[
'DEBUG']
383 if count > 0
and stdLogLevels.get(lvl, 0) > worst:
385 worst = stdLogLevels[lvl]
391 return {
'level': worstName,
'nLevel': worst,
'firstError': firstError}
395 firstLine = firstError =
None
396 firstLevel = stdLogLevels[floor]
399 if (count > 0
and stdLogLevels.get(lvl, 0) >= stdLogLevels[floor]
and
400 (firstError
is None or self.
_errorDetails[lvl][0][
'firstLine'] < firstLine)):
402 firstLevel = stdLogLevels[lvl]
406 return {
'level': firstName,
'nLevel': firstLevel,
'firstError': firstError}
409 eventLoopWarnings = []
411 if item
in [element[
'item']
for element
in eventLoopWarnings]:
414 eventLoopWarnings.append({
'item':item,
'count': count})
415 return eventLoopWarnings
417 def moreDetails(self, log, firstline, firstLineCount, knowledgeFile, offset=0):
421 linesToBeScanned = 50
422 seenAbnormalLines = []
423 abnormalLinesReport = {}
424 lastNormalLineReport = {}
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:
434 for linecounter, line
in reversed(linesList):
435 if re.findall(
r'|'.join(abnormalLinesList), line):
437 for dic
in seenAbnormalLines:
439 if dic[
'message'] == line
or dic[
'message'][0:15] == line[0:15]:
443 if seenLine
is False:
444 seenAbnormalLines.append({
'message': line,
'firstLine': linecounter,
'count': 1})
447 lastNormalLineReport = {
'message': line,
'firstLine': linecounter,
'count': 1}
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']})
460 return {
'abnormalLines': abnormalLinesReport,
'lastNormalLine': lastNormalLineReport}
470 _eventCounter = _run = _event = _currentAlgorithm = _functionLine = _currentFunction =
None
471 coreDumpReport =
'Core dump from CoreDumpSvc'
474 coreDumpDetailsReport = {}
476 for line, linecounter
in lineGenerator:
479 if 'Caught signal 11(Segmentation fault)' in line:
480 coreDumpReport =
'Segmentation fault'
481 if 'Event counter' in line:
485 if 'EventID' in line:
486 match = re.findall(
r'\[.*?\]', line)
487 if match
and match.__len__() >= 2:
490 keys = (match[0].
strip(brackets)).
split(commaDelimer)
491 values = (match[1].
strip(brackets)).
split(commaDelimer)
494 _run =
'Run: ' + values[keys.index(
'Run')]
497 _event =
'Evt: ' + values[keys.index(
'Evt')]
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:
505 _currentFunction =
'Current Function: ' + line.split(
' in ')[1].
split()[0]
507 _currentFunction =
'Current Function: ' + line.split()[1]
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)
522 coreDumpDetailsReport = self.
moreDetails(log, firstline, firstLineCount,
'knowledgeFile.db', offset)
523 abnormalLines = coreDumpDetailsReport[
'abnormalLines']
526 if 'message0' in abnormalLines.keys():
527 coreDumpReport +=
'; Abnormal line seen just before core dump: ' + abnormalLines[
'message0'][0:30] +
'...[truncated] ' +
'(see the jobReport)'
530 msg.debug(
'Identified core dump - adding to error detail report')
532 self.
_errorDetails[
'FATAL'].append({
'moreDetails': coreDumpDetailsReport,
'message': coreDumpReport,
'firstLine': firstLineCount,
'count': 1})
538 if 'Aborting execution' not in g4Report:
539 for line, linecounter
in lineGenerator:
540 g4Report += os.linesep + line
546 msg.warning(
'G4 exception closing string not found within {0} log lines of line {1}'.format(g4lines, firstLineCount))
550 msg.debug(
'Identified G4 exception - adding to error detail report')
551 if "just a warning" in g4Report:
554 self.
_errorDetails[
'WARNING'].append({
'message': g4Report,
'firstLine': firstLineCount,
'count': 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']))
559 self.
_errorDetails[
'FATAL'].append({
'message': g4Report,
'firstLine': firstLineCount,
'count': 1})
564 for line, linecounter
in lineGenerator:
565 g4Report += os.linesep + line
568 if 'G4Exception-END' in line:
570 if g4lines >= g4ExceptionLineDepth:
571 msg.warning(
'G4 exception closing string not found within {0} log lines of line {1}'.format(g4lines, firstLineCount))
575 msg.debug(
'Identified G4 exception - adding to error detail report')
576 if "-------- WWWW -------" in g4Report:
579 self.
_errorDetails[
'WARNING'].append({
'message': g4Report,
'firstLine': firstLineCount,
'count': 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']))
584 self.
_errorDetails[
'FATAL'].append({
'message': g4Report,
'firstLine': firstLineCount,
'count': 1})
588 pythonExceptionReport =
""
590 lastLine2 = firstline
591 pythonErrorLine = firstLineCount
593 for line, linecounter
in lineGenerator:
594 if 'Py:Athena' in line
and 'INFO leaving with code' in line:
596 pythonExceptionReport = lastLine
597 pythonErrorLine = linecounter-1
599 pythonExceptionReport = lastLine2
600 pythonErrorLine = linecounter-2
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
611 pythonExceptionDetailsReport = self.
moreDetails(log, firstline, firstLineCount,
'knowledgeFile.db')
612 abnormalLines = pythonExceptionDetailsReport[
'abnormalLines']
615 if 'message0' in abnormalLines.keys():
616 pythonExceptionReport +=
'; Abnormal line seen just before python exception: ' + abnormalLines[
'message0'][0:30] +
'...[truncated] ' +
'(see the jobReport)'
618 msg.debug(
'Identified python exception - adding to error detail report')
620 self.
_errorDetails[
'FATAL'].append({
'moreDetails': pythonExceptionDetailsReport,
'message': pythonExceptionReport,
'firstLine': pythonErrorLine,
'count': 1})
624 badAllocExceptionReport =
'terminate after \'std::bad_alloc\'.'
626 msg.debug(
'Identified bad_alloc - adding to error detail report')
628 self.
_errorDetails[
'CATASTROPHE'].append({
'message': badAllocExceptionReport,
'firstLine': firstLineCount,
'count': 1})
631 msg.debug(
'Identified ROOT IO problem - adding to error detail report')
633 self.
_errorDetails[
'FATAL'].append({
'message': firstline,
'firstLine': firstLineCount,
'count': 1})
640 def __init__(self, logfile=None, msgLimit=200, msgDetailLevel=stdLogLevels['ERROR']):
644 super(scriptLogFileReport, self).
__init__(logfile, msgLimit, msgDetailLevel)
648 for level
in list(stdLogLevels) + [
'UNKNOWN',
'IGNORED']:
660 msg.info(
'Scanning logfile {0}'.format(log))
662 myGen = trfUtils.lineByLine(log)
664 msg.error(
'Failed to open transform logfile {0}: {1:s}'.format(log, e))
667 self.
_errorDetails[
'ERROR'] = {
'message': str(e),
'firstLine': 0,
'count': 1}
670 for line, lineCounter
in myGen:
674 if line.__contains__(
'Error in <TFile::ReadBuffer>')
or \
675 line.__contains__(
'Error in <TFile::WriteBuffer>'):
680 worstlevelName =
'DEBUG'
681 worstLevel = stdLogLevels[worstlevelName]
683 if count > 0
and stdLogLevels.get(levelName, 0) > worstLevel:
684 worstlevelName = levelName
685 worstLevel = stdLogLevels[levelName]
692 return {
'level': worstlevelName,
'nLevel': worstLevel,
'firstError': firstError}
698 msg.debug(
'Identified ROOT IO problem - adding to error detail report')
700 self.
_errorDetails[
'FATAL'].append({
'message': line,
'firstLine': lineCounter,
'count': 1})
708 except Exception
as exception:
709 msg.error(
'Failed to import module PyJobTransforms.trfFileValidationFunctions with error {error}'.format(error = exception))
712 import multiprocessing
714 level = kwargs.get(
'level')
715 if level
is not None:
716 if level < msg.getEffectiveLevel():
718 msg.debug(f
"Set logging level of {msg.name!r} to {logging.getLevelName(level)!r}")
720 msg.debug(f
"Current process: {multiprocessing.current_process().name}")
722 validationFunction = getattr(trfFileValidationFunctions, functionName)
723 args =
", ".join(f
"{k}={v}" for k, v
in kwargs.items())
724 msg.debug(f
"Calling {validationFunction.__name__}({file}, {args}) ")
725 return validationFunction(file, **kwargs)
733 if multithreadedMode:
734 os.environ[
'TRF_MULTITHREADED_VALIDATION'] =
'TRUE'
735 if parallelMode
is False:
736 msg.info(
'Starting legacy (serial) file validation')
737 for (key, arg)
in dictionary.items():
738 if not isinstance(arg, argFile):
742 if arg.auxiliaryFile:
745 msg.info(
'Validating data type %s...', key)
747 for fname
in arg.value:
748 msg.info(
'Validating file %s...', fname)
751 msg.info(
'{0}: Testing corruption...'.format(fname))
752 if arg.getSingleMetadata(fname,
'integrity')
is True:
753 msg.info(
'Corruption test passed.')
754 elif arg.getSingleMetadata(fname,
'integrity')
is False:
755 msg.error(
'Corruption test failed.')
757 elif arg.getSingleMetadata(fname,
'integrity') ==
'UNDEFINED':
758 msg.info(
'No corruption test defined.')
759 elif arg.getSingleMetadata(fname,
'integrity')
is None:
760 msg.error(
'Could not check for file integrity')
763 msg.error(
'Unknown rc from corruption test.')
767 msg.info(
'{0}: Testing event count...'.format(fname))
768 if arg.getSingleMetadata(fname,
'nentries')
is not None:
769 msg.info(
'Event counting test passed ({0!s} events).'.format(arg.getSingleMetadata(fname,
'nentries')))
771 msg.error(
'Event counting test failed.')
775 msg.info(
'{0}: Checking if guid exists...'.format(fname))
776 if arg.getSingleMetadata(fname,
'file_guid')
is None:
777 msg.error(
'Guid could not be determined.')
779 elif arg.getSingleMetadata(fname,
'file_guid') ==
'UNDEFINED':
780 msg.info(
'Guid not defined.')
782 msg.info(
'Guid is %s', arg.getSingleMetadata(fname,
'file_guid'))
783 msg.info(
'Stopping legacy (serial) file validation')
784 elif parallelMode
is True:
785 msg.info(
'Starting parallel file validation')
791 integrityFunctionList = []
795 msg.debug(
'Collating list of files for validation')
796 for (key, arg)
in dictionary.items():
797 if not isinstance(arg, argFile):
801 for fname
in arg.value:
802 msg.debug(
'Appending file {fileName} to list of files for validation'.format(fileName = str(fname)))
804 fileList.append(fname)
812 integrityFunctionList.append(arg.integrityFunction)
813 except AttributeError
as e:
814 errmsg = f
'Validation function for file {fname} of type'\
815 f
' {type(arg).__name__!r} not available for parallel file validation: {e}'
818 trfExit.nameToCode(
'TRF_EXEC_VALIDATION_FAIL'), errmsg)
824 name =
"validation of file {fileName}".format(
825 fileName = str(fname)),
826 workFunction = returnIntegrityOfFile,
827 workFunctionKeywordArguments = {
829 'functionName': arg.integrityFunction,
830 'level': msg.getEffectiveLevel(),
832 workFunctionTimeout = 600
839 name =
"standard file validation",
845 msg.info(
'Submitting file validation jobs to parallel job processor')
846 parallelJobProcessor1.submit(jobSubmission = jobGroup1)
847 resultsList = parallelJobProcessor1.getResults()
848 msg.info(
'Parallel file validation complete')
851 msg.info(
'Processing file integrity results')
852 for currentFile, currentArg, currentIntegrityFunction, currentResult
in zip(fileList, argList, integrityFunctionList, resultsList):
853 msg.info(
'{IO} file {fileName} has integrity status {integrityStatus} as determined by integrity function {integrityFunction}'.format(
855 fileName = str(currentFile),
856 integrityStatus = str(currentResult),
857 integrityFunction = str(currentIntegrityFunction)
862 if currentResult[0]
is True:
863 msg.info(
'Updating integrity metadata for file {fileName}'.format(fileName = str(currentFile)))
864 currentArg._setMetadata(files=[currentFile,], metadataKeys={
'integrity': currentResult[0]})
866 exceptionMessage =
"{IO} file validation failure on file {fileName} with integrity status {integrityStatus} as determined by integrity function {integrityFunction}".format(
868 fileName = str(currentFile),
869 integrityStatus = str(currentResult),
870 integrityFunction = str(currentIntegrityFunction)
872 msg.error(
"exception message: {exceptionMessage}".format(
873 exceptionMessage = exceptionMessage
875 exitCodeName =
'TRF_OUTPUT_FILE_VALIDATION_FAIL'
877 trfExit.nameToCode(exitCodeName),
882 if currentArg.getSingleMetadata(currentFile, metadataKey =
'integrity', populate =
False) == currentResult[0]:
883 msg.debug(
"file integrity metadata update successful")
885 msg.error(
"file integrity metadata update unsuccessful")
887 metadataKeys = (
'nentries',
'file_guid')
888 msg.info(f
"{', '.join(fileList)}: Checking {', '.join(map(repr, metadataKeys))} ...")
889 metadata = {fname: arg.getMetadata(fname, metadataKeys=metadataKeys)[fname]
890 for fname, arg
in zip(fileList, argList, strict=
True)}
891 success = {fname: md
for fname, md
in metadata.items()
if None not in md.values()}
894 f
"{fname}: {' '.join(f'{k}={v}' for k, v in md.items())}"
895 for fname, md
in success.items()
897 msg.info(
"Checked\n\t" +
"\n\t".join(lines))
898 if len(success) != len(metadata):
899 missing =
", ".join(fname
for fname
in metadata
if fname
not in success)
900 keys =
'" and/or "'.join(metadataKeys)
901 errmsg = f
'{missing}: Could not determine "{keys}"'
904 msg.info(
'Stopping parallel file validation')
917 def __init__(self, executor, eventCountConf=None, eventCountConfOverwrite=False):
934 self.
_eventCountConf[
'EVNT'] = {
'EVNT_MRG':
"match",
"HITS": simEventEff,
"EVNT_TR":
"filter",
"DAOD_TRUTH*" :
"match"}
936 self.
_eventCountConf[
'HITS'] = {
'RDO':
"match",
'HITS_RSM': simEventEff,
"HITS_MRG":
"match",
'HITS_FILT': simEventEff,
"RDO_FILT":
"filter",
"DAOD_TRUTH*" :
"match",
"HIST_SIM" :
"match"}
937 self.
_eventCountConf[
'BS'] = {
'ESD':
"match",
'DRAW_*':
"filter",
'NTUP_*':
"filter",
"BS_MRG":
"match",
'DESD*':
"filter",
'AOD':
"match",
'DAOD*':
"filter",
"DAOD_PHYS":
"match",
"DAOD_PHYSLITE":
"match"}
938 self.
_eventCountConf[
'RDO*'] = {
'ESD':
"match",
'DRAW_*':
"filter",
'NTUP_*':
"filter",
"RDO_MRG":
"match",
"RDO_TRIG":
"match",
'AOD':
"match",
'DAOD*':
"filter",
"DAOD_PHYS":
"match",
"DAOD_PHYSLITE":
"match",
"HIST_DIGI":
"match"}
939 self.
_eventCountConf[
'ESD'] = {
'ESD_MRG':
"match",
'AOD':
"match",
'DESD*':
"filter",
'DAOD_*':
"filter",
'NTUP_*':
"filter",
"DAOD_PHYS":
"match",
"DAOD_PHYSLITE":
"match"}
940 self.
_eventCountConf[
'AOD'] = {
'AOD_MRG' :
"match",
'TAG':
"match",
"NTUP_*":
"filter",
"DAOD_*":
"filter",
"DAOD_PHYS":
"match",
"DAOD_PHYSLITE":
"match"}
952 if eventCountConfOverwrite
is True:
957 msg.debug(
'Event count check configuration is: {0}'.format(self.
_eventCountConf))
959 msg.debug(
'Event count check ready for executor {0}'.format(self.
_executor.name))
974 msg.info(
'Overriding check configuration with: {0}'.format(override))
983 for dataTypeName
in self.
_executor.input:
986 msg.debug(
'Input data type {0} has {1} events'.format(dataTypeName, self.
_inEventDict[dataTypeName]))
988 msg.warning(
'Found no dataDictionary entry for input data type {0}'.format(dataTypeName))
992 for dataTypeName
in self.
_executor.output:
995 msg.debug(
'Output data type {0} has {1} events'.format(dataTypeName, self.
_outEventDict[dataTypeName]))
997 msg.warning(
'Found no dataDictionary entry for output data type {0}'.format(dataTypeName))
1000 if "skipEvents" in self.
_executor.conf.argdict:
1006 if "maxEvents" in self.
_executor.conf.argdict:
1015 executorEventCounts, executorEventSkips = getExecutorStepEventCounts(self.
_executor)
1020 if "eventAcceptanceEfficiency" in self.
_executor.conf.argdict:
1035 for inData, neventsInData
in self.
_inEventDict.items():
1036 if not isinstance(neventsInData, int):
1037 msg.warning(
'File size metadata for {inData} was not countable, found {neventsInData}. No event checks possible for this input data.'.format(inData=inData, neventsInData=neventsInData))
1043 matchedInData =
False
1045 if fnmatch.fnmatch(inData, inDataKey):
1046 msg.info(
"Matched input data type {inData} to {inDataKey} by globbing".format(inData=inData, inDataKey=inDataKey))
1047 matchedInData =
True
1049 if not matchedInData:
1050 msg.warning(
'No defined event count match for {inData} -> {outData}, so no check(s) possible in this case.'.format(inData=inData, outData=list(self.
_outEventDict)))
1054 expectedEvents = neventsInData
1057 if expectedEvents < 0:
1058 msg.warning(
'skipEvents was set higher than the input events in {inData}: {skipEvents} > {neventsInData}. This is not an error, but it is not a normal configuration. Expected events is now 0.'.format(inData=inData, skipEvents=self.
_skipEvents, neventsInData=neventsInData))
1063 msg.warning(
'maxEvents was set higher than inputEvents-skipEvents for {inData}: {maxEvents} > {neventsInData}-{skipEvents}. This is not an error, but it is not a normal configuration. Expected events remains {expectedEvents}.'.format(inData=inData, maxEvents=self.
_maxEvents, neventsInData=neventsInData, skipEvents=self.
_skipEvents, expectedEvents=expectedEvents))
1065 msg.warning(
'maxEvents was set higher than inputEvents for {inData}: {maxEvents} > {neventsInData}. This is not an error, but it is not a normal configuration. Expected events remains {expectedEvents}.'.format(inData=inData, maxEvents=self.
_maxEvents, neventsInData=neventsInData, expectedEvents=expectedEvents))
1068 msg.debug(
'Expected number of processed events for {0} is {1}'.format(inData, expectedEvents))
1072 if not isinstance(neventsOutData, int):
1073 msg.warning(
'File size metadata for {outData} was not countable, found "{neventsOutData}". No event checks possible for this output data.'.format(outData=outData, neventsOutData=neventsOutData))
1077 outDataKey = outData
1081 for outDataKey, outDataConf
in self.
_eventCountConf[inDataKey].items():
1082 if fnmatch.fnmatch(outData, outDataKey):
1083 msg.info(
'Matched output data type {outData} to {outDatakey} by globbing'.format(outData=outData, outDatakey=outDataKey))
1084 outDataKey = outData
1085 checkConf = outDataConf
1088 msg.warning(
'No defined event count match for {inData} -> {outData}, so no check possible in this case.'.format(inData=inData, outData=outData))
1090 msg.debug(
'Event count check for {inData} to {outData} is {checkConf}'.format(inData=inData, outData=outData, checkConf=checkConf))
1093 if checkConf ==
'match':
1095 if neventsOutData == expectedEvents:
1096 msg.info(
"Event count check for {inData} to {outData} passed: all processed events found ({neventsOutData} output events)".format(inData=inData, outData=outData, neventsOutData=neventsOutData))
1099 'Event count check for {inData} to {outData} failed: found {neventsOutData} events, expected {expectedEvents}'.format(inData=inData, outData=outData, neventsOutData=neventsOutData, expectedEvents=expectedEvents))
1100 elif checkConf ==
'filter':
1101 if neventsOutData <= expectedEvents
and neventsOutData >= 0:
1102 msg.info(
"Event count check for {inData} to {outData} passed: found ({neventsOutData} output events selected from {expectedEvents} processed events)".format(inData=inData, outData=outData, neventsOutData=neventsOutData, expectedEvents=expectedEvents))
1105 'Event count check for {inData} to {outData} failed: found {neventsOutData} events, expected from 0 to {expectedEvents}'.format(inData=inData, outData=outData, neventsOutData=neventsOutData, expectedEvents=expectedEvents))
1106 elif checkConf ==
'minEff':
1107 if neventsOutData >= int(expectedEvents * self.
_evAccEff)
and neventsOutData <= expectedEvents:
1108 msg.info(
"Event count check for {inData} to {outData} passed: found ({neventsOutData} output events selected from {expectedEvents} processed events)".format(inData=inData, outData=outData, neventsOutData=neventsOutData, expectedEvents=expectedEvents))
1111 'Event count check for {inData} to {outData} failed: found {neventsOutData} events, expected from {minEvents} to {expectedEvents}'.format(inData=inData, outData=outData, neventsOutData=neventsOutData,
1112 minEvents=int(expectedEvents * self.
_evAccEff), expectedEvents=expectedEvents))
1113 elif isinstance(checkConf, (float, int)):
1114 checkConf = float(checkConf)
1115 if checkConf < 0.0
or checkConf > 1.0:
1117 'Event count check for {inData} to {outData} is misconfigured: the efficiency factor of {eff} is not between 0 and 1.'.format(inData=inData, outData=outData, eff=checkConf))
1118 if neventsOutData >= int(expectedEvents * checkConf)
and neventsOutData <= expectedEvents:
1119 msg.info(
"Event count check for {inData} to {outData} passed: found ({neventsOutData} output events selected from {expectedEvents} processed events)".format(inData=inData, outData=outData, neventsOutData=neventsOutData, expectedEvents=expectedEvents))
1122 'Event count check for {inData} to {outData} failed: found {neventsOutData} events, expected from {minEvents} to {expectedEvents}'.format(inData=inData, outData=outData, neventsOutData=neventsOutData,
1123 minEvents=int(expectedEvents * checkConf), expectedEvents=expectedEvents))
1126 'Unrecognised event count configuration for {inData} to {outData}: "{conf}" is not known'.format(inData=inData, outData=outData, conf=checkConf))
void clear()
Empty the pool.
JobGroup: a set of Job objects and pieces of information relevant to a given set of Job objects.
Job: a set of pieces of information relevant to a given work function.
ParallelJobProcessor: a multiple-process processor of Job objects.
Logfile suitable for scanning logfiles with an athena flavour, i.e., lines of the form "SERVICE LOGL...
firstError(self, floor='ERROR')
Return the first error found in the logfile above a certain loglevel.
rootSysErrorParser(self, lineGenerator, firstline, firstLineCount)
dbMonitor(self)
Return data volume and time spend to retrieve information from the database.
__init__(self, logfile, substepName=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'], ignoreList=None)
Class constructor.
badAllocExceptionParser(self, lineGenerator, firstline, firstLineCount)
knowledgeFileHandler(self, knowledgefile)
Generally, a knowledge file consists of non-standard logging error/abnormal lines which are left out ...
moreDetails(self, log, firstline, firstLineCount, knowledgeFile, offset=0)
scanLogFile(self, resetReport=False)
g494ExceptionParser(self, lineGenerator, firstline, firstLineCount)
worstError(self)
Return the worst error found in the logfile (first error of the most serious type).
pythonExceptionParser(self, log, lineGenerator, firstline, firstLineCount)
coreDumpSvcParser(self, log, lineGenerator, firstline, firstLineCount)
Attempt to suck a core dump report from the current logfile This function scans logs in two different...
g4ExceptionParser(self, lineGenerator, firstline, firstLineCount, g4ExceptionLineDepth)
Small class used for vailiadating event counts between input and output files.
__init__(self, executor, eventCountConf=None, eventCountConfOverwrite=False)
check in- and output event counts
decide(self)
Perform an event count check.
configureCheck(self, override=False)
Setup the parameters needed to define particular checks.
Class of patterns that can be ignored from athena logfiles.
_initialiseSerches(self, searchStrings=[])
__init__(self, files=['atlas_error_mask.db'], extraSearch=[])
Load error patterns from files.
_initalisePatterns(self, files)
A class holding report information from scanning a logfile This is pretty much a virtual class,...
__init__(self, logfile=None, msgLimit=10, msgDetailLevel=stdLogLevels['ERROR'])
scanLogFile(self, resetReport=False)
__init__(self, logfile=None, msgLimit=200, msgDetailLevel=stdLogLevels['ERROR'])
rootSysErrorParser(self, line, lineCounter)
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
std::vector< std::string > split(const std::string &s, const std::string &t=":")
bool match(std::string s1, std::string s2)
match the individual directories of two strings
performStandardFileValidation(dictionary, io, parallelMode=False, multithreadedMode=False)
perform standard file validation @ detail This method performs standard file validation in either ser...
returnIntegrityOfFile(file, functionName, **kwargs)
return integrity of file using appropriate validation function @ detail This method returns the integ...