analyze_reboot_time.py revision b1d6c73d8cbc45d04591453f8b80cb744017ddf9
1b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang#!/usr/bin/env python
2b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
3b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
4b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang# Use of this source code is governed by a BSD-style license that can be
5b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang# found in the LICENSE file.
6b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
7b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang# This file defines script for getting entries from ES concerning reboot time.
8b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
9b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang"""
10b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael LiangExample usage:
11b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    python analyze_reboot_time.py -l 12 --server cautotest --board daisy_spring
12b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
13b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael LiangUsage: analyze_reboot_time.py [-h] [-l LAST] --server AUTOTEST_SERVER
14b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              [--board BOARD] [--pool POOL] [--start START]
15b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              [--end END] [--gte GTE] [--lte LTE] [-n SIZE]
16b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              [--hosts HOSTS [HOSTS ...]]
17b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
18b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangoptional arguments:
19b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  -h, --help            show this help message and exit
20b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  -l LAST               last hours to search results across
21b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --server AUTOTEST_SERVER
22b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        Enter Autotest instance name, e.g. "cautotest".
23b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --board BOARD         restrict query by board, not implemented yet
24b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --pool POOL           restrict query by pool, not implemented yet
25b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --start START         Enter start time as: yyyy-mm-dd hh-mm-ss,defualts to
26b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        24h ago.
27b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --end END             Enter end time as: yyyy-mm-dd hh-mm-ss,defualts to
28b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        current time.
29b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --gte GTE             Enter lower bound on reboot time for entries to
30b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        return.
31b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --lte LTE             Enter upper bound on reboot time for entries to
32b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        return.
33b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  -n SIZE               Maximum number of entries to return.
34b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang  --hosts HOSTS [HOSTS ...]
35b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        Enter space deliminated hostnames
36b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang"""
37b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
38b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangimport argparse
39b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangimport datetime
40b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangimport time
41b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
42b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangimport common
43b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangimport host_history_utils
44b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangfrom autotest_lib.client.common_lib.cros.graphite import es_utils
45b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangfrom autotest_lib.server import frontend
46b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
47b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
48b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangdef should_care(board, pool, dut):
49b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """Whether we should care to print stats for this dut out
50b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
51b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    TODO: Move this to seperate file since host_history.py uses
52b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang          the same function.
53b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param board: board we want, i.e. 'daisy'
54b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param pool: pool we want, i.e. 'bvt'
55b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param dut: Host object representing DUT.
56b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @returns: True if the dut's stats should be counted.
57b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """
58b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    pool_label = 'pool:%s' % pool
59b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    board_label = 'board:%s' % board
60b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    return ((not pool or pool_label in dut.labels) and
61b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang            (not board or board_label in dut.labels))
62b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
63b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
64b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangdef get_entries(time_start, time_end, gte, lte, size, index, hostname):
65b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """Gets all entries from es db with the given constraints.
66b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
67b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param time_start: Earliest time entry was recorded
68b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param time_end: Latest time entry was recorded
69b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param gte: Lowest reboot_time to return
70b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param lte: Highest reboot_time to return
71b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param size: Max number of entries to return
72b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param index: es db index to get entries for, i.e. 'cautotest'
73b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param hostname: string representing hostname to query for
74b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @returns: Entries from esdb.
75b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """
76b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    query = es_utils.create_range_eq_query_multiple(
77b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        fields_returned=['hostname', 'time_recorded', 'value'],
78b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        equality_constraints=[('_type', 'reboot_total'),
79b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              ('hostname', hostname)],
80b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        range_constraints=[('time_recorded', time_start, time_end),
81b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                           ('value', gte, lte)],
82b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        size=size,
83b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        sort_specs=[{'hostname': 'asc'}, {'value': 'desc'}])
84b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    results = es_utils.execute_query(query, index=index,
85b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                                     host=es_utils.METADATA_ES_SERVER,
86b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                                     port=es_utils.ES_PORT)
87b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    return results
88b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
89b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
90b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangdef get_results_string(hostname, time_start, time_end, results):
91b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """Prints entries from esdb in a readable fashion.
92b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
93b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param hostname: Hostname of DUT we are printing result for.
94b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param time_start: Earliest time entry was recorded
95b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param time_end: Latest time entry was recorded
96b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param gte: Lowest reboot_time to return
97b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param lte: Highest reboot_time to return
98b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @param size: Max number of entries to return
99b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    @returns: String reporting reboot times for this host.
100b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """
101b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    num_entries = results['hits']['total']
102b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    return_string = ' Host: %s \n   Number of entries: %s \n' % (
103b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang            hostname, results['hits']['total'])
104b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    return_string += ' %s - %s \n' % (
105b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang            host_history_utils.unix_time_to_readable_date(time_start),
106b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang            host_history_utils.unix_time_to_readable_date(time_end))
107b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    if num_entries <= 0:
108b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        return return_string
109b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    for result in results['hits']['hits']:
110b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        fields = result['fields']
111b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        time_recorded = fields['time_recorded'][0]
112b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        time_string = host_history_utils.unix_time_to_readable_date(
113b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                time_recorded)
114b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        reboot_total = fields['value'][0]
115b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        spaces = (15 - len(str(time_string))) * ' '
116b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        return_string += '    %s  Reboot_time:  %.3fs\n' % (
117b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                time_string, reboot_total)
118b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    return return_string
119b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
120b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
121b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liangif __name__ == '__main__':
122b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    """main script"""
123b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    t_now = time.time()
124b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    t_now_minus_one_day = t_now - 3600 * 24
125b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser = argparse.ArgumentParser()
126b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('-l', type=float, dest='last',
127b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help='last hours to search results across',
128b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=24)
129b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--server', type=str, dest='autotest_server',
130b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        required=True,
131b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help='Enter Autotest instance name, e.g. "cautotest".')
132b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--board', type=str, dest='board',
133b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help='restrict query by board, not implemented yet',
134b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=None)
135b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--pool', type=str, dest='pool',
136b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help='restrict query by pool, not implemented yet',
137b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=None)
138b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--start', type=str, dest='start',
139b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help=('Enter start time as: yyyy-mm-dd hh-mm-ss,'
140b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              'defualts to 24h ago.'),
141b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=t_now_minus_one_day)
142b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--end', type=str, dest='end',
143b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help=('Enter end time as: yyyy-mm-dd hh-mm-ss,'
144b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              'defualts to current time.'),
145b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=t_now)
146b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--gte', type=float, dest='gte',
147b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help=('Enter lower bound on reboot time '
148b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              'for entries to return.'),
149b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=0)
150b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--lte', type=float, dest='lte',
151b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help=('Enter upper bound on reboot time '
152b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                              'for entries to return.'),
153b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=None)
154b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('-n', type=int, dest='size',
155b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help='Maximum number of entries to return.',
156b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=10000)
157b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    parser.add_argument('--hosts', nargs='+', dest='hosts',
158b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        help='Enter space deliminated hostnames',
159b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                        default=[])
160b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    options = parser.parse_args()
161b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
162b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    if options.last:
163b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        t_start = t_now - 3600 * options.last
164b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        t_end = t_now
165b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    else:
166b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        t_start = es_utils._to_epoch_time(datetime.datetime.strptime(
167b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                options.start, '%Y-%m-%d %H:%M:%S'))
168b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        t_end = es_utils._to_epoch_time(datetime.datetime.strptime(
169b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                options.end, '%Y-%m-%d %H:%M:%S'))
170b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    if options.hosts:
171b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        hosts = options.hosts
172b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    else:
173b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        hosts = []
174b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        print 'trying to get all duts...'
175b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        afe = frontend.AFE()
176b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        print 'making the query...'
177b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        duts = afe.get_hosts()
178b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        for dut in duts:
179b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang            if should_care(options.board, options.pool, dut):
180b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                hosts.append(dut.hostname)
181b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang
182b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang    for hostname in hosts:
183b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        results = get_entries(
184b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                t_start, t_end, options.gte, options.lte, options.size,
185b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang                options.autotest_server, hostname)
186b1d6c73d8cbc45d04591453f8b80cb744017ddf9Michael Liang        print get_results_string(hostname, t_start, t_end, results)
187