blob: 1673e2aa2b88c3b8078f28d7d2e7477ce6cfe39b [file] [log] [blame]
Allen Liec5beb32016-09-08 15:31:41 -07001# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Allen Li788d1672016-12-16 15:58:23 -08005"""Send system monitoring data to the timeseries monitoring API."""
Allen Liec5beb32016-09-08 15:31:41 -07006
7from __future__ import print_function
8
Allen Li788d1672016-12-16 15:58:23 -08009import random
10import time
Allen Liec5beb32016-09-08 15:31:41 -070011
Allen Li788d1672016-12-16 15:58:23 -080012import psutil
13
14from chromite.lib import commandline
Allen Liec5beb32016-09-08 15:31:41 -070015from chromite.lib import cros_logging as logging
Allen Li788d1672016-12-16 15:58:23 -080016from chromite.lib import metrics
17from chromite.lib import ts_mon_config
18from chromite.scripts.sysmon import puppet_metrics
19from chromite.scripts.sysmon import system_metrics
20from infra_libs.ts_mon.common import interface
Allen Liec5beb32016-09-08 15:31:41 -070021
Allen Li788d1672016-12-16 15:58:23 -080022DEFAULT_LOG_LEVEL = 'DEBUG'
23DEFAULT_INTERVAL = 60 # 1 minute
24
25logger = logging.getLogger(__name__)
26
27
28class _MainLoop(object):
29 """Main loop for sysmon."""
30
31 def __init__(self, loop_func, interval=60):
32 """Initialize instance.
33
34 Args:
35 loop_func: Function to call on each loop.
36 interval: Time between loops in seconds.
37 """
38 self._loop_func = loop_func
39 self._interval = interval
40 self._cycles = 0
41
42 def loop_once(self):
43 """Do actions for a single loop."""
44 try:
45 self._loop_func(self._cycles)
46 except Exception:
47 logger.exception('Error during loop.')
48
49 def loop_forever(self):
50 while True:
51 self.loop_once()
52 _force_sleep(self._interval)
53 self._cycles = (self._cycles + 1) % 60
54
55
56def _force_sleep(secs):
57 """Force sleep for at least the given number of seconds."""
58 now = time.time()
59 finished_time = now + secs
60 while now < finished_time:
61 remaining = finished_time - now
62 logger.debug('Sleeping for %d, %d remaining', secs, remaining)
63 time.sleep(remaining)
64 now = time.time()
65
66
67def collect_metrics(cycles):
68 system_metrics.get_uptime()
69 system_metrics.get_cpu_info()
70 system_metrics.get_disk_info()
71 system_metrics.get_mem_info()
72 system_metrics.get_net_info()
73 system_metrics.get_proc_info()
74 system_metrics.get_load_avg()
75 puppet_metrics.get_puppet_summary()
76 if cycles == 0:
77 system_metrics.get_os_info()
78 system_metrics.get_unix_time() # must be just before flush
79 metrics.Flush()
80
81
82def main():
83 parser = commandline.ArgumentParser(
84 description=__doc__,
85 default_log_level=DEFAULT_LOG_LEVEL)
86 parser.add_argument(
87 '--interval',
88 default=DEFAULT_INTERVAL, type=int,
89 help='time (in seconds) between sampling system metrics')
90 opts = parser.parse_args()
91 opts.Freeze()
92
93 # This returns a 0 value the first time it's called. Call it now and
94 # discard the return value.
95 psutil.cpu_times_percent()
96
97 # Wait a random amount of time before starting the loop in case sysmon
98 # is started at exactly the same time on all machines.
99 time.sleep(random.uniform(0, opts.interval))
100
101 # This call returns a context manager that doesn't do anything, so we
102 # ignore the return value.
103 ts_mon_config.SetupTsMonGlobalState('sysmon', auto_flush=False)
104 # The default prefix is '/chrome/infra/'.
105 interface.state.metric_name_prefix = (interface.state.metric_name_prefix
106 + 'chromeos/sysmon/')
107
108 mainloop = _MainLoop(loop_func=collect_metrics,
109 interval=opts.interval)
110 mainloop.loop_forever()
111
112
113if __name__ == '__main__':
114 main()