helper-telemetry.js (3787B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 /* import-globals-from head.js */ 7 8 /** 9 * Reset all telemetry events. 10 */ 11 function setupTelemetryTest() { 12 // Let's reset the counts. 13 Services.telemetry.clearEvents(); 14 15 // Ensure no events have been logged 16 const ALL_CHANNELS = Ci.nsITelemetry.DATASET_ALL_CHANNELS; 17 const snapshot = Services.telemetry.snapshotEvents(ALL_CHANNELS, true); 18 ok(!snapshot.parent, "No events have been logged for the main process"); 19 } 20 /* exported setupTelemetryTest */ 21 22 /** 23 * Check that the logged telemetry events exactly match the array of expected events. 24 * Will compare the number of events, the event methods, and the event extras including 25 * the about:debugging session id. 26 */ 27 function checkTelemetryEvents(expectedEvents, expectedSessionId) { 28 const evts = readAboutDebuggingEvents(); 29 is(evts.length, expectedEvents.length, "Expected number of events"); 30 if (evts.length !== expectedEvents.length) { 31 info("Expected:" + JSON.stringify(expectedEvents, null, 2)); 32 info("Got: " + JSON.stringify(evts, null, 2)); 33 } 34 35 function _eventHasExpectedExtras(e, expectedEvent) { 36 const expectedExtras = Object.keys(expectedEvent.extras); 37 return expectedExtras.every(extra => { 38 return e.extras[extra] === expectedEvent.extras[extra]; 39 }); 40 } 41 42 for (const expectedEvent of expectedEvents) { 43 const sameMethodEvents = evts.filter( 44 e => e.method === expectedEvent.method 45 ); 46 ok( 47 !!sameMethodEvents.length, 48 "Found event for method: " + expectedEvent.method 49 ); 50 51 const sameExtrasEvents = sameMethodEvents.filter(e => 52 _eventHasExpectedExtras(e, expectedEvent) 53 ); 54 Assert.strictEqual( 55 sameExtrasEvents.length, 56 1, 57 "Found exactly one event matching the expected extras" 58 ); 59 if (sameExtrasEvents.length === 0) { 60 info(JSON.stringify(sameMethodEvents)); 61 } 62 is( 63 sameExtrasEvents[0].extras.session_id, 64 expectedSessionId, 65 "Select page event has the expected session" 66 ); 67 } 68 69 return evts; 70 } 71 /* exported checkTelemetryEvents */ 72 73 /** 74 * Retrieve the session id from an "open" event. 75 * Note that calling this will "clear" all the events. 76 */ 77 function getOpenEventSessionId() { 78 const openEvents = readAboutDebuggingEvents().filter( 79 e => e.method === "open_adbg" 80 ); 81 ok(!!openEvents[0], "Found an about:debugging open event"); 82 return openEvents[0].extras.session_id; 83 } 84 /* exported getOpenEventSessionId */ 85 86 /** 87 * Read all the pending events that have "aboutdebugging" as their object property. 88 * WARNING: Calling this method also flushes/clears the events. 89 */ 90 function readAboutDebuggingEvents() { 91 const ALL_CHANNELS = Ci.nsITelemetry.DATASET_ALL_CHANNELS; 92 // Retrieve and clear telemetry events. 93 const snapshot = Services.telemetry.snapshotEvents(ALL_CHANNELS, true); 94 // about:debugging events are logged in the parent process 95 const parentEvents = snapshot.parent || []; 96 97 return parentEvents 98 .map(_toEventObject) 99 .filter(e => e.object === "aboutdebugging"); 100 } 101 /* exported getLoggedEvents */ 102 103 /** 104 * The telemetry event data structure is simply an array. This helper remaps the array to 105 * an object with more user friendly properties. 106 */ 107 function _toEventObject(rawEvent) { 108 return { 109 // Category is typically devtools.main for us. 110 category: rawEvent[1], 111 // Method is the event's name (eg open, select_page etc...) 112 method: rawEvent[2], 113 // Object will usually be aboutdebugging for our tests 114 object: rawEvent[3], 115 // Value is usually empty for devtools events 116 value: rawEvent[4], 117 // Extras contain all the details of the event, including the session_id. 118 extras: rawEvent[5], 119 }; 120 }