Bug 1316281 - Part 2 - Record search event in Telemetry. r=dexter,mak data-review=rweiss

This commit is contained in:
Georg Fritzsche 2016-12-02 12:17:12 +01:00
parent fe78815dce
commit dc328f2736
7 changed files with 118 additions and 22 deletions

View File

@ -293,29 +293,34 @@ let BrowserUsageTelemetry = {
}
// Dispatch the search signal to other handlers.
this._handleSearchAction(source, details);
this._handleSearchAction(engine, source, details);
},
_handleSearchAction(source, details) {
_recordSearch(engine, source, action = null) {
let scalarKey = action ? "search_" + action : "search";
Services.telemetry.keyedScalarAdd("browser.engagement.navigation." + source,
scalarKey, 1);
Services.telemetry.recordEvent("navigation", "search", source, action,
{ engine: getSearchEngineId(engine) });
},
_handleSearchAction(engine, source, details) {
switch (source) {
case "urlbar":
case "oneoff-urlbar":
case "searchbar":
case "oneoff-searchbar":
case "unknown": // Edge case: this is the searchbar (see bug 1195733 comment 7).
this._handleSearchAndUrlbar(source, details);
this._handleSearchAndUrlbar(engine, source, details);
break;
case "abouthome":
Services.telemetry.keyedScalarAdd("browser.engagement.navigation.about_home",
"search_enter", 1);
this._recordSearch(engine, "about_home", "enter");
break;
case "newtab":
Services.telemetry.keyedScalarAdd("browser.engagement.navigation.about_newtab",
"search_enter", 1);
this._recordSearch(engine, "about_newtab", "enter");
break;
case "contextmenu":
Services.telemetry.keyedScalarAdd("browser.engagement.navigation.contextmenu",
"search", 1);
this._recordSearch(engine, "contextmenu");
break;
}
},
@ -324,15 +329,14 @@ let BrowserUsageTelemetry = {
* This function handles the "urlbar", "urlbar-oneoff", "searchbar" and
* "searchbar-oneoff" sources.
*/
_handleSearchAndUrlbar(source, details) {
_handleSearchAndUrlbar(engine, source, details) {
// We want "urlbar" and "urlbar-oneoff" (and similar cases) to go in the same
// scalar, but in a different key.
// When using one-offs in the searchbar we get an "unknown" source. See bug
// 1195733 comment 7 for the context. Fix-up the label here.
const plainSourceName =
const sourceName =
(source === "unknown") ? "searchbar" : source.replace("oneoff-", "");
const scalarName = "browser.engagement.navigation." + plainSourceName;
const isOneOff = !!details.isOneOff;
if (isOneOff) {
@ -346,25 +350,24 @@ let BrowserUsageTelemetry = {
return;
}
// If that's a legit one-off search signal, increment the scalar using the
// relative key.
Services.telemetry.keyedScalarAdd(scalarName, "search_oneoff", 1);
// If that's a legit one-off search signal, record it using the relative key.
this._recordSearch(engine, sourceName, "oneoff");
return;
}
// The search was not a one-off. It was a search with the default search engine.
if (details.isSuggestion) {
// It came from a suggested search, so count it as such.
Services.telemetry.keyedScalarAdd(scalarName, "search_suggestion", 1);
this._recordSearch(engine, sourceName, "suggestion");
return;
} else if (details.isAlias) {
// This one came from a search that used an alias.
Services.telemetry.keyedScalarAdd(scalarName, "search_alias", 1);
this._recordSearch(engine, sourceName, "alias");
return;
}
// The search signal was generated by typing something and pressing enter.
Services.telemetry.keyedScalarAdd(scalarName, "search_enter", 1);
this._recordSearch(engine, sourceName, "enter");
},
/**

View File

@ -37,8 +37,9 @@ add_task(function* setup() {
});
add_task(function* test_context_menu() {
// Let's reset the counts.
// Let's reset the Telemetry data.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
// Open a new tab with a page containing some text.
@ -64,7 +65,7 @@ add_task(function* test_context_menu() {
let searchItem = contextMenu.getElementsByAttribute("id", "context-searchselect")[0];
searchItem.click();
info("Validate the search counts.");
info("Validate the search metrics.");
const scalars =
Services.telemetry.snapshotKeyedScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
checkKeyedScalar(scalars, SCALAR_CONTEXT_MENU, "search", 1);
@ -74,6 +75,11 @@ add_task(function* test_context_menu() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.contextmenu', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "contextmenu", null, {engine: "other-MozSearch"}]]);
contextMenu.hidePopup();
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
yield BrowserTestUtils.removeTab(tab);
@ -82,6 +88,7 @@ add_task(function* test_context_menu() {
add_task(function* test_about_newtab() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
@ -105,5 +112,10 @@ add_task(function* test_about_newtab() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.newtab', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "about_newtab", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});

View File

@ -41,6 +41,7 @@ add_task(function* setup() {
add_task(function* test_abouthome_simpleQuery() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
@ -74,5 +75,10 @@ add_task(function* test_abouthome_simpleQuery() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.abouthome', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "about_home", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});

View File

@ -81,6 +81,7 @@ add_task(function* setup() {
add_task(function* test_plainQuery() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
@ -101,12 +102,18 @@ add_task(function* test_plainQuery() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.searchbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_oneOff() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
@ -130,12 +137,18 @@ add_task(function* test_oneOff() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch2.searchbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "oneoff", {engine: "other-MozSearch2"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_suggestion() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
// Create an engine to generate search suggestions and add it as default
@ -168,7 +181,13 @@ add_task(function* test_suggestion() {
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-' + suggestionEngine.name + '.searchbar', 1);
let searchEngineId = 'other-' + suggestionEngine.name;
checkKeyedHistogram(search_hist, searchEngineId + '.searchbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "suggestion", {engine: searchEngineId}]]);
Services.search.currentEngine = previousEngine;
Services.search.removeEngine(suggestionEngine);

View File

@ -74,6 +74,7 @@ add_task(function* setup() {
add_task(function* test_simpleQuery() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
@ -94,12 +95,18 @@ add_task(function* test_simpleQuery() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_searchAlias() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
@ -120,12 +127,18 @@ add_task(function* test_searchAlias() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "alias", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_oneOff() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
@ -149,12 +162,18 @@ add_task(function* test_oneOff() {
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-MozSearch.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "oneoff", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_suggestion() {
// Let's reset the counts.
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();
let search_hist = getSearchCountsHistogram();
// Create an engine to generate search suggestions and add it as default
@ -187,7 +206,13 @@ add_task(function* test_suggestion() {
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, 'other-' + suggestionEngine.name + '.urlbar', 1);
let searchEngineId = 'other-' + suggestionEngine.name;
checkKeyedHistogram(search_hist, searchEngineId + '.urlbar', 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "suggestion", {engine: searchEngineId}]]);
Services.search.currentEngine = previousEngine;
Services.search.removeEngine(suggestionEngine);

View File

@ -95,3 +95,19 @@ function checkKeyedHistogram(h, key, expectedValue) {
Assert.ok(key in snapshot, `The histogram must contain ${key}.`);
Assert.equal(snapshot[key].sum, expectedValue, `The key ${key} must contain ${expectedValue}.`);
}
function checkEvents(events, expectedEvents) {
if (!Services.telemetry.canRecordExtended) {
// Currently we only collect the tested events when extended Telemetry is enabled.
return;
}
Assert.equal(events.length, expectedEvents.length, "Should have matching amount of events.");
// Strip timestamps from the events for easier comparison.
events = events.map(e => e.slice(1));
for (let i = 0; i < events.length; ++i) {
Assert.deepEqual(events[i], expectedEvents[i], "Events should match.");
}
}

View File

@ -1,3 +1,18 @@
navigation:
- methods: ["search"]
objects: ["about_home", "about_newtab", "contextmenu", "oneoff",
"suggestion", "alias", "enter", "searchbar", "urlbar"]
release_channel_collection: opt-in
description: >
This is recorded on each search navigation.
The value field records the action used to trigger the search:
"enter", "oneoff", "suggestion", "alias", null (for contextmenu)
bug_numbers: [1316281]
notification_emails: ["past@mozilla.com"]
expiry_version: "58.0"
extra_keys:
engine: The id of the search engine used.
# This category contains event entries used for Telemetry tests.
# They will not be sent out with any pings.
telemetry.test: