OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import datetime | 5 import datetime |
6 import json | |
7 import logging | 6 import logging |
8 import os | 7 import os |
9 import random | 8 import random |
10 import shutil | 9 import shutil |
11 import subprocess | |
12 import sys | 10 import sys |
13 import tempfile | 11 import tempfile |
14 | 12 |
15 from py_utils import cloud_storage # pylint: disable=import-error | 13 from py_utils import cloud_storage # pylint: disable=import-error |
16 | 14 |
17 from telemetry.internal.util import file_handle | 15 from telemetry.internal.util import file_handle |
18 from telemetry.timeline import trace_data as trace_data_module | 16 from telemetry.timeline import trace_data as trace_data_module |
19 from telemetry import value as value_module | 17 from telemetry import value as value_module |
20 | 18 |
21 _TRACE2HTML_PATH = os.path.join(os.path.dirname(__file__), '..', '..', '..', | |
22 'tracing', 'bin', 'trace2html') | |
23 | |
24 | 19 |
25 class TraceValue(value_module.Value): | 20 class TraceValue(value_module.Value): |
26 def __init__(self, page, trace_data, important=False, description=None): | 21 def __init__(self, page, trace_data, important=False, description=None): |
27 """A value that contains a TraceData object and knows how to | 22 """A value that contains a TraceData object and knows how to |
28 output it. | 23 output it. |
29 | 24 |
30 Adding TraceValues and outputting as JSON will produce a directory full of | 25 Adding TraceValues and outputting as JSON will produce a directory full of |
31 HTML files called trace_files. Outputting as chart JSON will also produce | 26 HTML files called trace_files. Outputting as chart JSON will also produce |
32 an index, files.html, linking to each of these files. | 27 an index, files.html, linking to each of these files. |
33 """ | 28 """ |
34 super(TraceValue, self).__init__( | 29 super(TraceValue, self).__init__( |
35 page, name='trace', units='', important=important, | 30 page, name='trace', units='', important=important, |
36 description=description, tir_label=None, grouping_keys=None) | 31 description=description, tir_label=None, grouping_keys=None) |
37 self._temp_file = self._GetTempFileHandle(trace_data) | 32 self._temp_file = self._GetTempFileHandle(trace_data) |
38 self._cloud_url = None | 33 self._cloud_url = None |
39 self._serialized_file_handle = None | 34 self._serialized_file_handle = None |
40 | 35 |
41 @property | 36 @property |
42 def value(self): | 37 def value(self): |
43 if self._cloud_url: | 38 if self._cloud_url: |
44 return self._cloud_url | 39 return self._cloud_url |
45 elif self._serialized_file_handle: | 40 elif self._serialized_file_handle: |
46 return self._serialized_file_handle.GetAbsPath() | 41 return self._serialized_file_handle.GetAbsPath() |
47 | 42 |
48 def _GetTraceParts(self, trace_data): | 43 def _GetTraceParts(self, trace_data): |
49 return [(trace_data.GetTracesFor(p), p) | 44 return [(trace_data.GetTracesFor(p), p) |
50 for p in trace_data_module.ALL_TRACE_PARTS | 45 for p in trace_data_module.ALL_TRACE_PARTS |
51 if trace_data.HasTracesFor(p)] | 46 if trace_data.HasTracesFor(p)] |
52 | 47 |
53 @staticmethod | |
54 def _DumpTraceToFile(trace, path): | |
55 with open(path, 'w') as fp: | |
56 if isinstance(trace, basestring): | |
57 fp.write(trace) | |
58 elif isinstance(trace, dict) or isinstance(trace, list): | |
59 json.dump(trace, fp) | |
60 else: | |
61 raise TypeError('Trace is of unknown type.') | |
62 | |
63 def _GetTempFileHandle(self, trace_data): | 48 def _GetTempFileHandle(self, trace_data): |
64 temp_dir = tempfile.mkdtemp() | 49 tf = tempfile.NamedTemporaryFile(delete=False, suffix='.html') |
65 trace_files = [] | 50 tf.close() |
66 counter = 0 | 51 title = '' |
67 try: | 52 if self.page: |
68 trace_size_data = {} | 53 title = self.page.display_name |
69 for traces_list, part in self._GetTraceParts(trace_data): | 54 trace_data.Serialize(tf.name, trace_title=title) |
70 for trace in traces_list: | 55 return file_handle.FromFilePath(tf.name) |
71 if isinstance(trace, trace_data_module.TraceFileHandle): | |
72 file_path = trace.file_path | |
73 else: | |
74 file_path = os.path.join(temp_dir, '%s.trace' % counter) | |
75 self._DumpTraceToFile(trace, file_path) | |
76 trace_size_data.setdefault(part, 0) | |
77 trace_size_data[part] += os.path.getsize(file_path) | |
78 trace_files.append(file_path) | |
79 counter += 1 | |
80 logging.info('Trace sizes in bytes: %s', trace_size_data) | |
81 tf = tempfile.NamedTemporaryFile(delete=False, suffix='.html') | |
82 tf.close() | |
83 if trace_files: | |
84 title = '' | |
85 if self.page: | |
86 title = self.page.display_name | |
87 cmd = (['python', _TRACE2HTML_PATH] + trace_files + | |
88 ['--output', tf.name] + ['--title', title]) | |
89 subprocess.check_output(cmd) | |
90 else: | |
91 logging.warning('No traces to convert to html.') | |
92 return file_handle.FromTempFile(tf) | |
93 finally: | |
94 shutil.rmtree(temp_dir) | |
95 | 56 |
96 def __repr__(self): | 57 def __repr__(self): |
97 if self.page: | 58 if self.page: |
98 page_name = self.page.display_name | 59 page_name = self.page.display_name |
99 else: | 60 else: |
100 page_name = 'None' | 61 page_name = 'None' |
101 return 'TraceValue(%s, %s)' % (page_name, self.name) | 62 return 'TraceValue(%s, %s)' % (page_name, self.name) |
102 | 63 |
103 def CleanUp(self): | 64 def CleanUp(self): |
104 """Cleans up tempfile after it is no longer needed. | 65 """Cleans up tempfile after it is no longer needed. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 fh.extension)) | 151 fh.extension)) |
191 self._cloud_url = cloud_storage.Insert( | 152 self._cloud_url = cloud_storage.Insert( |
192 bucket, remote_path, fh.GetAbsPath()) | 153 bucket, remote_path, fh.GetAbsPath()) |
193 sys.stderr.write( | 154 sys.stderr.write( |
194 'View generated trace files online at %s for page %s\n' % | 155 'View generated trace files online at %s for page %s\n' % |
195 (self._cloud_url, self.page.url if self.page else 'unknown')) | 156 (self._cloud_url, self.page.url if self.page else 'unknown')) |
196 return self._cloud_url | 157 return self._cloud_url |
197 except cloud_storage.PermissionError as e: | 158 except cloud_storage.PermissionError as e: |
198 logging.error('Cannot upload trace files to cloud storage due to ' | 159 logging.error('Cannot upload trace files to cloud storage due to ' |
199 ' permission error: %s' % e.message) | 160 ' permission error: %s' % e.message) |
OLD | NEW |