1#!/usr/bin/python 2 3# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7""" Return the time difference between two logfile entries 8""" 9 10import logging 11import optparse 12import os 13import re 14import sys 15import time 16 17logger = logging.getLogger('log_time_diff') 18handler = logging.StreamHandler(file('/dev/stderr', 'w')) 19formatter = logging.Formatter('\tlog_time_diff: %(levelname)s\t%(message)s') 20handler.setFormatter(formatter) 21logger.addHandler(handler) 22 23 24class StampParser(object): 25 saved_msgs = '/var/tmp/messages.autotest_start' 26 def __init__(self, from_str, to_str, start = None): 27 self.from_re = re.compile(from_str) 28 self.to_re = re.compile(to_str) 29 self.start_line = None 30 self.end_line = None 31 if start: 32 self.start = self.syslog_to_float(start) 33 else: 34 if os.path.exists(self.saved_msgs): 35 for line in file(self.saved_msgs): 36 pass 37 self.start = self.syslog_to_float(line.split(' ')[0]) 38 39 def parse_file(self, filename): 40 for line in file(filename): 41 if self.from_re.search(line): 42 self.end_line = None 43 self.start_line = line 44 if self.to_re.search(line): 45 self.end_line = line 46 47 def syslog_to_float(self, syslog_time): 48 # Lines end up like 2011-05-13T07:38:05.238129-07:00 ... 49 date, sep, fraction = syslog_time.partition('.') 50 int_time = time.mktime(time.strptime(date, '%Y-%m-%dT%H:%M:%S')) 51 return float('%d.%s' % (int_time, re.split('[+-]', fraction)[0])) 52 53 def results(self): 54 if not self.start_line or not self.end_line: 55 logger.error('Could not find strings in file') 56 return '-' 57 58 logger.debug('Start line: %s', self.start_line) 59 logger.debug('End line: %s', self.end_line) 60 61 syslog_from = self.start_line.split(' ')[0] 62 syslog_from_time = self.syslog_to_float(syslog_from) 63 if self.start and syslog_from_time < self.start: 64 logger.error('Search string only appears before start time!') 65 return '-' 66 67 from_match = re.search('kernel:\s*\[\s*([0-9.]*)', self.start_line) 68 to_match = re.search('kernel:\s*\[\s*([0-9.]*)', self.end_line) 69 if from_match and to_match: 70 # Lines end up like <syslog time> host kernel: [1307112.080338] ... 71 logger.info('Using kernel timestamp %s %s' % 72 (from_match.group(1), to_match.group(1))) 73 from_time = float(from_match.group(1)) 74 to_time = float(to_match.group(1)) 75 else: 76 syslog_to = self.end_line.split(' ')[0] 77 logger.info('Using syslog timestamp %s %s' % 78 (syslog_from, syslog_to)) 79 from_time = syslog_from_time 80 to_time = self.syslog_to_float(syslog_to) 81 return (to_time - from_time) 82 83 84def main(argv): 85 parser = optparse.OptionParser('Usage: %prog [options...]') 86 parser.add_option('--from', dest='from_str', 87 help='First regexp to search for') 88 parser.add_option('--to', dest='to_str', 89 help='Second regexp to search for') 90 parser.add_option('--file', dest='file', default='/var/log/messages', 91 help='File to search for regexps in') 92 parser.add_option('--no-rotate', dest='no_rotate', action='store_true', 93 help='Do not search in file.1 for the same expression') 94 parser.add_option('--start', dest='start', 95 help='Do not accept events that start before this time') 96 parser.add_option('--debug', dest='debug', action='store_true', 97 help='Show extra verbose messages') 98 (options, args) = parser.parse_args(argv[1:]) 99 100 if not options.from_str or not options.to_str: 101 parser.error('Required arguments: --from=<from_re> --to=<to_re>') 102 103 104 if options.debug: 105 logger.setLevel(logging.DEBUG) 106 else: 107 logger.setLevel(logging.INFO) 108 109 parser = StampParser(options.from_str, options.to_str, options.start) 110 111 # If file rotation is enabled, try to parse previous file 112 if not options.no_rotate: 113 rotate_file = '%s.1' % options.file 114 if os.path.exists(rotate_file): 115 parser.parse_file(rotate_file) 116 117 parser.parse_file(options.file) 118 print parser.results() 119 120if __name__ == '__main__': 121 main(sys.argv) 122