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.
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
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.
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
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')
54 title
= self
.page
.display_name
55 trace_data
.Serialize(tf
.name
, trace_title
=title
)
56 return file_handle
.FromFilePath(tf
.name
)
60 page_name
= self
.page
.display_name
63 return 'TraceValue(%s, %s)' % (page_name
, self
.name
)
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.
71 if self
._temp
_file
is None:
73 os
.remove(self
._temp
_file
.GetAbsPath())
74 self
._temp
_file
= None
79 def __exit__(self
, _
, __
, ___
):
84 return self
._temp
_file
is None
88 return self
._temp
_file
.GetAbsPath()
90 def GetBuildbotDataType(self
, output_context
):
93 def GetBuildbotValue(self
):
96 def GetRepresentativeNumber(self
):
99 def GetRepresentativeString(self
):
103 def GetJSONTypeName():
107 def MergeLikeValuesFromSamePage(cls
, values
):
108 assert len(values
) > 0
112 def MergeLikeValuesFromDifferentPages(cls
, values
):
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
122 d
['cloud_url'] = self
._cloud
_url
125 def Serialize(self
, dir_path
):
126 if self
._temp
_file
is None:
127 raise ValueError('Tried to serialize nonexistent trace.')
129 file_name
= self
.page
.file_safe_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.')
144 if self
._serialized
_file
_handle
:
145 fh
= self
._serialized
_file
_handle
148 remote_path
= ('trace-file-id_%s-%s-%d%s' % (
150 datetime
.datetime
.now().strftime('%Y-%m-%d_%H-%M-%S'),
151 random
.randint(1, 100000),
153 self
._cloud
_url
= cloud_storage
.Insert(
154 bucket
, remote_path
, fh
.GetAbsPath())
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
)