1#!/usr/bin/env python
2
3# Copyright (c) 2014 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# This file defines script for getting entries from ES concerning reboot time.
8
9"""
10Example usage:
11    python analyze_reboot_time.py -l 12 --server cautotest --board daisy_spring
12
13Usage: analyze_reboot_time.py [-h] [-l LAST] --server AUTOTEST_SERVER
14                              [--board BOARD] [--pool POOL] [--start START]
15                              [--end END] [--gte GTE] [--lte LTE] [-n SIZE]
16                              [--hosts HOSTS [HOSTS ...]]
17
18optional arguments:
19  -h, --help            show this help message and exit
20  -l LAST               last hours to search results across
21  --server AUTOTEST_SERVER
22                        Enter Autotest instance name, e.g. "cautotest".
23  --board BOARD         restrict query by board, not implemented yet
24  --pool POOL           restrict query by pool, not implemented yet
25  --start START         Enter start time as: yyyy-mm-dd hh-mm-ss,defualts to
26                        24h ago.
27  --end END             Enter end time as: yyyy-mm-dd hh-mm-ss,defualts to
28                        current time.
29  --gte GTE             Enter lower bound on reboot time for entries to
30                        return.
31  --lte LTE             Enter upper bound on reboot time for entries to
32                        return.
33  -n SIZE               Maximum number of entries to return.
34  --hosts HOSTS [HOSTS ...]
35                        Enter space deliminated hostnames
36"""
37
38import argparse
39import time
40
41import common
42import host_history
43from autotest_lib.client.common_lib import time_utils
44from autotest_lib.client.common_lib.cros.graphite import autotest_es
45
46
47def get_entries(time_start, time_end, gte, lte, size, index, hostname):
48    """Gets all entries from es db with the given constraints.
49
50    @param time_start: Earliest time entry was recorded
51    @param time_end: Latest time entry was recorded
52    @param gte: Lowest reboot_time to return
53    @param lte: Highest reboot_time to return
54    @param size: Max number of entries to return
55    @param index: es db index to get entries for, i.e. 'cautotest'
56    @param hostname: string representing hostname to query for
57    @returns: Entries from esdb.
58    """
59    time_start_epoch = time_utils.to_epoch_time(time_start)
60    time_end_epoch = time_utils.to_epoch_time(time_end)
61    gte_epoch = time_utils.to_epoch_time(gte)
62    lte_epoch = time_utils.to_epoch_time(lte)
63    return autotest_es.query(
64        index=index,
65        fields_returned=['hostname', 'time_recorded', 'value'],
66        equality_constraints=[('_type', 'reboot_total'),
67                              ('hostname', hostname)],
68        range_constraints=[('time_recorded', time_start_epoch, time_end_epoch),
69                           ('value', gte_epoch, lte_epoch)],
70        size=size,
71        sort_specs=[{'hostname': 'asc'}, {'value': 'desc'}])
72    return results
73
74
75def get_results_string(hostname, time_start, time_end, results):
76    """Prints entries from esdb in a readable fashion.
77
78    @param hostname: Hostname of DUT we are printing result for.
79    @param time_start: Earliest time entry was recorded
80    @param time_end: Latest time entry was recorded
81    @param gte: Lowest reboot_time to return
82    @param lte: Highest reboot_time to return
83    @param size: Max number of entries to return
84    @returns: String reporting reboot times for this host.
85    """
86    return_string = ' Host: %s \n   Number of entries: %s \n' % (
87            hostname, results.total)
88    return_string += ' %s - %s \n' % (
89            time_utils.epoch_time_to_date_string(time_start),
90            time_utils.epoch_time_to_date_string(time_end))
91    if results.total <= 0:
92        return return_string
93    for result in results.hits:
94        time_recorded = result['time_recorded'][0]
95        time_string = time_utils.epoch_time_to_date_string(
96                time_recorded)
97        reboot_total = result['value'][0]
98        spaces = (15 - len(str(time_string))) * ' '
99        return_string += '    %s  Reboot_time:  %.3fs\n' % (
100                time_string, reboot_total)
101    return return_string
102
103
104if __name__ == '__main__':
105    """main script"""
106    t_now = time.time()
107    t_now_minus_one_day = t_now - 3600 * 24
108    parser = argparse.ArgumentParser()
109    parser.add_argument('-l', type=float, dest='last',
110                        help='last hours to search results across',
111                        default=24)
112    parser.add_argument('--server', type=str, dest='autotest_server',
113                        required=True,
114                        help='Enter Autotest instance name, e.g. "cautotest".')
115    parser.add_argument('--board', type=str, dest='board',
116                        help='restrict query by board, not implemented yet',
117                        default=None)
118    parser.add_argument('--pool', type=str, dest='pool',
119                        help='restrict query by pool, not implemented yet',
120                        default=None)
121    parser.add_argument('--start', type=str, dest='start',
122                        help=('Enter start time as: yyyy-mm-dd hh-mm-ss,'
123                              'defualts to 24h ago.'),
124                        default=t_now_minus_one_day)
125    parser.add_argument('--end', type=str, dest='end',
126                        help=('Enter end time as: yyyy-mm-dd hh-mm-ss,'
127                              'defualts to current time.'),
128                        default=t_now)
129    parser.add_argument('--gte', type=float, dest='gte',
130                        help=('Enter lower bound on reboot time '
131                              'for entries to return.'),
132                        default=0)
133    parser.add_argument('--lte', type=float, dest='lte',
134                        help=('Enter upper bound on reboot time '
135                              'for entries to return.'),
136                        default=None)
137    parser.add_argument('-n', type=int, dest='size',
138                        help='Maximum number of entries to return.',
139                        default=10000)
140    parser.add_argument('--hosts', nargs='+', dest='hosts',
141                        help='Enter space deliminated hostnames',
142                        default=[])
143    options = parser.parse_args()
144
145    if options.last:
146        t_start = t_now - 3600 * options.last
147        t_end = t_now
148    else:
149        t_start = time_utils.to_epoch_time(options.start)
150        t_end = time_utils.to_epoch_time(options.end)
151    if options.hosts:
152        hosts = options.hosts
153    else:
154        hosts = host_history.get_matched_hosts(options.autotest_server,
155                                               options.board, options.pool)
156
157    for hostname in hosts:
158        results = get_entries(
159                t_start, t_end, options.gte, options.lte, options.size,
160                options.autotest_server, hostname)
161        print get_results_string(hostname, t_start, t_end, results)
162