Bug 1232917 - List & render custom pings in about:telemetry. r=gfritzsche
authorpenhlenh <penhlenh@gmail.com>
Mon, 29 Feb 2016 01:09:35 +0700
changeset 322318 2590a95c7571baa9f35a62ccf50223ccbe4e8f65
parent 322317 23566cc859df754ebb0b63bc0a2cb498c2f2d9b6
child 322319 7fefbc8e44b87963e30f652a07ade9a63deb6754
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgfritzsche
bugs1232917
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1232917 - List & render custom pings in about:telemetry. r=gfritzsche
toolkit/content/aboutTelemetry.js
toolkit/content/aboutTelemetry.xhtml
toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -12,16 +12,17 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/TelemetryTimestamps.jsm");
 Cu.import("resource://gre/modules/TelemetryController.jsm");
 Cu.import("resource://gre/modules/TelemetrySession.jsm");
 Cu.import("resource://gre/modules/TelemetryArchive.jsm");
 Cu.import("resource://gre/modules/TelemetryUtils.jsm");
 Cu.import("resource://gre/modules/TelemetryLog.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
 
 const Telemetry = Services.telemetry;
 const bundle = Services.strings.createBundle(
   "chrome://global/locale/aboutTelemetry.properties");
 const brandBundle = Services.strings.createBundle(
@@ -311,105 +312,100 @@ var PingPicker = {
   onPingSourceChanged: function() {
     this.update();
   },
 
   onPingDisplayChanged: function() {
     this.update();
   },
 
-  update: function() {
+  update: Task.async(function*() {
     let viewCurrent = document.getElementById("ping-source-current").checked;
     let viewStructured = document.getElementById("ping-source-structured").checked;
     let currentChanged = viewCurrent !== this.viewCurrentPingData;
     let structuredChanged = viewStructured !== this.viewStructuredPingData;
     this.viewCurrentPingData = viewCurrent;
     this.viewStructuredPingData = viewStructured;
 
     if (currentChanged) {
       if (this.viewCurrentPingData) {
         document.getElementById("current-ping-picker").classList.remove("hidden");
         document.getElementById("archived-ping-picker").classList.add("hidden");
         this._updateCurrentPingData();
       } else {
         document.getElementById("current-ping-picker").classList.add("hidden");
-        this._updateArchivedPingList().then(() =>
-          document.getElementById("archived-ping-picker").classList.remove("hidden"));
+        yield this._updateArchivedPingList();
+        document.getElementById("archived-ping-picker").classList.remove("hidden");
       }
     }
 
     if (structuredChanged) {
       if (this.viewStructuredPingData) {
         this._showStructuredPingData();
       } else {
         this._showRawPingData();
       }
     }
-  },
+  }),
 
   _updateCurrentPingData: function() {
     const subsession = document.getElementById("show-subsession-data").checked;
     const ping = TelemetryController.getCurrentPingData(subsession);
     if (!ping) {
       return;
     }
     displayPingData(ping, true);
   },
 
   _updateArchivedPingData: function() {
     let id = this._getSelectedPingId();
-    TelemetryArchive.promiseArchivedPingById(id)
-                    .then((ping) => displayPingData(ping, true));
+    return TelemetryArchive.promiseArchivedPingById(id)
+                           .then((ping) => displayPingData(ping, true));
   },
 
-  _updateArchivedPingList: function() {
-    return TelemetryArchive.promiseArchivedPingList().then((pingList) => {
-      // The archived ping list is sorted in ascending timestamp order,
-      // but descending is more practical for the operations we do here.
-      pingList.reverse();
+  _updateArchivedPingList: Task.async(function*() {
+    let pingList = yield TelemetryArchive.promiseArchivedPingList();
+    // The archived ping list is sorted in ascending timestamp order,
+    // but descending is more practical for the operations we do here.
+    pingList.reverse();
+
+    this._archivedPings = pingList;
 
-      // Currently about:telemetry can only handle the Telemetry session pings,
-      // so we have to filter out everything else.
-      pingList = pingList.filter(
-        (p) => ["main", "saved-session"].indexOf(p.type) != -1);
-      this._archivedPings = pingList;
-
-      // Collect the start dates for all the weeks we have pings for.
-      let weekStart = (date) => {
-        let weekDay = (date.getDay() + 6) % 7;
-        let monday = new Date(date);
-        monday.setDate(date.getDate() - weekDay);
-        return TelemetryUtils.truncateToDays(monday);
-      };
+    // Collect the start dates for all the weeks we have pings for.
+    let weekStart = (date) => {
+      let weekDay = (date.getDay() + 6) % 7;
+      let monday = new Date(date);
+      monday.setDate(date.getDate() - weekDay);
+      return TelemetryUtils.truncateToDays(monday);
+    };
 
-      let weekStartDates = new Set();
-      for (let p of pingList) {
-        weekStartDates.add(weekStart(new Date(p.timestampCreated)).getTime());
-      }
+    let weekStartDates = new Set();
+    for (let p of pingList) {
+      weekStartDates.add(weekStart(new Date(p.timestampCreated)).getTime());
+    }
 
-      // Build a list of the week date ranges we have ping data for.
-      let plusOneWeek = (date) => {
-        let d = date;
-        d.setDate(d.getDate() + 7);
-        return d;
-      };
+    // Build a list of the week date ranges we have ping data for.
+    let plusOneWeek = (date) => {
+      let d = date;
+      d.setDate(d.getDate() + 7);
+      return d;
+    };
 
-      this._weeks = Array.from(weekStartDates.values(), startTime => ({
-        startDate: new Date(startTime),
-        endDate: plusOneWeek(new Date(startTime)),
-      }));
+    this._weeks = Array.from(weekStartDates.values(), startTime => ({
+      startDate: new Date(startTime),
+      endDate: plusOneWeek(new Date(startTime)),
+    }));
 
-      // Render the archive data.
-      this._renderWeeks();
-      this._renderPingList();
+    // Render the archive data.
+    this._renderWeeks();
+    this._renderPingList();
 
-      // Update the displayed ping.
-      this._updateArchivedPingData();
-    });
-  },
+    // Update the displayed ping.
+    yield this._updateArchivedPingData();
+  }),
 
   _renderWeeks: function() {
     let weekSelector = document.getElementById("choose-ping-week");
     removeAllChildNodes(weekSelector);
 
     let index = 0;
     for (let week of this._weeks) {
       let text = shortDateString(week.startDate)
@@ -991,16 +987,27 @@ var StackRenderer = {
       aPrefix + "-title", aFormatArgs, aFormatArgs.length);
     titleElement.appendChild(document.createTextNode(titleText));
 
     div.appendChild(titleElement);
     div.appendChild(document.createElement("br"));
   }
 };
 
+var RawPayload = {
+  /**
+   * Renders the raw payload
+   */
+  render: function(aPing) {
+    setHasData("raw-payload-section", true);
+    let pre = document.getElementById("raw-payload-data-pre");
+    pre.textContent = JSON.stringify(aPing.payload, null, 2);
+  }
+};
+
 function SymbolicationRequest(aPrefix, aRenderHeader,
                               aMemoryMap, aStacks, aDurations = null) {
   this.prefix = aPrefix;
   this.renderHeader = aRenderHeader;
   this.memoryMap = aMemoryMap;
   this.stacks = aStacks;
   this.durations = aDurations;
 }
@@ -1771,16 +1778,41 @@ function renderPayloadList(ping) {
     text = bundle.formatStringFromName("childPayloadN", [payloadIndex], 1);
     content = document.createTextNode(text);
     option.appendChild(content);
     option.setAttribute("value", payloadIndex);
     listEl.appendChild(option);
   }
 }
 
+function toggleElementHidden(element, isHidden) {
+  if (isHidden) {
+    element.classList.add("hidden");
+  } else {
+    element.classList.remove("hidden");
+  }
+}
+
+function togglePingSections(isMainPing) {
+  // We always show the sections that are "common" to all pings.
+  // The raw payload section is only used for pings other than "main" and "saved-session".
+  let commonSections = new Set(["general-data-section", "environment-data-section"]);
+  let otherPingSections = new Set(["raw-payload-section"]);
+
+  let elements = document.getElementById("structured-ping-data-section").children;
+  for (let section of elements) {
+    if (commonSections.has(section.id)) {
+      continue;
+    }
+
+    let showElement = isMainPing != otherPingSections.has(section.id);
+    toggleElementHidden(section, !showElement);
+  }
+}
+
 function displayPingData(ping, updatePayloadList = false) {
   gPingData = ping;
 
   // Render raw ping data.
   let pre = document.getElementById("raw-ping-data");
   pre.textContent = JSON.stringify(gPingData, null, 2);
 
   // Update the structured data rendering.
@@ -1793,16 +1825,26 @@ function displayPingData(ping, updatePay
   }
 
   // Show general data.
   GeneralData.render(ping);
 
   // Show environment data.
   EnvironmentData.render(ping);
 
+  // We only have special rendering code for the payloads from "main" pings.
+  // For any other pings we just render the raw JSON payload.
+  let isMainPing = (ping.type == "main" || ping.type == "saved-session");
+  togglePingSections(isMainPing);
+
+  if (!isMainPing) {
+    RawPayload.render(ping);
+    return;
+  }
+
   // Show telemetry log.
   TelLog.render(ping);
 
   // Show slow SQL stats
   SlowSQL.render(ping);
 
   // Show chrome hang stacks
   ChromeHangs.render(ping);
--- a/toolkit/content/aboutTelemetry.xhtml
+++ b/toolkit/content/aboutTelemetry.xhtml
@@ -236,13 +236,22 @@
         <input type="checkbox" class="statebox"/>
         <h1 class="section-name">&aboutTelemetry.addonHistogramsSection;</h1>
         <span class="toggle-caption">&aboutTelemetry.toggle;</span>
         <span class="empty-caption">&aboutTelemetry.emptySection;</span>
         <div id="addon-histograms" class="data">
         </div>
       </section>
 
+      <section id="raw-payload-section" class="data-section">
+        <input type="checkbox" class="statebox"/>
+        <h1 class="section-name">&aboutTelemetry.rawPayload;</h1>
+        <span class="toggle-caption">&aboutTelemetry.toggle;</span>
+        <span class="empty-caption">&aboutTelemetry.emptySection;</span>
+        <div id="raw-payload-data" class="data">
+          <pre id="raw-payload-data-pre"></pre>
+        </div>
+      </section>
     </div>
 
   </body>
 
 </html>
--- a/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
@@ -150,8 +150,12 @@ Ping
 
 <!ENTITY aboutTelemetry.filterText "
   Filter (strings or /regexp/)
 ">
 
 <!ENTITY aboutTelemetry.payloadChoiceHeader "
   Payload
 ">
+
+<!ENTITY aboutTelemetry.rawPayload "
+  Raw Payload
+">
\ No newline at end of file