Update sdk/platform-tools to version 26.0.0.
[android_tools.git] / sdk / platform-tools / systrace / catapult / telemetry / telemetry / value / trace.py
blobb6b756dd4648508499f1c9056d5b737f858beb4a
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
3 # found in the LICENSE file.
5 import datetime
6 import logging
7 import os
8 import random
9 import shutil
10 import sys
11 import tempfile
13 from py_utils import cloud_storage # pylint: disable=import-error
15 from telemetry.internal.util import file_handle
16 from telemetry.timeline import trace_data as trace_data_module
17 from telemetry import value as value_module
18 from tracing.trace_data import trace_data as trace_data_module
21 class TraceValue(value_module.Value):
22 def __init__(self, page, trace_data, important=False, description=None):
23 """A value that contains a TraceData object and knows how to
24 output it.
26 Adding TraceValues and outputting as JSON will produce a directory full of
27 HTML files called trace_files. Outputting as chart JSON will also produce
28 an index, files.html, linking to each of these files.
29 """
30 super(TraceValue, self).__init__(
31 page, name='trace', units='', important=important,
32 description=description, tir_label=None, grouping_keys=None)
33 self._temp_file = self._GetTempFileHandle(trace_data)
34 self._cloud_url = None
35 self._serialized_file_handle = None
37 @property
38 def value(self):
39 if self._cloud_url:
40 return self._cloud_url
41 elif self._serialized_file_handle:
42 return self._serialized_file_handle.GetAbsPath()
44 def _GetTraceParts(self, trace_data):
45 return [(trace_data.GetTracesFor(p), p)
46 for p in trace_data_module.ALL_TRACE_PARTS
47 if trace_data.HasTracesFor(p)]
49 def _GetTempFileHandle(self, trace_data):
50 tf = tempfile.NamedTemporaryFile(delete=False, suffix='.html')
51 tf.close()
52 title = ''
53 if self.page:
54 title = self.page.display_name
55 trace_data.Serialize(tf.name, trace_title=title)
56 return file_handle.FromFilePath(tf.name)
58 def __repr__(self):
59 if self.page:
60 page_name = self.page.display_name
61 else:
62 page_name = 'None'
63 return 'TraceValue(%s, %s)' % (page_name, self.name)
65 def CleanUp(self):
66 """Cleans up tempfile after it is no longer needed.
68 A cleaned up TraceValue cannot be used for further operations. CleanUp()
69 may be called more than once without error.
70 """
71 if self._temp_file is None:
72 return
73 os.remove(self._temp_file.GetAbsPath())
74 self._temp_file = None
76 def __enter__(self):
77 return self
79 def __exit__(self, _, __, ___):
80 self.CleanUp()
82 @property
83 def cleaned_up(self):
84 return self._temp_file is None
86 @property
87 def filename(self):
88 return self._temp_file.GetAbsPath()
90 def GetBuildbotDataType(self, output_context):
91 return None
93 def GetBuildbotValue(self):
94 return None
96 def GetRepresentativeNumber(self):
97 return None
99 def GetRepresentativeString(self):
100 return None
102 @staticmethod
103 def GetJSONTypeName():
104 return 'trace'
106 @classmethod
107 def MergeLikeValuesFromSamePage(cls, values):
108 assert len(values) > 0
109 return values[0]
111 @classmethod
112 def MergeLikeValuesFromDifferentPages(cls, values):
113 return None
115 def AsDict(self):
116 if self._temp_file is None:
117 raise ValueError('Tried to serialize TraceValue without tempfile.')
118 d = super(TraceValue, self).AsDict()
119 if self._serialized_file_handle:
120 d['file_id'] = self._serialized_file_handle.id
121 if self._cloud_url:
122 d['cloud_url'] = self._cloud_url
123 return d
125 def Serialize(self, dir_path):
126 if self._temp_file is None:
127 raise ValueError('Tried to serialize nonexistent trace.')
128 if self.page:
129 file_name = self.page.file_safe_name
130 else:
131 file_name = ''
132 file_name += str(self._temp_file.id)
133 file_name += datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
134 file_name += self._temp_file.extension
135 file_path = os.path.abspath(os.path.join(dir_path, file_name))
136 shutil.copy(self._temp_file.GetAbsPath(), file_path)
137 self._serialized_file_handle = file_handle.FromFilePath(file_path)
138 return self._serialized_file_handle
140 def UploadToCloud(self, bucket):
141 if self._temp_file is None:
142 raise ValueError('Tried to upload nonexistent trace to Cloud Storage.')
143 try:
144 if self._serialized_file_handle:
145 fh = self._serialized_file_handle
146 else:
147 fh = self._temp_file
148 remote_path = ('trace-file-id_%s-%s-%d%s' % (
149 fh.id,
150 datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S'),
151 random.randint(1, 100000),
152 fh.extension))
153 self._cloud_url = cloud_storage.Insert(
154 bucket, remote_path, fh.GetAbsPath())
155 sys.stderr.write(
156 'View generated trace files online at %s for page %s\n' %
157 (self._cloud_url, self.page.url if self.page else 'unknown'))
158 return self._cloud_url
159 except cloud_storage.PermissionError as e:
160 logging.error('Cannot upload trace files to cloud storage due to '
161 ' permission error: %s' % e.message)