Commit
·
3864f2f
0
Parent(s):
init: upload perfetto_relay.html
Browse files- README.md +2 -0
- pages/perfetto_relay.html +150 -0
README.md
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Storage Repo for Nightly ci of SGLang
|
| 2 |
+
|
pages/perfetto_relay.html
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8">
|
| 5 |
+
<title>Perfetto Trace Relay</title>
|
| 6 |
+
<style>
|
| 7 |
+
body { font-family: sans-serif; padding: 2em; }
|
| 8 |
+
</style>
|
| 9 |
+
</head>
|
| 10 |
+
<body>
|
| 11 |
+
<h1>Perfetto Trace Relay</h1>
|
| 12 |
+
<p id="status">Initializing...</p>
|
| 13 |
+
|
| 14 |
+
<script>
|
| 15 |
+
(async () => {
|
| 16 |
+
const statusElement = document.getElementById('status');
|
| 17 |
+
const PERFETTO_UI_URL = 'https://ui.perfetto.dev';
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* Displays a final message on the relay page itself.
|
| 21 |
+
* @param {string} message The message to display.
|
| 22 |
+
* @param {boolean} isError If true, display as an error.
|
| 23 |
+
*/
|
| 24 |
+
const setStatus = (message, isError = false) => {
|
| 25 |
+
console.log(message);
|
| 26 |
+
statusElement.textContent = message;
|
| 27 |
+
if (isError) {
|
| 28 |
+
statusElement.style.color = 'red';
|
| 29 |
+
console.error(message);
|
| 30 |
+
}
|
| 31 |
+
};
|
| 32 |
+
|
| 33 |
+
/**
|
| 34 |
+
* Establishes a handshake with the Perfetto UI window to ensure it's ready.
|
| 35 |
+
* The Perfetto UI will respond with 'PONG' when it receives a 'PING'.
|
| 36 |
+
* @param {Window} ui The window handle for the Perfetto UI.
|
| 37 |
+
* @returns {Promise<void>} A promise that resolves when the handshake is complete.
|
| 38 |
+
*/
|
| 39 |
+
const establishHandshake = (ui) => {
|
| 40 |
+
return new Promise((resolve, reject) => {
|
| 41 |
+
let intervalId = null;
|
| 42 |
+
let timeoutId = null;
|
| 43 |
+
|
| 44 |
+
const cleanup = () => {
|
| 45 |
+
clearInterval(intervalId);
|
| 46 |
+
clearTimeout(timeoutId);
|
| 47 |
+
window.removeEventListener('message', messageHandler);
|
| 48 |
+
};
|
| 49 |
+
|
| 50 |
+
const messageHandler = (event) => {
|
| 51 |
+
if (event.source === ui && event.data === 'PONG') {
|
| 52 |
+
cleanup();
|
| 53 |
+
resolve();
|
| 54 |
+
}
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
window.addEventListener('message', messageHandler);
|
| 58 |
+
|
| 59 |
+
// 1. Start pinging the UI
|
| 60 |
+
intervalId = setInterval(() => {
|
| 61 |
+
// The try-catch is necessary because the UI window might be closed by the user.
|
| 62 |
+
try {
|
| 63 |
+
ui.postMessage('PING', PERFETTO_UI_URL);
|
| 64 |
+
} catch (e) {
|
| 65 |
+
// If postMessage fails, it's likely the window was closed.
|
| 66 |
+
cleanup();
|
| 67 |
+
reject(new Error('Perfetto UI window was closed before handshake could complete.'));
|
| 68 |
+
}
|
| 69 |
+
}, 200);
|
| 70 |
+
|
| 71 |
+
// 2. Set a timeout for the handshake
|
| 72 |
+
timeoutId = setTimeout(() => {
|
| 73 |
+
cleanup();
|
| 74 |
+
reject(new Error('Handshake with Perfetto UI timed out. The UI might not have loaded correctly.'));
|
| 75 |
+
}, 10000); // 10-second timeout
|
| 76 |
+
});
|
| 77 |
+
};
|
| 78 |
+
|
| 79 |
+
/**
|
| 80 |
+
* Fetches the trace file and posts it to the Perfetto UI.
|
| 81 |
+
* @param {Window} ui The window handle for the Perfetto UI.
|
| 82 |
+
* @param {string} srcUrl The URL of the trace file to fetch.
|
| 83 |
+
* @param {string | null} customTitle An optional title for the trace.
|
| 84 |
+
*/
|
| 85 |
+
const fetchTraceAndPost = async (ui, srcUrl, customTitle) => {
|
| 86 |
+
// This fetch is executed on your domain, so it can handle auth/CORS/ACLs.
|
| 87 |
+
const response = await fetch(srcUrl, {
|
| 88 |
+
mode: 'cors',
|
| 89 |
+
credentials: 'omit', // Avoids "ACAO: * + credentials" error.
|
| 90 |
+
cache: 'no-store', // Ensures the latest trace is always fetched.
|
| 91 |
+
});
|
| 92 |
+
|
| 93 |
+
if (!response.ok) {
|
| 94 |
+
const errorMsg = `Failed to load trace: ${response.status} ${response.statusText}`;
|
| 95 |
+
ui.postMessage({ perfetto: { title: errorMsg } }, PERFETTO_UI_URL);
|
| 96 |
+
throw new Error(errorMsg);
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
const buffer = await response.arrayBuffer();
|
| 100 |
+
|
| 101 |
+
// Determine a sensible title and filename for the trace.
|
| 102 |
+
const title = customTitle || srcUrl.split('/').pop() || 'trace';
|
| 103 |
+
const fileName = title.endsWith('.gz') || title.endsWith('.zip') ? title : `${title}.perfetto-trace`;
|
| 104 |
+
|
| 105 |
+
// Post the trace buffer to the Perfetto UI.
|
| 106 |
+
ui.postMessage({
|
| 107 |
+
perfetto: {
|
| 108 |
+
buffer,
|
| 109 |
+
title,
|
| 110 |
+
fileName,
|
| 111 |
+
// Keep the UI open after loading, useful for debugging.
|
| 112 |
+
keepApiOpen: true,
|
| 113 |
+
}
|
| 114 |
+
}, PERFETTO_UI_URL, [buffer]); // Transfer the buffer for performance.
|
| 115 |
+
};
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
// --- Main Execution Logic ---
|
| 119 |
+
try {
|
| 120 |
+
const params = new URLSearchParams(location.search);
|
| 121 |
+
const src = params.get('src');
|
| 122 |
+
const title = params.get('title');
|
| 123 |
+
|
| 124 |
+
if (!src) {
|
| 125 |
+
throw new Error('Required "src" URL parameter is missing.');
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
setStatus('Opening Perfetto UI...');
|
| 129 |
+
const ui = window.open(PERFETTO_UI_URL);
|
| 130 |
+
if (!ui) {
|
| 131 |
+
throw new Error('Failed to open Perfetto UI. Please disable your popup blocker for this site.');
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
setStatus('Waiting for handshake with Perfetto UI...');
|
| 135 |
+
await establishHandshake(ui);
|
| 136 |
+
|
| 137 |
+
setStatus(`Fetching trace from ${src}...`);
|
| 138 |
+
await fetchTraceAndPost(ui, src, title);
|
| 139 |
+
|
| 140 |
+
setStatus('Trace successfully sent to Perfetto UI. You can now close this tab.');
|
| 141 |
+
// Optionally, close the relay window automatically.
|
| 142 |
+
// window.close();
|
| 143 |
+
|
| 144 |
+
} catch (error) {
|
| 145 |
+
setStatus(error.message, true);
|
| 146 |
+
}
|
| 147 |
+
})();
|
| 148 |
+
</script>
|
| 149 |
+
</body>
|
| 150 |
+
</html>
|