--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -41,16 +41,19 @@ const isWindows = (Services.appinfo.OS =
const EOL = isWindows ? "\r\n" : "\n";
// This is the ping object currently displayed in the page.
var gPingData = null;
// Cached value of document's RTL mode
var documentRTLMode = "";
+// Data Collection Processes
+var gOptions = ["parent", "content", "extension", "dynamic", "gpu"];
+
/**
* Helper function for determining whether the document direction is RTL.
* Caches result of check on first invocation.
*/
function isRTL() {
if (!documentRTLMode)
documentRTLMode = window.getComputedStyle(document.body).direction;
return (documentRTLMode == "rtl");
@@ -1700,35 +1703,58 @@ var AddonDetails = {
};
var Scalars = {
/**
* Render the scalar data - if present - from the payload in a simple key-value table.
* @param aPayload A payload object to render the data from.
*/
render(aPayload) {
+ this.scalarSelect("parent", aPayload);
+ this.checkProcessData("scalars-section", aPayload);
+ },
+
+ checkProcessData(aId, aPayload) {
+ let prOptions = [];
+ var i = 0;
+ for (let f of gOptions) {
+ if (f === "parent" && aPayload.scalars) {
+ prOptions[i] = f;
+ i = i + 1;
+ } else if ("processes" in aPayload && f in aPayload.processes &&
+ "scalars" in aPayload.processes[f]) {
+ let scalars = aPayload.processes[f].scalars;
+ if (Object.keys(scalars).length > 0 && scalars) {
+ prOptions[i] = f;
+ i = i + 1;
+ }
+ }
+ }
+
+ addSubSection(aId, aPayload, prOptions, Scalars.scalarSelect);
+
+ },
+
+ scalarSelect(aProcess, aPayload) {
let scalarsSection = document.getElementById("scalars");
removeAllChildNodes(scalarsSection);
- let processesSelect = document.getElementById("processes");
- let selectedProcess = processesSelect.selectedOptions.item(0).getAttribute("value");
-
if (!aPayload.processes ||
- !selectedProcess ||
- !(selectedProcess in aPayload.processes)) {
+ !aProcess ||
+ !(aProcess in aPayload.processes)) {
return;
}
- let scalars = aPayload.processes[selectedProcess].scalars || {};
- let hasData = Array.from(processesSelect.options).some((option) => {
- let value = option.getAttribute("value");
+ let scalars = aPayload.processes[aProcess].scalars || {};
+ let hasData = gOptions.some((option) => {
+ let value = aProcess;
let sclrs = aPayload.processes[value].scalars;
return sclrs && Object.keys(sclrs).length > 0;
});
- setHasData("scalars-section", hasData);
+ hasSubsectionData("scalars-section", hasData);
if (Object.keys(scalars).length > 0) {
const headings = [
"namesHeader",
"valuesHeader",
].map(h => bundle.GetStringFromName(h));
const table = GenericTable.render(explodeObject(scalars), headings);
scalarsSection.appendChild(table);
}
@@ -1736,35 +1762,58 @@ var Scalars = {
};
var KeyedScalars = {
/**
* Render the keyed scalar data - if present - from the payload in a simple key-value table.
* @param aPayload A payload object to render the data from.
*/
render(aPayload) {
+ this.keyedScalarSelect("parent", aPayload);
+ this.checkProcessData("keyed-scalars-section", aPayload);
+ },
+
+ checkProcessData(aId, aPayload) {
+ let prOptions = [];
+ var i = 0;
+ for (let f of gOptions) {
+ if (f === "parent" && aPayload.keyedScalars) {
+ prOptions[i] = f;
+ i = i + 1;
+ } else if ("processes" in aPayload && f in aPayload.processes &&
+ "keyedScalars" in aPayload.processes[f]) {
+ let keyedScalars = aPayload.processes[f].keyedScalars;
+ if (Object.keys(keyedScalars).length > 0 && keyedScalars) {
+ prOptions[i] = f;
+ i = i + 1;
+ }
+ }
+ }
+
+ addSubSection(aId, aPayload, prOptions, KeyedScalars.keyedScalarSelect);
+
+ },
+
+ keyedScalarSelect(aProcess, aPayload) {
let scalarsSection = document.getElementById("keyed-scalars");
removeAllChildNodes(scalarsSection);
- let processesSelect = document.getElementById("processes");
- let selectedProcess = processesSelect.selectedOptions.item(0).getAttribute("value");
-
if (!aPayload.processes ||
- !selectedProcess ||
- !(selectedProcess in aPayload.processes)) {
+ !aProcess ||
+ !(aProcess in aPayload.processes)) {
return;
}
- let keyedScalars = aPayload.processes[selectedProcess].keyedScalars || {};
- let hasData = Array.from(processesSelect.options).some((option) => {
- let value = option.getAttribute("value");
+ let keyedScalars = aPayload.processes[aProcess].keyedScalars || {};
+ let hasData = gOptions.some((option) => {
+ let value = aProcess;
let keyedS = aPayload.processes[value].keyedScalars;
return keyedS && Object.keys(keyedS).length > 0;
});
- setHasData("keyed-scalars-section", hasData);
+ hasSubsectionData("keyed-scalars-section", hasData);
if (!Object.keys(keyedScalars).length > 0) {
return;
}
const headings = [
"namesHeader",
"valuesHeader",
].map(h => bundle.GetStringFromName(h));
@@ -1786,35 +1835,58 @@ var KeyedScalars = {
};
var Events = {
/**
* Render the event data - if present - from the payload in a simple table.
* @param aPayload A payload object to render the data from.
*/
render(aPayload) {
+ this.eventsSelect("parent", aPayload);
+ this.checkProcessData("events-section", aPayload);
+ },
+
+ checkProcessData(aId, aPayload) {
+ let prOptions = [];
+ var i = 0;
+ for (let f of gOptions) {
+ if (f === "parent" && aPayload.events) {
+ prOptions[i] = f;
+ i = i + 1;
+ } else if ("processes" in aPayload && f in aPayload.processes &&
+ "events" in aPayload.processes[f]) {
+ let events = aPayload.processes[f].events;
+ if (Object.keys(events).length > 0 && events) {
+ prOptions[i] = f;
+ i = i + 1;
+ }
+ }
+ }
+
+ addSubSection(aId, aPayload, prOptions, Events.eventsSelect);
+
+ },
+
+ eventsSelect(aProcess, aPayload) {
let eventsSection = document.getElementById("events");
removeAllChildNodes(eventsSection);
- let processesSelect = document.getElementById("processes");
- let selectedProcess = processesSelect.selectedOptions.item(0).getAttribute("value");
-
if (!aPayload.processes ||
- !selectedProcess ||
- !(selectedProcess in aPayload.processes)) {
+ !aProcess ||
+ !(aProcess in aPayload.processes)) {
return;
}
- let events = aPayload.processes[selectedProcess].events || {};
- let hasData = Array.from(processesSelect.options).some((option) => {
- let value = option.getAttribute("value");
+ let events = aPayload.processes[aProcess].events || {};
+ let hasData = gOptions.some((option) => {
+ let value = aProcess;
let evts = aPayload.processes[value].events;
return evts && Object.keys(evts).length > 0;
});
- setHasData("events-section", hasData);
+ hasSubsectionData("events-section", hasData);
if (Object.keys(events).length > 0) {
const headings = [
"timestampHeader",
"categoryHeader",
"methodHeader",
"objectHeader",
"valuesHeader",
"extraHeader",
@@ -1836,16 +1908,21 @@ function setHasData(aSectionID, aHasData
let sectionElement = document.getElementById(aSectionID);
sectionElement.classList[aHasData ? "add" : "remove"]("has-data");
// Display or Hide the section in the sidebar
let sectionCategory = document.querySelector(".category[value=" + aSectionID + "]");
sectionCategory.classList[aHasData ? "add" : "remove"]("has-data");
}
+function hasSubsectionData(aSectionID, aHasData) {
+ let sectionElement = document.getElementById(aSectionID);
+ sectionElement.classList[aHasData ? "add" : "remove"]("has-data");
+}
+
/**
* Sets the text of the page header based on a config pref + bundle strings
*/
function setupPageHeader() {
let serverOwner = Preferences.get(PREF_TELEMETRY_SERVER_OWNER, "Mozilla");
let brandName = brandBundle.GetStringFromName("brandFullName");
let subtitleText = bundle.formatStringFromName(
"pageSubtitle", [serverOwner, brandName], 2);
@@ -1859,28 +1936,16 @@ function setupPageHeader() {
"https://telemetry.mozilla.org/",
];
let htmlLink = document.querySelectorAll("#home-section > ul > li > a");
htmlLink.forEach((a, index) => {
a.href = links[index];
});
}
-function displayProcessesSelector(selectedSection) {
- let whitelist = [
- "scalars-section",
- "keyed-scalars-section",
- "histograms-section",
- "keyed-histograms-section",
- "events-section"
- ];
- let processes = document.getElementById("processes");
- processes.hidden = !whitelist.includes(selectedSection);
-}
-
function refreshSearch() {
removeSearchSectionTitles();
let selectedSection = document.querySelector(".category.selected").getAttribute("value");
let search = document.getElementById("search");
if (!Search.blacklist.includes(selectedSection)) {
Search.search(search.value);
}
}
@@ -1989,21 +2054,56 @@ function show(selected) {
selected.classList.add("selected");
document.querySelectorAll("section").forEach((section) => {
section.classList.remove("active");
});
selected_section.classList.add("active");
adjustHeaderState();
- displayProcessesSelector(selectedValue);
adjustSearchState();
changeUrlPath(selectedValue);
}
+/**
+ * This function only highlights the selected sub-section by attaching the "selected" class
+ */
+function showSection(aSectionId) {
+ if (!aSectionId) {
+ return;
+ }
+ let current_selection = document.querySelector(".category-subsection.selected");
+ if (current_selection) {
+ current_selection.classList.remove("selected");
+ }
+
+ document.getElementById(aSectionId).classList.add("selected");
+}
+
+/**
+ * Adds sub-sections
+ */
+function addSubSection(aId, aPayload, aProcessList, aCallFunc) {
+ let category = document.querySelector("#categories > [value=" + aId + "]");
+ category.classList.add("has-subsection");
+ for (let f of aProcessList) {
+ let subCategory = document.createElement("div");
+ subCategory.classList.add("category-subsection");
+ subCategory.setAttribute("value", aId + "-" + f);
+ subCategory.setAttribute("id", aId + "-" + f);
+ subCategory.addEventListener("click", () => {
+ let sectionId = aId + "-" + f;
+ showSection(sectionId);
+ aCallFunc(f, aPayload);
+ });
+ subCategory.appendChild(document.createTextNode(f));
+ category.appendChild(subCategory);
+ }
+}
+
function showSubSection(selected) {
if (!selected) {
return;
}
let current_selection = document.querySelector(".category-subsection.selected");
if (current_selection)
current_selection.classList.remove("selected");
selected.classList.add("selected");
@@ -2194,74 +2294,121 @@ var LateWritesSingleton = {
let memoryMap = lateWrites.memoryMap;
StackRenderer.renderStacks("late-writes", stacks, memoryMap,
LateWritesSingleton.renderHeader);
},
};
var HistogramSection = {
render(aPayload) {
+ this.histogramSelect("parent", aPayload);
+ this.checkProcessData("histograms-section", aPayload);
+ },
+
+ checkProcessData(aId, aPayload) {
+ let prOptions = [];
+ var i = 0;
+ for (let f of gOptions) {
+ if (f === "parent" && aPayload.histograms) {
+ prOptions[i] = f;
+ i = i + 1;
+ } else if ("processes" in aPayload && f in aPayload.processes &&
+ "histograms" in aPayload.processes[f]) {
+ let histograms = aPayload.processes[f].histograms;
+ if (Object.keys(histograms).length > 0 && histograms) {
+ prOptions[i] = f;
+ i = i + 1;
+ }
+ }
+ }
+
+ addSubSection(aId, aPayload, prOptions, HistogramSection.histogramSelect);
+
+ },
+
+ histogramSelect(aProcess, aPayload) {
let hgramDiv = document.getElementById("histograms");
removeAllChildNodes(hgramDiv);
let histograms = {};
- let hgramsSelect = document.getElementById("processes");
- let hgramsOption = hgramsSelect.selectedOptions.item(0);
- let hgramsProcess = hgramsOption.getAttribute("value");
- if (hgramsProcess === "parent") {
+ if (aProcess === "parent") {
histograms = aPayload.histograms;
- } else if ("processes" in aPayload && hgramsProcess in aPayload.processes &&
- "histograms" in aPayload.processes[hgramsProcess]) {
- histograms = aPayload.processes[hgramsProcess].histograms;
+ } else if ("processes" in aPayload && aProcess in aPayload.processes &&
+ "histograms" in aPayload.processes[aProcess]) {
+ histograms = aPayload.processes[aProcess].histograms;
}
- let hasData = Array.from(hgramsSelect.options).some((option) => {
- let value = option.getAttribute("value");
+ let hasData = gOptions.some((option) => {
+ let value = aProcess;
if (value == "parent") {
return Object.keys(aPayload.histograms).length > 0;
}
let histos = aPayload.processes[value].histograms;
return histos && Object.keys(histos).length > 0;
});
- setHasData("histograms-section", hasData);
+ hasSubsectionData("histograms-section", hasData);
if (Object.keys(histograms).length > 0) {
for (let [name, hgram] of Object.entries(histograms)) {
Histogram.render(hgramDiv, name, hgram, {unpacked: true});
}
}
},
};
var KeyedHistogramSection = {
render(aPayload) {
+ this.keyedHistogramSelect("parent", aPayload);
+ this.checkProcessData("keyed-histograms-section", aPayload);
+ },
+
+ checkProcessData(aId, aPayload) {
+ let prOptions = [];
+ var i = 0;
+ for (let f of gOptions) {
+ if (f === "parent" && aPayload.keyedHistograms) {
+ prOptions[i] = f;
+ i = i + 1;
+ } else if ("processes" in aPayload && f in aPayload.processes &&
+ "keyedHistograms" in aPayload.processes[f]) {
+ let keyedHistograms = aPayload.processes[f].keyedHistograms;
+ if (Object.keys(keyedHistograms).length > 0 && keyedHistograms) {
+ prOptions[i] = f;
+ i = i + 1;
+ }
+ }
+ }
+
+ addSubSection(aId, aPayload, prOptions, KeyedHistogramSection.keyedHistogramSelect);
+
+ },
+
+ keyedHistogramSelect(aProcess, aPayload) {
let keyedDiv = document.getElementById("keyed-histograms");
removeAllChildNodes(keyedDiv);
let keyedHistograms = {};
- let keyedHgramsSelect = document.getElementById("processes");
- let keyedHgramsOption = keyedHgramsSelect.selectedOptions.item(0);
- let keyedHgramsProcess = keyedHgramsOption.getAttribute("value");
- if (keyedHgramsProcess === "parent") {
+
+ if (aProcess === "parent") {
keyedHistograms = aPayload.keyedHistograms;
- } else if ("processes" in aPayload && keyedHgramsProcess in aPayload.processes &&
- "keyedHistograms" in aPayload.processes[keyedHgramsProcess]) {
- keyedHistograms = aPayload.processes[keyedHgramsProcess].keyedHistograms;
+ } else if ("processes" in aPayload && aProcess in aPayload.processes &&
+ "keyedHistograms" in aPayload.processes[aProcess]) {
+ keyedHistograms = aPayload.processes[aProcess].keyedHistograms;
}
- let hasData = Array.from(keyedHgramsSelect.options).some((option) => {
- let value = option.getAttribute("value");
+ let hasData = gOptions.some((option) => {
+ let value = aProcess;
if (value == "parent") {
return Object.keys(aPayload.keyedHistograms).length > 0;
}
- let keyedHistos = aPayload.processes[value].keyedHistograms;
- return keyedHistos && Object.keys(keyedHistos).length > 0;
+ let histos = aPayload.processes[value].keyedHistograms;
+ return histos && Object.keys(histos).length > 0;
});
- setHasData("keyed-histograms-section", hasData);
+ hasSubsectionData("keyed-histograms-section", hasData);
if (Object.keys(keyedHistograms).length > 0) {
for (let [id, keyed] of Object.entries(keyedHistograms)) {
if (Object.keys(keyed).length > 0) {
KeyedHistogram.render(keyedDiv, id, keyed, {unpacked: true});
}
}
}
},