diff --git a/apps/system/js/advanced_telemetry.js b/apps/system/js/advanced_telemetry.js index 81110a08bc99..f9277adb36c5 100644 --- a/apps/system/js/advanced_telemetry.js +++ b/apps/system/js/advanced_telemetry.js @@ -96,7 +96,7 @@ var array = longLine.match(/.{1,1000}/g); // Output each chunk to the console array.forEach(function (value) { - console.log(AT_DEBUG_PREFIX + value); + console.log(value); }); } else { // Its < what ADB can handle so just output it normally. @@ -383,7 +383,7 @@ // to accumulate until the retry interval expires. self.startRetryBatch(); } - + self.request.packHistograms(); self.request.send({ timeout: AT.REPORT_TIMEOUT, onload: onload, @@ -430,9 +430,10 @@ // Merge the new metrics into the old metrics and then transmit the // result to the server. function mergePayloads(payloadOld, payloadNew) { - mergeKeyed(payloadOld.keyedHistograms, payloadOld, payloadNew); - mergeLists(payloadOld.addonHistograms, - payloadNew.addonHistograms); + mergeHistogramType(payloadOld.keyedHistograms, payloadOld, payloadNew, + 'keyedHistograms'); + mergeHistogramType(payloadOld.addonHistograms, payloadOld, payloadNew, + 'addonHistograms'); return payloadOld; } }); @@ -443,7 +444,7 @@ oldHist.log_sum += newHist.log_sum; oldHist.log_sum_squares += newHist.log_sum_squares; - for(var i = 0; i < oldHist.counts.length; i++) { + for (var i = 0; i < oldHist.counts.length; i++) { oldHist.counts[i] += newHist.counts[i]; } } @@ -451,11 +452,11 @@ function mergeLists(oldList, newList) { var histMap = new Map(); - for(var keyOld in oldList) { + for (var keyOld in oldList) { histMap.set(keyOld, oldList[keyOld]); } - for(var keyNew in newList) { + for (var keyNew in newList) { if (histMap.has(keyNew)) { mergeHistogram(oldList[keyNew], newList[keyNew]); } else { @@ -464,16 +465,16 @@ } } - function mergeKeyed(keyedOldHist, payloadOld, payloadNew) { + function mergeHistogramType(oldHist, payloadOld, payloadNew, histType) { var keyedOldMapKeys = new Map(); - for(var keyOld in keyedOldHist) { - keyedOldMapKeys.set(keyOld, keyedOldHist[keyOld]); + for (var keyOld in oldHist) { + keyedOldMapKeys.set(keyOld, oldHist[keyOld]); } - var keyedNew = payloadNew.keyedHistograms; - var keyedOld = payloadOld.keyedHistograms; - for(var keyNew in keyedNew) { + var keyedNew = payloadNew[histType]; + var keyedOld = payloadOld[histType]; + for (var keyNew in keyedNew) { if (keyedOldMapKeys.has(keyNew)) { mergeLists(keyedOld[keyNew], keyedNew[keyNew]); } else { @@ -512,6 +513,82 @@ return JSON.stringify(packet); }; + // This method converts a raw histogram with the .counts and .ranges arrays + // in it to one with just .values using the dict format. + AdvancedTelemetryPing.prototype.packHistogram = + function packHistogram(hgram) { + //Constant for Histogram types + const HISTOGRAM_EXP = 0; + + if (typeof hgram.ranges === 'undefined' || + typeof hgram.counts === 'undefined') { + return 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 + }; + + if (hgram.histogram_type === HISTOGRAM_EXP) { + retgram.log_sum = hgram.log_sum; + retgram.log_sum_squares = hgram.log_sum_squares; + } else { + retgram.sum_squares_lo = hgram.sum_squares_lo; + retgram.sum_squares_hi = hgram.sum_squares_hi; + } + + let first = true; + let last = 0; + + for (let i = 0; i < c.length; i++) { + let value = c[i]; + if (!value) { + continue; + } + + // add a lower bound + if (i && first) { + retgram.values[r[i - 1]] = 0; + } + first = false; + last = i + 1; + retgram.values[r[i]] = value; + } + + // add an upper bound + if (last && last < c.length) { + retgram.values[r[last]] = 0; + } + return retgram; + }, + + // This method loops through the payload of histograms and converts each + // histogram payload to the 'dict' format required by the server for parsing. + AdvancedTelemetryPing.prototype.packHistograms = function() { + var nameAddonHist = this.packet.payload.addonHistograms; + var nameKeyHist = this.packet.payload.keyedHistograms; + + // Pack the Addon Histograms. + for (var addon in nameAddonHist) { + for (var hist in nameAddonHist[addon]) { + nameAddonHist[addon][hist] = + this.packHistogram(nameAddonHist[addon][hist]); + } + } + + // Pack the Keyed Histograms. + for (var key in nameKeyHist) { + for (var hist2 in nameKeyHist[key]) { + nameKeyHist[key][hist2] = this.packHistogram(nameKeyHist[key][hist2]); + } + } + }; + AdvancedTelemetryPing.prototype.send = function(xhrAttrs) { return new Promise((resolve, reject) => { this.data = this.getData(this.packet); diff --git a/apps/system/test/unit/advanced_telemetry_test.js b/apps/system/test/unit/advanced_telemetry_test.js index 294a9024fe82..755a5259fc6f 100644 --- a/apps/system/test/unit/advanced_telemetry_test.js +++ b/apps/system/test/unit/advanced_telemetry_test.js @@ -65,15 +65,17 @@ suite('AdvancedTelemetry:', function() { } }, addonHistograms: { - COMM_SMS: { - min: 1, - max: 1000, - histogram_type:0, - sum:58, - log_sum: 10.935960054397583, - log_sum_squares: 29.95399808883667, - ranges: [0,1,2,5,12,29,70,170,412,1000], - counts:[0,0,0,0,4,0,0,0,0,0] + addon1: { + COMM_SMS: { + min: 1, + max: 1000, + histogram_type: 0, + sum: 58, + log_sum: 10.935960054397583, + log_sum_squares: 29.95399808883667, + ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000], + counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0] + } } } }; @@ -158,25 +160,29 @@ suite('AdvancedTelemetry:', function() { } }, addonHistograms: { - COMM_SMS: { - min: 1, - max: 1000, - histogram_type:0, - sum:58, - log_sum: 10.935960054397583, - log_sum_squares: 29.95399808883667, - ranges: [0,1,2,5,12,29,70,170,412,1000], - counts:[0,0,0,0,4,0,0,0,0,0] + addon1: { + COMM_SMS: { + min: 1, + max: 1000, + histogram_type: 0, + sum: 58, + log_sum: 10.935960054397583, + log_sum_squares: 29.95399808883667, + ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000], + counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0] + } }, - COMM_DIALER: { - min: 1, - max: 1000, - histogram_type:0, - sum:58, - log_sum: 10.935960054397583, - log_sum_squares: 29.95399808883667, - ranges: [0,1,2,5,12,29,70,170,412,1000], - counts:[0,0,0,0,4,0,0,0,0,0] + addon2: { + COMM_DIALER: { + min: 1, + max: 1000, + histogram_type: 0, + sum: 58, + log_sum: 10.935960054397583, + log_sum_squares: 29.95399808883667, + ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000], + counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0] + } } } }; @@ -241,20 +247,24 @@ suite('AdvancedTelemetry:', function() { } }, addonHistograms:{ - COMM_SMS:{ - min:1,max:1000,histogram_type:0, - sum:116, - log_sum:21.871920108795166, - log_sum_squares:59.90799617767334, - ranges:[0,1,2,5,12,29,70,170,412,1000], - counts:[0,0,0,0,8,0,0,0,0,0]}, - COMM_DIALER:{ - min:1,max:1000,histogram_type:0, - sum:58, - log_sum:10.935960054397583, - log_sum_squares:29.95399808883667, - ranges:[0,1,2,5,12,29,70,170,412,1000], - counts:[0,0,0,0,4,0,0,0,0,0]} + addon1: { + COMM_SMS: { + min: 1, max: 1000, histogram_type: 0, + sum: 116, + log_sum: 21.871920108795166, + log_sum_squares: 59.90799617767334, + ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000], + counts: [0, 0, 0, 0, 8, 0, 0, 0, 0, 0]} + }, + addon2: { + COMM_DIALER: { + min: 1, max: 1000, histogram_type: 0, + sum: 58, + log_sum: 10.935960054397583, + log_sum_squares: 29.95399808883667, + ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000], + counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]} + } } }; @@ -306,7 +316,7 @@ suite('AdvancedTelemetry:', function() { suite('Sending the Metrics:', function() { var at, clock, XHR, xhr, mockSettings; var transmitSpy; - var wrapper; + var wrapper, packedWrapper; var gzipCompressedData = new Uint8Array([1,2,3,4,5]); setup(function(done) { @@ -342,7 +352,7 @@ suite('AdvancedTelemetry:', function() { } }, addonHistograms: { - communications: { + addon3: { rn_metric: { min: 1, max: 10000, @@ -358,6 +368,52 @@ suite('AdvancedTelemetry:', function() { } }; + packedWrapper = { + type: AdvancedTelemetry.REASON, + id: 'uuid', + creationDate: 'testDate', + version: AdvancedTelemetry.TELEMETRY_VERSION, + application: { + architecture: 'arm', + buildId: 'build', + name: AdvancedTelemetry.TELEMETRY_APP_NAME, + version: '43', + vendor: 'Mozilla', + platformVersion: '43', + xpcomAbi: 'arm-gcc3', + channel: 'default' + }, + clientId: 'uuid', + payload: { + keyedHistograms: { + DEVTOOLS_HUD_REFLOW_DURATION: { + verticalhome: { + range: [1, 1000], + bucket_count:10, + histogram_type: 0, + values: {'5':0, '12':2, '29':1, '70':1, '170':0}, + sum: 189, + log_sum:14.329224586486816, + log_sum_squares: 53.6346640586853 + } + } + }, + addonHistograms: { + addon3: { + rn_metric: { + range: [1, 10000], + bucket_count: 10, + histogram_type: 1, + values: {'0': 0, '1': 1, '1251': 0}, + sum: 99, + sum_squares_lo: 9801, + sum_squares_hi: 0 + } + } + } + } + }; + transmitSpy = this.sinon.spy(AdvancedTelemetry.prototype, 'transmit'); clock = this.sinon.useFakeTimers(); XHR = sinon.useFakeXMLHttpRequest(); @@ -478,9 +534,9 @@ suite('AdvancedTelemetry:', function() { assert.equal(req.clientId, wrapper.clientId); // Verify the application object picked up the settings correctly. - assert.deepEqual(req.application, wrapper.application); - // Verify that the Histograms are intact. - assert.deepEqual(req.payload, wrapper.payload); + assert.deepEqual(req.application, packedWrapper.application); + // Verify that the Histograms are intact and are properly packed. + assert.deepEqual(req.payload, packedWrapper.payload); done(); });