Bug 701863 - clone STARTUP_* histograms properly; r=taras
authorNathan Froyd <froydnj@mozilla.com>
Fri, 06 Jan 2012 14:40:45 -0500
changeset 85186 488c9feac9bd35bb0d02823193c508f1b14a1593
parent 85185 4c6086b7e2fab725f2d3b3b77d575cd028029beb
child 85187 555ca2958f6f146ac075496ec7a1dfe9f0238781
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstaras
bugs701863
milestone12.0a1
Bug 701863 - clone STARTUP_* histograms properly; r=taras
toolkit/components/telemetry/Telemetry.cpp
toolkit/components/telemetry/TelemetryPing.js
toolkit/components/telemetry/nsITelemetry.idl
toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -106,32 +106,34 @@ StatisticsRecorder gStatisticsRecorder;
 // Hardcoded probes
 struct TelemetryHistogram {
   Histogram *histogram;
   const char *id;
   PRUint32 min;
   PRUint32 max;
   PRUint32 bucketCount;
   PRUint32 histogramType;
+  const char *comment;
 };
 
 // Perform the checks at the beginning of HistogramGet at compile time, so
 // that if people add incorrect histogram definitions, they get compiler
 // errors.
 #define HISTOGRAM(id, min, max, bucket_count, histogram_type, b) \
   PR_STATIC_ASSERT(nsITelemetry::HISTOGRAM_ ## histogram_type == nsITelemetry::HISTOGRAM_BOOLEAN || \
                    (min < max && bucket_count > 2 && min >= 1));
 
 #include "TelemetryHistograms.h"
 
 #undef HISTOGRAM
 
 const TelemetryHistogram gHistograms[] = {
-#define HISTOGRAM(id, min, max, bucket_count, histogram_type, b) \
-  { NULL, NS_STRINGIFY(id), min, max, bucket_count, nsITelemetry::HISTOGRAM_ ## histogram_type },
+#define HISTOGRAM(id, min, max, bucket_count, histogram_type, comment) \
+  { NULL, NS_STRINGIFY(id), min, max, bucket_count, \
+    nsITelemetry::HISTOGRAM_ ## histogram_type, comment },
 
 #include "TelemetryHistograms.h"
 
 #undef HISTOGRAM
 };
 
 bool
 TelemetryHistogramType(Histogram *h, PRUint32 *result)
@@ -227,17 +229,16 @@ ReflectHistogramSnapshot(JSContext *cx, 
         && JS_DefineProperty(cx, obj, "max", INT_TO_JSVAL(h->declared_max()), NULL, NULL, JSPROP_ENUMERATE)
         && JS_DefineProperty(cx, obj, "histogram_type", INT_TO_JSVAL(h->histogram_type()), NULL, NULL, JSPROP_ENUMERATE)
         && JS_DefineProperty(cx, obj, "sum", DOUBLE_TO_JSVAL(ss.sum()), NULL, NULL, JSPROP_ENUMERATE)
         && (rarray = JS_NewArrayObject(cx, count, NULL))
         && JS_DefineProperty(cx, obj, "ranges", OBJECT_TO_JSVAL(rarray), NULL, NULL, JSPROP_ENUMERATE)
         && FillRanges(cx, rarray, h)
         && (counts_array = JS_NewArrayObject(cx, count, NULL))
         && JS_DefineProperty(cx, obj, "counts", OBJECT_TO_JSVAL(counts_array), NULL, NULL, JSPROP_ENUMERATE)
-        && JS_DefineProperty(cx, obj, "static", static_histogram, NULL, NULL, JSPROP_ENUMERATE)
         )) {
     return JS_FALSE;
   }
   for (size_t i = 0; i < count; i++) {
     if (!JS_DefineElement(cx, counts_array, i, INT_TO_JSVAL(ss.counts(i)), NULL, NULL, JSPROP_ENUMERATE)) {
       return JS_FALSE;
     }
   }
@@ -502,16 +503,39 @@ TelemetryImpl::GetSlowSQL(JSContext *cx,
   // Add info about slow SQL queries on other threads
   if (!AddSQLInfo(cx, root_obj, false))
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+TelemetryImpl::GetRegisteredHistograms(JSContext *cx, jsval *ret)
+{
+  size_t count = ArrayLength(gHistograms);
+  JSObject *info = JS_NewObject(cx, NULL, NULL, NULL);
+  if (!info)
+    return NS_ERROR_FAILURE;
+
+  for (size_t i = 0; i < count; ++i) {
+    JSString *comment = JS_InternString(cx, gHistograms[i].comment);
+    
+    if (!(comment
+          && JS_DefineProperty(cx, info, gHistograms[i].id,
+                               STRING_TO_JSVAL(comment), NULL, NULL,
+                               JSPROP_ENUMERATE))) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  *ret = OBJECT_TO_JSVAL(info);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 TelemetryImpl::GetHistogramById(const nsACString &name, JSContext *cx, jsval *ret)
 {
   Histogram *h;
   nsresult rv = GetHistogramByName(name, &h);
   if (NS_FAILED(rv))
     return rv;
 
   return WrapAndReturnHistogram(h, cx, ret);
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -124,40 +124,31 @@ function getSimpleMeasurements() {
 }
 
 function TelemetryPing() {}
 
 TelemetryPing.prototype = {
   _histograms: {},
   _initialized: false,
   _prevValues: {},
-  _sqliteOverhead: {},
 
   /**
    * Returns a set of histograms that can be converted into JSON
    * @return a snapshot of the histograms of form:
    *  { histogram_name: {range:[minvalue,maxvalue], bucket_count:<number of buckets>,
    *    histogram_type: <0 for exponential, 1 for linear>, bucketX:countX, ....} ...}
    * where bucket[XY], count[XY] are positive integers.
    */
   getHistograms: function getHistograms() {
     let hls = Telemetry.histogramSnapshots;
+    let info = Telemetry.registeredHistograms;
     let ret = {};
 
-    // bug 701583: report sqlite overhead on startup
-    for (let key in this._sqliteOverhead) {
-      hls[key] = this._sqliteOverhead[key];
-    }
-
-    for (let key in hls) {
-      let hgram = hls[key];
-      if (!hgram.static)
-        continue;
-
-      let r = hgram.ranges;
+    function processHistogram(name, hgram) {
+      let r = hgram.ranges;;
       let c = hgram.counts;
       let retgram = {
         range: [r[1], r[r.length - 1]],
         bucket_count: r.length,
         histogram_type: hgram.histogram_type,
         values: {},
         sum: hgram.sum
       };
@@ -177,18 +168,28 @@ TelemetryPing.prototype = {
         first = false;
         last = i + 1;
         retgram.values[r[i]] = value;
       }
 
       // add an upper bound
       if (last && last < c.length)
         retgram.values[r[last]] = 0;
-      ret[key] = retgram;
+      ret[name] = retgram;
+    };
+
+    for (let name in hls) {
+      if (info[name]) {
+	processHistogram(name, hls[name]);
+	let startup_name = "STARTUP_" + name;
+	if (hls[startup_name])
+	  processHistogram(startup_name, hls[startup_name]);
+      }
     }
+
     return ret;
   },
 
   addValue: function addValue(name, id, val) {
     let h = this._histograms[name];
     if (!h) {
       h = Telemetry.getHistogramById(id);
       this._histograms[name] = h;
@@ -302,21 +303,21 @@ TelemetryPing.prototype = {
       this.addValue(mr.path, id, val);
     }
   },
   
   /** 
    * Make a copy of sqlite histograms on startup
    */
   gatherStartupSqlite: function gatherStartupSqlite() {
-    let hls = Telemetry.histogramSnapshots;
+    let info = Telemetry.registeredHistograms;
     let sqlite_re = /SQLITE/;
-    for (let key in hls) {
-      if (sqlite_re.test(key))
-        this._sqliteOverhead["STARTUP_" + key] = hls[key];
+    for (let name in info) {
+      if (sqlite_re.test(name))
+        Telemetry.histogramFrom("STARTUP_" + name, name);
     }
   },
 
   /**
    * Send data to the server. Record success/send-time in histograms
    */
   send: function send(reason, server) {
     // populate histograms one last time
--- a/toolkit/components/telemetry/nsITelemetry.idl
+++ b/toolkit/components/telemetry/nsITelemetry.idl
@@ -80,16 +80,24 @@ interface nsITelemetry : nsISupports
    *   otherThreads: Slow statements that executed on a non-main thread
    *   sqlString - String of the offending prepared statement
    *   hit count - The number of times this statement required longer than the threshold time to execute
    *   total time - The sum of all execution times above the threshold time for this statement
    */
   [implicit_jscontext]
   readonly attribute jsval slowSQL;
 
+  /**
+   * An object whose properties are the names of histograms defined in
+   * TelemetryHistograms.h and whose corresponding values are the textual
+   * comments associated with said histograms.
+   */
+  [implicit_jscontext]
+  readonly attribute jsval registeredHistograms;
+
   /** 
    * Create and return a histogram where bucket sizes increase exponentially. Parameters:
    *
    * @param name Unique histogram name
    * @param min - Minimal bucket size
    * @param max - Maximum bucket size
    * @param bucket_count - number of buckets in the histogram.
    * @param type - HISTOGRAM_EXPONENTIAL or HISTOGRAM_LINEAR
--- a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
+++ b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
@@ -28,18 +28,16 @@ function test_histogram(histogram_type, 
   }
   var hgrams = Telemetry.histogramSnapshots
   gh = hgrams[name]
   do_check_eq(gh.histogram_type, histogram_type);
 
   do_check_eq(gh.min, min)
   do_check_eq(gh.max, max)
 
-  do_check_false(gh.static); 
-
   // Check that booleans work with nonboolean histograms
   h.add(false);
   h.add(true);
   var s = h.snapshot().counts;
   do_check_eq(s[0], 2)
   do_check_eq(s[1], 2)
 }
 
@@ -83,17 +81,16 @@ function test_getHistogramById() {
   } catch (e) {
     
   }
   var h = Telemetry.getHistogramById("CYCLE_COLLECTOR");
   var s = h.snapshot();
   do_check_eq(s.histogram_type, Telemetry.HISTOGRAM_EXPONENTIAL);
   do_check_eq(s.min, 1);
   do_check_eq(s.max, 10000);
-  do_check_true(s.static);
 }
 
 function test_getSlowSQL() {
   var slow = Telemetry.slowSQL;
   do_check_true(("mainThread" in slow) && ("otherThreads" in slow));
 }
 
 // Check that telemetry doesn't record in private mode