| Index: tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_devtools_tracing_backend.py
|
| diff --git a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_devtools_tracing_backend.py b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_devtools_tracing_backend.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b1345ad91e5d5f973e2c1a025e19b5b8f2877fab
|
| --- /dev/null
|
| +++ b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_devtools_tracing_backend.py
|
| @@ -0,0 +1,114 @@
|
| +# Copyright 2014 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 sys
|
| +import traceback
|
| +
|
| +
|
| +class ChromeTracingStartedError(Exception):
|
| + pass
|
| +
|
| +
|
| +class ChromeTracingStoppedError(Exception):
|
| + pass
|
| +
|
| +
|
| +class ChromeDevtoolsTracingBackend(object):
|
| + # A singleton map from platform backends to maps of uniquely-identifying
|
| + # remote port (which may be the same as local port) to DevToolsClientBackend.
|
| + # There is no guarantee that the devtools agent is still alive.
|
| + _platform_backends_to_devtools_clients_maps = {}
|
| + _is_tracing_running_for_platform_backend = {}
|
| + _is_tracing_running_for_platform_backend.setdefault(False)
|
| +
|
| + def __init__(self, platform_backend):
|
| + self._platform_backend = platform_backend
|
| +
|
| + @classmethod
|
| + def _RemoveStaleDevToolsClient(cls, platform_backend):
|
| + """Removes DevTools clients that are no longer connectable."""
|
| + devtools_clients_map = cls._platform_backends_to_devtools_clients_maps.get(
|
| + platform_backend, {})
|
| + devtools_clients_map = {
|
| + port: client
|
| + for port, client in devtools_clients_map.iteritems()
|
| + if client.IsAlive()
|
| + }
|
| + cls._platform_backends_to_devtools_clients_maps[platform_backend] = (
|
| + devtools_clients_map)
|
| +
|
| + @classmethod
|
| + def RegisterDevToolsClient(cls, devtools_client_backend, platform_backend):
|
| + is_tracing_running = cls._is_tracing_running_for_platform_backend.get(
|
| + platform_backend)
|
| + if is_tracing_running:
|
| + raise ChromeTracingStartedError(
|
| + 'Cannot add new DevTools client when tracing is running on '
|
| + 'platform backend %s.' % platform_backend)
|
| + remote_port = str(devtools_client_backend.remote_port)
|
| + if platform_backend not in cls._platform_backends_to_devtools_clients_maps:
|
| + cls._platform_backends_to_devtools_clients_maps[platform_backend] = {}
|
| + devtools_clients_map = (
|
| + cls._platform_backends_to_devtools_clients_maps[platform_backend])
|
| + devtools_clients_map[remote_port] = devtools_client_backend
|
| +
|
| + @classmethod
|
| + def IsSupported(cls, platform_backend):
|
| + cls._RemoveStaleDevToolsClient(platform_backend)
|
| + devtools_clients_map = cls._platform_backends_to_devtools_clients_maps.get(
|
| + platform_backend, {})
|
| + for _, devtools_client in devtools_clients_map.iteritems():
|
| + if devtools_client.IsChromeTracingSupported():
|
| + return True
|
| + return False
|
| +
|
| + @property
|
| + def _is_active(self):
|
| + return self._is_tracing_running_for_platform_backend.get(
|
| + self._platform_backend)
|
| +
|
| + @_is_active.setter
|
| + def _is_active(self, value):
|
| + self._is_tracing_running_for_platform_backend[self._platform_backend] = (
|
| + value)
|
| +
|
| + def Start(self, trace_options, category_filter, timeout):
|
| + if not trace_options.enable_chrome_trace:
|
| + return False
|
| +
|
| + if self._is_active:
|
| + raise ChromeTracingStartedError(
|
| + 'Tracing is already running on platform backend %s.'
|
| + % self._platform_backend)
|
| + self._RemoveStaleDevToolsClient(self._platform_backend)
|
| + devtools_clients_map = self._platform_backends_to_devtools_clients_maps.get(
|
| + self._platform_backend, {})
|
| + if not devtools_clients_map:
|
| + return False
|
| + for _, devtools_client in devtools_clients_map.iteritems():
|
| + devtools_client.StartChromeTracing(
|
| + trace_options, category_filter.filter_string, timeout)
|
| + self._is_active = True
|
| + return True
|
| +
|
| + def Stop(self, trace_data_builder):
|
| + devtools_clients_map = (
|
| + self._platform_backends_to_devtools_clients_maps[self._platform_backend])
|
| + raised_execption_messages = []
|
| + for devtools_port, devtools_client in devtools_clients_map.iteritems():
|
| + # We do not check for stale DevTools client, so that we get an
|
| + # exception if there is a stale client. This is because we
|
| + # will potentially lose data if there is a stale client.
|
| + try:
|
| + devtools_client.StopChromeTracing(trace_data_builder)
|
| + except Exception:
|
| + raised_execption_messages.append(
|
| + 'Error when trying to stop tracing on devtools at port %s:\n%s'
|
| + % (devtools_port,
|
| + ''.join(traceback.format_exception(*sys.exc_info()))))
|
| +
|
| + self._is_active = False
|
| + if raised_execption_messages:
|
| + raise ChromeTracingStoppedError(
|
| + 'Exceptions raised when trying to stop devtool tracing\n:' +
|
| + '\n'.join(raised_execption_messages))
|
|
|