summaryrefslogtreecommitdiffstats
path: root/tools/telemetry
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-18 00:32:10 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-18 00:32:10 +0000
commita0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc (patch)
tree15a2aecb6b8191703e2ae50f58361367bf237c3e /tools/telemetry
parent36ed2103b130db30ad7fe5a50675ecb48d5c78de (diff)
downloadchromium_src-a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc.zip
chromium_src-a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc.tar.gz
chromium_src-a0a5a3a03e51c8d8cf6fa2e4bd1d55ba72a836cc.tar.bz2
Telemetry / Devtools TraceHandler: exposes tracing via dev tools.
- exposes start / stop / get request methods via devtools. This allows Telemetry to integrate trace collection across all platforms in a consistent way. BUG= TEST=./tools/telemetry/run_tests --browser=android-content-shell testGotTrace Review URL: https://chromiumcodereview.appspot.com/11548032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173595 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/telemetry')
-rw-r--r--tools/telemetry/telemetry/browser.py13
-rw-r--r--tools/telemetry/telemetry/browser_backend.py20
-rw-r--r--tools/telemetry/telemetry/page_runner.py79
-rw-r--r--tools/telemetry/telemetry/tracing_backend.py63
-rw-r--r--tools/telemetry/telemetry/tracing_backend_unittest.py33
5 files changed, 155 insertions, 53 deletions
diff --git a/tools/telemetry/telemetry/browser.py b/tools/telemetry/telemetry/browser.py
index a01cbfc..cfa2569 100644
--- a/tools/telemetry/telemetry/browser.py
+++ b/tools/telemetry/telemetry/browser.py
@@ -54,6 +54,19 @@ class Browser(object):
def tabs(self):
return self._backend.tabs
+ @property
+ def supports_tracing(self):
+ return self._backend.supports_tracing
+
+ def StartTracing(self):
+ return self._backend.StartTracing()
+
+ def StopTracing(self):
+ return self._backend.StopTracing()
+
+ def GetTrace(self):
+ return self._backend.GetTrace()
+
def Close(self):
"""Closes this browser."""
if self._wpr_server:
diff --git a/tools/telemetry/telemetry/browser_backend.py b/tools/telemetry/telemetry/browser_backend.py
index 5afa946..11eecf9 100644
--- a/tools/telemetry/telemetry/browser_backend.py
+++ b/tools/telemetry/telemetry/browser_backend.py
@@ -1,6 +1,7 @@
# Copyright (c) 2012 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 urllib2
import httplib
import socket
@@ -10,6 +11,7 @@ import weakref
from telemetry import browser_gone_exception
from telemetry import tab
+from telemetry import tracing_backend
from telemetry import user_agent
from telemetry import util
from telemetry import wpr_modes
@@ -123,6 +125,7 @@ class BrowserBackend(object):
self._inspector_protocol_version = 0
self._chrome_branch_number = 0
self._webkit_base_revision = 0
+ self._tracing_backend = None
def SetBrowser(self, browser):
self.tabs = TabController(browser, self)
@@ -186,6 +189,23 @@ class BrowserBackend(object):
def supports_tab_control(self):
return self._chrome_branch_number >= 1303
+ @property
+ def supports_tracing(self):
+ return True
+
+ def StartTracing(self):
+ self._tracing_backend = tracing_backend.TracingBackend(self._port)
+ self._tracing_backend.BeginTracing()
+
+ def StopTracing(self):
+ self._tracing_backend.EndTracingAsync()
+
+ def GetTrace(self):
+ def IsTracingRunning(self):
+ return not self._tracing_backend.HasCompleted()
+ util.WaitFor(lambda: not IsTracingRunning(self), 10)
+ return self._tracing_backend.GetTraceAndReset()
+
def CreateForwarder(self, host_port):
raise NotImplementedError()
diff --git a/tools/telemetry/telemetry/page_runner.py b/tools/telemetry/telemetry/page_runner.py
index ffe2251..c19d74a 100644
--- a/tools/telemetry/telemetry/page_runner.py
+++ b/tools/telemetry/telemetry/page_runner.py
@@ -23,13 +23,9 @@ class _RunState(object):
self.first_browser = True
self.browser = None
self.tab = None
- self.trace_tab = None
+ self.is_tracing = False
def Close(self):
- if self.trace_tab:
- self.trace_tab.Disconnect()
- self.trace_tab = None
-
if self.tab:
self.tab.Disconnect()
self.tab = None
@@ -136,7 +132,7 @@ http://goto/read-src-internal, or create a new archive using record_wpr.
logging.warning('Tab crashed: %s%s', page.url, stdout)
state.Close()
- if options.trace_dir and state.trace_tab:
+ if options.trace_dir:
self._EndTracing(state, options, page)
break
except browser_gone_exception.BrowserGoneException:
@@ -228,56 +224,33 @@ http://goto/read-src-internal, or create a new archive using record_wpr.
state.browser.SetReplayArchivePath(archive_path)
def _SetupTracingTab(self, state):
- if not state.trace_tab:
- # Swap the two tabs because new tabs open to about:blank, and we
- # can't navigate across protocols to chrome://tracing. The initial
- # tab starts at chrome://newtab, so it works for that tab.
- # TODO(dtu): If the trace_tab crashes, we're hosed.
- state.trace_tab = state.tab
- state.tab = state.browser.tabs.New()
+ if state.browser.supports_tracing:
+ state.is_tracing = True
+ state.browser.StartTracing()
- state.trace_tab.page.Navigate('chrome://tracing')
- state.trace_tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+ def _EndTracing(self, state, options, page):
+ if state.is_tracing:
+ state.is_tracing = False
+ state.browser.StopTracing()
+ trace = state.browser.GetTrace()
+ logging.info('Processing trace...')
- # Start tracing.
- state.trace_tab.runtime.Execute('tracingController.beginTracing('
- 'tracingController.supportsSystemTracing);')
+ trace_file_base = os.path.join(
+ options.trace_dir, page.url_as_file_safe_name)
- def _EndTracing(self, state, options, page):
- def IsTracingRunning():
- return state.trace_tab.runtime.Evaluate(
- 'tracingController.isTracingEnabled')
- # Tracing might have ended already if the buffer filled up.
- if IsTracingRunning():
- state.trace_tab.runtime.Execute('tracingController.endTracing()')
- util.WaitFor(lambda: not IsTracingRunning(), 10)
-
- logging.info('Processing trace...')
-
- trace_file_base = os.path.join(
- options.trace_dir, page.url_as_file_safe_name)
-
- if options.page_repeat != 1 or options.pageset_repeat != 1:
- trace_file_index = 0
-
- while True:
- trace_file = '%s_%03d.json' % (trace_file_base, trace_file_index)
- if not os.path.exists(trace_file):
- break
- trace_file_index = trace_file_index + 1
- else:
- trace_file = '%s.json' % trace_file_base
-
- with open(trace_file, 'w') as trace_file:
- trace_file.write(state.trace_tab.runtime.Evaluate("""
- JSON.stringify({
- traceEvents: tracingController.traceEvents,
- systemTraceEvents: tracingController.systemTraceEvents,
- clientInfo: tracingController.clientInfo_,
- gpuInfo: tracingController.gpuInfo_
- });
- """))
- logging.info('Trace saved.')
+ if options.page_repeat != 1 or options.pageset_repeat != 1:
+ trace_file_index = 0
+
+ while True:
+ trace_file = '%s_%03d.json' % (trace_file_base, trace_file_index)
+ if not os.path.exists(trace_file):
+ break
+ trace_file_index = trace_file_index + 1
+ else:
+ trace_file = '%s.json' % trace_file_base
+ with open(trace_file, 'w') as trace_file:
+ trace_file.write(trace)
+ logging.info('Trace saved.')
def _PreparePage(self, page, tab, page_state, results):
parsed_url = urlparse.urlparse(page.url)
diff --git a/tools/telemetry/telemetry/tracing_backend.py b/tools/telemetry/telemetry/tracing_backend.py
new file mode 100644
index 0000000..54f9057
--- /dev/null
+++ b/tools/telemetry/telemetry/tracing_backend.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2012 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
+
+from telemetry import util
+from telemetry import websocket
+
+
+class TracingBackend(object):
+ def __init__(self, devtools_port):
+ debugger_url = 'ws://localhost:%i/devtools/browser' % devtools_port
+ self._socket = websocket.create_connection(debugger_url)
+ self._next_request_id = 0
+ self._cur_socket_timeout = 0
+
+ def BeginTracing(self):
+ req = {'method': 'Tracing.start'}
+ self._SyncRequest(req)
+
+ def EndTracingAsync(self):
+ req = {'method': 'Tracing.end'}
+ self._SyncRequest(req)
+
+ def HasCompleted(self):
+ req = {'method': 'Tracing.hasCompleted'}
+ r = self._SyncRequest(req)
+ return r['response']['result']
+
+ def GetTraceAndReset(self):
+ req = {'method': 'Tracing.getTraceAndReset'}
+ r = self._SyncRequest(req)
+ return '{"traceEvents":[' + r['response']['result'] + ']}'
+
+ def _SyncRequest(self, req, timeout=10):
+ self._SetTimeout(timeout)
+ req['id'] = self._next_request_id
+ self._next_request_id += 1
+ data = json.dumps(req)
+ logging.debug('will send [%s]', data)
+ self._socket.send(data)
+
+ while True:
+ try:
+ data = self._socket.recv()
+ except (socket.error, websocket.WebSocketException):
+ raise util.TimeoutException(
+ 'Timed out waiting for reply. This is unusual.')
+
+ logging.debug('got [%s]', data)
+ res = json.loads(data)
+ if res['id'] != req['id']:
+ logging.debug('Dropped reply: %s', json.dumps(res))
+ continue
+ return res
+
+ def _SetTimeout(self, timeout):
+ if self._cur_socket_timeout != timeout:
+ self._socket.settimeout(timeout)
+ self._cur_socket_timeout = timeout
diff --git a/tools/telemetry/telemetry/tracing_backend_unittest.py b/tools/telemetry/telemetry/tracing_backend_unittest.py
new file mode 100644
index 0000000..7a8370d
--- /dev/null
+++ b/tools/telemetry/telemetry/tracing_backend_unittest.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 os
+
+from telemetry import tab_test_case
+from telemetry import util
+
+
+class TracingBackendTest(tab_test_case.TabTestCase):
+ def _StartServer(self):
+ base_dir = os.path.dirname(__file__)
+ self._browser.SetHTTPServerDirectory(os.path.join(base_dir, '..',
+ 'unittest_data'))
+
+ def _WaitForAnimationFrame(self):
+ def _IsDone():
+ js_is_done = """done"""
+ return bool(self._tab.runtime.Evaluate(js_is_done))
+ util.WaitFor(_IsDone, 5)
+
+ def testGotTrace(self):
+ self._StartServer()
+ self._browser.StartTracing()
+ self._browser.http_server.UrlOf('image.png')
+ self.assertTrue(self._browser.supports_tracing)
+ self._browser.StopTracing()
+ trace = self._browser.GetTrace()
+ json_trace = json.loads(trace)
+ self.assertTrue('traceEvents' in json_trace)
+ self.assertTrue(json_trace['traceEvents'])