blob: dee96efff6668282dd3a709c7d5634f039c9a19c [file] [log] [blame]
Paul Stewartd956fa22011-05-23 13:11:06 -07001#!/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'))
Paul Stewartca77b112011-06-22 13:01:15 -070051 return float('%d.%s' % (int_time, re.split('[+-]', fraction)[0]))
Paul Stewartd956fa22011-05-23 13:11:06 -070052
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)