Index: tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py |
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py |
deleted file mode 100644 |
index b34e9c890ce4f188edca7deecad7fd59c8374fb8..0000000000000000000000000000000000000000 |
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py |
+++ /dev/null |
@@ -1,247 +0,0 @@ |
-# Copyright 2013 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-import json |
-import logging |
-import socket |
-import time |
-import traceback |
- |
-from telemetry import decorators |
-from telemetry.internal.backends.chrome_inspector import inspector_websocket |
-from telemetry.internal.backends.chrome_inspector import websocket |
-from telemetry.timeline import trace_data as trace_data_module |
- |
- |
-class TracingUnsupportedException(Exception): |
- pass |
- |
- |
-class TracingTimeoutException(Exception): |
- pass |
- |
- |
-class TracingUnrecoverableException(Exception): |
- pass |
- |
- |
-class TracingHasNotRunException(Exception): |
- pass |
- |
- |
-class TracingUnexpectedResponseException(Exception): |
- pass |
- |
- |
-class _DevToolsStreamReader(object): |
- def __init__(self, inspector_socket, stream_handle): |
- self._inspector_websocket = inspector_socket |
- self._handle = stream_handle |
- self._callback = None |
- self._data = None |
- |
- def Read(self, callback): |
- # Do not allow the instance of this class to be reused, as |
- # we only read data sequentially at the moment, so a stream |
- # can only be read once. |
- assert not self._callback |
- self._data = [] |
- self._callback = callback |
- self._ReadChunkFromStream() |
- # The below is not a typo -- queue one extra read ahead to avoid latency. |
- self._ReadChunkFromStream() |
- |
- def _ReadChunkFromStream(self): |
- # Limit max block size to avoid fragmenting memory in sock.recv(), |
- # (see https://github.com/liris/websocket-client/issues/163 for details) |
- req = {'method': 'IO.read', 'params': { |
- 'handle': self._handle, 'size': 32768}} |
- self._inspector_websocket.AsyncRequest(req, self._GotChunkFromStream) |
- |
- def _GotChunkFromStream(self, response): |
- # Quietly discard responses from reads queued ahead after EOF. |
- if self._data is None: |
- return |
- if 'error' in response: |
- raise TracingUnrecoverableException( |
- 'Reading trace failed: %s' % response['error']['message']) |
- result = response['result'] |
- self._data.append(result['data']) |
- if not result.get('eof', False): |
- self._ReadChunkFromStream() |
- return |
- req = {'method': 'IO.close', 'params': {'handle': self._handle}} |
- self._inspector_websocket.SendAndIgnoreResponse(req) |
- trace_string = ''.join(self._data) |
- self._data = None |
- self._callback(trace_string) |
- |
- |
-class TracingBackend(object): |
- |
- _TRACING_DOMAIN = 'Tracing' |
- |
- def __init__(self, inspector_socket, is_tracing_running=False): |
- self._inspector_websocket = inspector_socket |
- self._inspector_websocket.RegisterDomain( |
- self._TRACING_DOMAIN, self._NotificationHandler) |
- self._trace_events = [] |
- self._is_tracing_running = is_tracing_running |
- self._has_received_all_tracing_data = False |
- |
- @property |
- def is_tracing_running(self): |
- return self._is_tracing_running |
- |
- def StartTracing(self, trace_options, custom_categories=None, timeout=10): |
- """When first called, starts tracing, and returns True. |
- |
- If called during tracing, tracing is unchanged, and it returns False. |
- """ |
- if self.is_tracing_running: |
- return False |
- # Reset collected tracing data from previous tracing calls. |
- self._trace_events = [] |
- |
- if not self.IsTracingSupported(): |
- raise TracingUnsupportedException( |
- 'Chrome tracing not supported for this app.') |
- |
- req = { |
- 'method': 'Tracing.start', |
- 'params': { |
- 'options': trace_options.GetTraceOptionsStringForChromeDevtool(), |
- 'transferMode': 'ReturnAsStream' |
- } |
- } |
- if custom_categories: |
- req['params']['categories'] = custom_categories |
- logging.info('Start Tracing Request: %s', repr(req)) |
- self._inspector_websocket.SyncRequest(req, timeout) |
- self._is_tracing_running = True |
- return True |
- |
- def StopTracing(self, trace_data_builder, timeout=30): |
- """Stops tracing and pushes results to the supplied TraceDataBuilder. |
- |
- If this is called after tracing has been stopped, trace data from the last |
- tracing run is pushed. |
- """ |
- if not self.is_tracing_running: |
- if not self._trace_events: |
- raise TracingHasNotRunException() |
- else: |
- req = {'method': 'Tracing.end'} |
- self._inspector_websocket.SendAndIgnoreResponse(req) |
- # After Tracing.end, chrome browser will send asynchronous notifications |
- # containing trace data. This is until Tracing.tracingComplete is sent, |
- # which means there is no trace buffers pending flush. |
- self._CollectTracingData(timeout) |
- self._is_tracing_running = False |
- trace_data_builder.AddEventsTo( |
- trace_data_module.CHROME_TRACE_PART, self._trace_events) |
- |
- def DumpMemory(self, timeout=30): |
- """Dumps memory. |
- |
- Returns: |
- GUID of the generated dump if successful, None otherwise. |
- |
- Raises: |
- TracingTimeoutException: If more than |timeout| seconds has passed |
- since the last time any data is received. |
- TracingUnrecoverableException: If there is a websocket error. |
- TracingUnexpectedResponseException: If the response contains an error |
- or does not contain the expected result. |
- """ |
- request = { |
- 'method': 'Tracing.requestMemoryDump' |
- } |
- try: |
- response = self._inspector_websocket.SyncRequest(request, timeout) |
- except websocket.WebSocketTimeoutException: |
- raise TracingTimeoutException( |
- 'Exception raised while sending a Tracing.requestMemoryDump ' |
- 'request:\n' + traceback.format_exc()) |
- except (socket.error, websocket.WebSocketException, |
- inspector_websocket.WebSocketDisconnected): |
- raise TracingUnrecoverableException( |
- 'Exception raised while sending a Tracing.requestMemoryDump ' |
- 'request:\n' + traceback.format_exc()) |
- |
- |
- if ('error' in response or |
- 'result' not in response or |
- 'success' not in response['result'] or |
- 'dumpGuid' not in response['result']): |
- raise TracingUnexpectedResponseException( |
- 'Inspector returned unexpected response for ' |
- 'Tracing.requestMemoryDump:\n' + json.dumps(response, indent=2)) |
- |
- result = response['result'] |
- return result['dumpGuid'] if result['success'] else None |
- |
- def _CollectTracingData(self, timeout): |
- """Collects tracing data. Assumes that Tracing.end has already been sent. |
- |
- Args: |
- timeout: The timeout in seconds. |
- |
- Raises: |
- TracingTimeoutException: If more than |timeout| seconds has passed |
- since the last time any data is received. |
- TracingUnrecoverableException: If there is a websocket error. |
- """ |
- self._has_received_all_tracing_data = False |
- start_time = time.time() |
- while True: |
- try: |
- self._inspector_websocket.DispatchNotifications(timeout) |
- start_time = time.time() |
- except websocket.WebSocketTimeoutException: |
- pass |
- except (socket.error, websocket.WebSocketException): |
- raise TracingUnrecoverableException( |
- 'Exception raised while collecting tracing data:\n' + |
- traceback.format_exc()) |
- |
- if self._has_received_all_tracing_data: |
- break |
- |
- elapsed_time = time.time() - start_time |
- if elapsed_time > timeout: |
- raise TracingTimeoutException( |
- 'Only received partial trace data due to timeout after %s seconds. ' |
- 'If the trace data is big, you may want to increase the timeout ' |
- 'amount.' % elapsed_time) |
- |
- def _NotificationHandler(self, res): |
- if 'Tracing.dataCollected' == res.get('method'): |
- value = res.get('params', {}).get('value') |
- self._trace_events.extend(value) |
- elif 'Tracing.tracingComplete' == res.get('method'): |
- stream_handle = res.get('params', {}).get('stream') |
- if not stream_handle: |
- self._has_received_all_tracing_data = True |
- return |
- |
- if self._trace_events: |
- raise TracingUnexpectedResponseException( |
- 'Got both dataCollected events and a stream from server') |
- reader = _DevToolsStreamReader(self._inspector_websocket, stream_handle) |
- reader.Read(self._ReceivedAllTraceDataFromStream) |
- |
- def _ReceivedAllTraceDataFromStream(self, data): |
- self._trace_events = json.loads(data) |
- self._has_received_all_tracing_data = True |
- |
- def Close(self): |
- self._inspector_websocket.UnregisterDomain(self._TRACING_DOMAIN) |
- self._inspector_websocket = None |
- |
- @decorators.Cache |
- def IsTracingSupported(self): |
- req = {'method': 'Tracing.hasCompleted'} |
- res = self._inspector_websocket.SyncRequest(req) |
- return not res.get('response') |