aboutsummaryrefslogtreecommitdiff
path: root/src/zen/frontend/html/trace.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/zen/frontend/html/trace.js')
-rw-r--r--src/zen/frontend/html/trace.js40
1 files changed, 28 insertions, 12 deletions
diff --git a/src/zen/frontend/html/trace.js b/src/zen/frontend/html/trace.js
index 2910da15d..2c0b7a3bd 100644
--- a/src/zen/frontend/html/trace.js
+++ b/src/zen/frontend/html/trace.js
@@ -8,16 +8,8 @@ import { StatsView } from "./stats.js";
import { MemoryView } from "./memory.js";
import { LogsView } from "./logs.js";
import { CsvStatsView } from "./csvstats.js";
-
-function escapeHtml(s) {
- return String(s).replace(/[&<>"']/g, (c) => ({
- "&": "&amp;",
- "<": "&lt;",
- ">": "&gt;",
- "\"": "&quot;",
- "'": "&#39;",
- }[c]));
-}
+import { CountersView } from "./counters.js";
+import { escapeHtml } from "./util.js";
function formatTimeMs(us) {
if (us < 1000) return `${us} µs`;
@@ -157,10 +149,11 @@ async function main() {
const memoryView = new MemoryView(model, document.getElementById("memory-content"));
const logsView = new LogsView(model, document.getElementById("logs-content"));
const csvView = new CsvStatsView(model, document.getElementById("csv-content"));
+ const countersView = new CountersView(model, document.getElementById("counters-content"));
const threadsListApi = renderThreadsList(model, timeline);
renderRegionCategories(model, timeline);
- setupTabs(memoryView, logsView, csvView);
+ setupTabs(memoryView, logsView, csvView, countersView);
setupSearch(model, timeline, stats);
const bookmarksToggle = document.getElementById("bookmarks-toggle");
@@ -173,6 +166,26 @@ async function main() {
timeline.setLodEnabled(lodToggle.checked);
});
+ const compactToggle = document.getElementById("compact-toggle");
+ compactToggle.addEventListener("change", () => {
+ timeline.setCompact(compactToggle.checked);
+ });
+
+ // 'c' toggles compact mode while the timeline tab is active. Skipped
+ // when focus is in a text input so typing 'c' in the search box still
+ // works normally.
+ document.addEventListener("keydown", (e) => {
+ if (e.key !== "c" && e.key !== "C") return;
+ if (e.ctrlKey || e.metaKey || e.altKey) return;
+ const target = e.target;
+ if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable)) return;
+ const timelineTab = document.querySelector(".tab[data-tab='timeline']");
+ if (!timelineTab || !timelineTab.classList.contains("active")) return;
+ e.preventDefault();
+ compactToggle.checked = !compactToggle.checked;
+ timeline.setCompact(compactToggle.checked);
+ });
+
// Enable all threads that actually have captured scopes by default; if
// none do, enable every thread so the swimlanes still show up empty.
const withScopes = model.threads.filter((t) => t.scope_count > 0).map((t) => t.thread_id);
@@ -492,7 +505,7 @@ function renderRegionCategories(model, timeline) {
timeline.setEnabledRegionCategories(allIndices);
}
-function setupTabs(memoryView, logsView, csvView) {
+function setupTabs(memoryView, logsView, csvView, countersView) {
const tabs = document.querySelectorAll(".tab");
const views = document.querySelectorAll(".view");
const validTabs = new Set(Array.from(tabs, (tab) => tab.dataset.tab));
@@ -518,6 +531,9 @@ function setupTabs(memoryView, logsView, csvView) {
if (key === "csv" && csvView) {
csvView.ensureLoaded();
}
+ if (key === "counters" && countersView) {
+ countersView.ensureLoaded();
+ }
}
for (const tab of tabs) {