github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/experiment/parse_build_log.py (about) 1 #!/usr/bin/python 2 3 # Copyright 2018 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """Parser for e2e test logs. 18 19 Useful for finding which tests overlapped with a certain event. 20 """ 21 22 import argparse 23 import datetime 24 import re 25 26 27 _LINE_RE = re.compile(r'^[IWE]111[45] \d\d:\d\d:\d\d\.\d\d\d\] ?(.*)') 28 _DATE_FORMAT = '%Y-%m-%d %H:%M:%S' 29 _CURRENT_YEAR = datetime.datetime.utcnow().year 30 31 32 class TestOutput(object): 33 def __init__(self): 34 self._lines = [] 35 self._start = None 36 self._end = None 37 self._it = None 38 39 def append(self, line): 40 self._lines.append(line) 41 try: 42 timestamp = datetime.datetime.strptime(line[:19], '%b %d %H:%M:%S.%f').replace( 43 year=_CURRENT_YEAR) 44 except: # pylint: disable=bare-except 45 pass 46 else: 47 if not self._start: 48 self._start = timestamp 49 self._end = timestamp 50 if line.startswith('[It] '): 51 self._it = line 52 if line.startswith('[BeforeEach] ') and not self._it: 53 self._it = line 54 55 def overlaps(self, after, before): 56 if self._end and after and self._end < after: 57 return False 58 if self._start and before and self._start > before: 59 return False 60 return True 61 62 def __len__(self): 63 return len(self._lines) 64 65 def __str__(self): 66 if not self._lines: 67 return '<empty>' 68 return 'Test %s->%s (%5d lines) %s' % ( 69 self._start, self._end, len(self), self._it if self._it else '') 70 71 72 def _get_tests(log): 73 current_test = TestOutput() 74 for line in log: 75 line = line.rstrip() 76 match = _LINE_RE.match(line) 77 if not match: 78 raise Exception('line %s does not match' % line) 79 if '------------------------------' in line: 80 ended_test = current_test 81 current_test = TestOutput() 82 if len(ended_test) <= 1: 83 continue 84 else: 85 yield ended_test 86 else: 87 current_test.append(match.group(1)) 88 yield current_test 89 90 91 def main(): 92 parser = argparse.ArgumentParser(description=__doc__) 93 parser.add_argument('--log_year', default=_CURRENT_YEAR, 94 help=('Year in which the log was created. ' 95 'Needed because the year is omitted in the log.')) 96 parser.add_argument('--after', 97 help=('Show tests which ended at or after this time ' 98 '(format: %s).' % _DATE_FORMAT.replace('%', '%%'))) 99 parser.add_argument('--before', 100 help=('Show tests which started at or before this time ' 101 '(format: %s).' % _DATE_FORMAT.replace('%', '%%'))) 102 parser.add_argument('file') 103 104 args = parser.parse_args() 105 after = datetime.datetime.strptime(args.after, _DATE_FORMAT) if args.after else None 106 before = datetime.datetime.strptime(args.before, _DATE_FORMAT) if args.before else None 107 if after and before and after.year != before.year: 108 raise Exception('Logs spanning year boundary are not supported.') 109 if not args.log_year and (after or before): 110 year = after.year if after else before.year 111 if year != _CURRENT_YEAR: 112 raise Exception('Please explicitly specify the year in which the log was created.') 113 with open(args.file) as log: 114 for test in _get_tests(log): 115 if test.overlaps(after, before): 116 print str(test) 117 118 119 if __name__ == '__main__': 120 main()