OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 | |
3 """ | |
4 Launches a daemon to monitor the devices' temperatures by | |
5 uploading them to monarch every 30 seconds. | |
6 """ | |
7 | |
8 import json | |
9 import logging | |
10 import os | |
11 import optparse | |
12 import re | |
13 import signal | |
14 import subprocess | |
15 import sys | |
16 import time | |
17 | |
18 # Common name of sensor found in nexus devices to measure cpu (core0) temp | |
19 _CPU_TEMP_SENSOR = 'tsens_tz_sensor0' | |
20 | |
21 # Location of the infra-python package's run script | |
22 _RUN_PY = '/opt/infra-python/run.py' | |
luqui
2015/09/03 01:10:41
We can't rely on this location. Probably have to
bpastene
2015/09/04 03:47:21
Per offline discussion with Luke, resolving this w
| |
23 | |
24 class SigtermError(Exception): | |
25 """Exception used to catch a sigterm.""" | |
26 pass | |
27 | |
28 def main(adb_path, | |
29 devices_json, | |
30 metric_prefix="android_device", | |
31 pid_file_path='/tmp/device_monitor_pid'): | |
32 """Polls the devices for their battery and cpu temperatures | |
33 every 30 seconds and uploads them to monarch through infra's | |
34 ts_mon. Fully qualified, the metric names would be | |
35 /chrome/infra/${metric_prefix}/${device_serial}/(battery|cpu)_temp | |
36 | |
37 Args: | |
38 adb_path: Path to adb binary | |
39 devices_json: Json list of device serials to poll | |
40 metric_prefix: Prefix of the metric name. | |
41 pid_file_path: Path to the file to write the pid to | |
42 """ | |
43 | |
44 def SigtermHandler(_signum, _unused_frame): | |
45 raise SigtermError() | |
46 signal.signal(signal.SIGTERM, SigtermHandler) | |
47 | |
48 if pid_file_path: | |
luqui
2015/09/03 01:10:41
This whole block and the kill script have nothing
bpastene
2015/09/03 17:36:00
I was trying to emulate the style of the one scrip
bpastene
2015/09/04 03:47:21
Uploaded a cl for the changes to daemonizer here:
| |
49 # If an old monitor is still running, kill it. Its list of | |
50 # devices to poll might be outdated | |
51 try: | |
52 with open(pid_file_path, 'r') as pid_file: | |
53 monitor_pid = int(pid_file.readline()) | |
54 os.kill(monitor_pid, signal.SIGTERM) | |
55 except (IOError, OSError, ValueError): | |
56 logging.exception("Unable to kill old monitoring process") | |
57 try: | |
58 with open(pid_file_path, 'w+') as pid_file: | |
59 pid_file.write('%s' % str(os.getpid())) | |
60 except (IOError): | |
61 logging.exception("Unable to write pid to file") | |
62 | |
63 devices = json.loads(devices_json) | |
64 try: | |
65 while True: | |
66 upload_cmd_args = [] | |
67 for device in devices: | |
68 bat_temp = None | |
69 cpu_temp = None | |
70 # Search for the file that the _CPU_TEMP_SENSOR dumps to and cat it | |
71 cmd = [adb_path, '-s', device, 'shell', | |
72 'grep "%s" /sys/class/thermal/thermal_zone*/type -l' | |
luqui
2015/09/03 01:10:41
Stylistically I usually see options first: grep -l
jbudorick
2015/09/03 17:37:31
Is this true across all Nexus devices, or just spe
bpastene
2015/09/04 03:47:21
I'm not sure. All the devices I've come across on
bpastene
2015/09/04 03:47:21
Done.
| |
73 % (_CPU_TEMP_SENSOR)] | |
74 try: | |
75 cpu_temp_files = subprocess.check_output(cmd) | |
76 if (len(cpu_temp_files.splitlines()) == 1): | |
77 cpu_temp_file = cpu_temp_files.strip()[:-4] + "temp" | |
luqui
2015/09/03 01:10:41
This is opaque. Can you use re.sub() instead so I
bpastene
2015/09/04 03:47:21
Done.
| |
78 cmd = [adb_path, '-s', device, 'shell', | |
jbudorick
2015/09/03 17:37:31
Someday I will get infra to use something other th
| |
79 'cat %s' % (cpu_temp_file)] | |
80 file_contents = subprocess.check_output(cmd) | |
81 cpu_temp = int(file_contents) | |
82 except (subprocess.CalledProcessError, TypeError, ValueError): | |
83 cpu_temp = None | |
84 | |
85 # Dump system battery info and grab the temp | |
jbudorick
2015/09/03 17:37:31
and as an added bonus, you'd get this for free: ht
| |
86 cmd = [adb_path, '-s', device, 'shell', 'dumpsys battery'] | |
87 try: | |
88 battery_info = subprocess.check_output(cmd) | |
89 for line in battery_info.splitlines(): | |
90 m = re.match('^\s*temperature: ([0-9]+)\s*$', line) | |
91 if m: | |
92 bat_temp = int(m.group(1)) | |
93 except (subprocess.CalledProcessError, TypeError, ValueError): | |
94 bat_temp = None | |
95 | |
96 cpu_dict = {'name': "%s/%s/cpu_temp" % (metric_prefix, device), | |
97 'value': cpu_temp} | |
98 cpu_temp_args = ['--float', json.dumps(cpu_dict)] if cpu_temp else [] | |
99 battery_dict = {'name': '%s/%s/battery_temp' % (metric_prefix, | |
100 device), 'value': bat_temp} | |
101 bat_temp_args = ['--float', | |
102 json.dumps(battery_dict)] if bat_temp else [] | |
103 upload_cmd_args = upload_cmd_args + cpu_temp_args + bat_temp_args | |
luqui
2015/09/03 01:10:41
+=
It took me a while to realize the point of thi
bpastene
2015/09/04 03:47:21
Done.
| |
104 | |
105 cmd = [_RUN_PY, 'infra.tools.send_ts_mon_values'] + upload_cmd_args | |
106 try: | |
107 subprocess.Popen(cmd) | |
108 except OSError: | |
109 logging.exception('Unable to call %s', _RUN_PY) | |
110 | |
111 time.sleep(30) | |
112 except SigtermError: | |
113 logging.info("Got a SIGTERM, shutting down") | |
114 except: # pylint: disable=bare-except | |
115 logging.exception('Unexpected exception in main.') | |
116 | |
117 if __name__ == '__main__': | |
118 sys.exit(main(*sys.argv[1:])) | |
OLD | NEW |