Skip to content

Instantly share code, notes, and snippets.

@victorporof
Last active May 13, 2022 07:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save victorporof/a82efafc203179966a712e6f8155bf4b to your computer and use it in GitHub Desktop.
Save victorporof/a82efafc203179966a712e6f8155bf4b to your computer and use it in GitHub Desktop.
Perf Extension
<!DOCTYPE html>
<html>
<head>
<script src="devtools.js"></script>
</head>
</html>
chrome.devtools.panels.create("My Panel", null, "panel.html", function (panel) {
//
});
{
"action": {},
"devtools_page": "devtools.html",
"key": "...",
"manifest_version": 3,
"name": "DevTools Perf!",
"permissions": ["debugger"],
"version": "1.0"
}
<html>
<head>
<style>
:root[recording] .record-button {
color: red;
}
</style>
</head>
<body>
<input class="record-button" type="button" />
<script src="utils.js"></script>
<script src="panel.js"></script>
</body>
</html>
const state = {
isRecording: false,
};
const recordButton = document.querySelector(".record-button");
recordButton.addEventListener("click", toggleRecording);
function render() {
if (state.isRecording) {
document.documentElement.setAttribute("recording", "true");
recordButton.setAttribute("value", "Stop Recording");
} else {
document.documentElement.removeAttribute("recording");
recordButton.setAttribute("value", "Start Recording");
}
}
async function toggleRecording() {
if (!state.isRecording) {
startRecording();
} else {
stopRecording();
}
}
async function startRecording() {
await sendCommand(getInspectedTab(), "DOM.disable");
await sendCommand(getInspectedTab(), "CSS.disable");
await sendCommand(getInspectedTab(), "Overlay.disable");
await sendCommand(getInspectedTab(), "Tracing.start", makeTracingParams());
state.isRecording = true;
render();
}
async function stopRecording() {
await sendCommand(getInspectedTab(), "DOM.enable");
await sendCommand(getInspectedTab(), "CSS.enable");
await sendCommand(getInspectedTab(), "Overlay.enable");
await sendCommand(getInspectedTab(), "Tracing.end", makeTracingParams());
state.isRecording = false;
render();
}
attach(getInspectedTab(), "1.0").then(render);
function promisify(f) {
return (...args) => new Promise((resolve) => f(...args, resolve));
}
const attach = promisify(chrome.debugger.attach);
const sendCommand = promisify(chrome.debugger.sendCommand);
function getInspectedTab() {
return { tabId: chrome.devtools.inspectedWindow.tabId };
}
function makeTracingParams() {
return {
bufferUsageReportingInterval: 500,
categories: [
"-*",
"devtools.timeline",
"disabled-by-default-devtools.timeline",
"disabled-by-default-devtools.timeline.frame",
"v8.execute",
"disabled-by-default-v8.compile",
"blink.console",
"blink.user_timing",
"loading",
"latencyInfo",
"disabled-by-default-v8.cpu_profiler",
"disabled-by-default-devtools.timeline.stack",
"disabled-by-default-devtools.screenshot",
].join(","),
options: "",
transferMode: "ReportEvents",
};
}
@paulirish
Copy link

i tweaked the extension to show the trace data collected.

commit 8203a504e398a3b0efd8de198c95d467c3eb4060
Author: Paul Irish <commits@paul.irish>
Date:   9 seconds ago

    print trace data

diff --git a/panel.html b/panel.html
index cf79e8e..6d823d1 100644
--- a/panel.html
+++ b/panel.html
@@ -10,5 +10,7 @@
     <input class="record-button" type="button" />
     <script src="utils.js"></script>
     <script src="panel.js"></script>
+
+    <div id="trace"></div>
   </body>
 </html>
diff --git a/panel.js b/panel.js
index 0d0dc4c..ca49cbf 100644
--- a/panel.js
+++ b/panel.js
@@ -24,6 +24,8 @@ async function toggleRecording() {
 }
 
 async function startRecording() {
+  document.querySelector('#trace').textContent = '';
+
   await sendCommand(getInspectedTab(), "DOM.disable");
   await sendCommand(getInspectedTab(), "CSS.disable");
   await sendCommand(getInspectedTab(), "Overlay.disable");
@@ -41,4 +43,20 @@ async function stopRecording() {
   render();
 }
 
+onEvent((method, params) => {
+  if (!method.startsWith('Tracing.')) return;
+  printEventData(params);
+});
+
+function printEventData(data) {
+  // TODO: Filter down to trace event allowlist
+
+  const h3 = document.createElement('h3');
+  h3.textContent = method;
+  const pre  = document.createElement('pre');
+  pre.textContent = JSON.stringify(params, null, 2);
+  document.querySelector('#trace').append(h3, pre);
+}
+
+
 attach(getInspectedTab(), "1.0").then(render);
diff --git a/utils.js b/utils.js
index 48b8cc4..58ff01e 100644
--- a/utils.js
+++ b/utils.js
@@ -5,10 +5,21 @@ function promisify(f) {
 const attach = promisify(chrome.debugger.attach);
 const sendCommand = promisify(chrome.debugger.sendCommand);
 
+
 function getInspectedTab() {
   return { tabId: chrome.devtools.inspectedWindow.tabId };
 }
 
+
+function onEvent(callback) {
+  const inspectedTab = getInspectedTab();
+  chrome.debugger.onEvent.addListener((source, method, params) => {
+    if (source.tabId !== inspectedTab.tabId) return;
+
+    callback(method, params);
+  });
+}
+
 function makeTracingParams() {
   return {
     bufferUsageReportingInterval: 500,

@victorporof
Copy link
Author

Sweet, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment