Bug 1024757 - Translation FHR should report missed opportunities due to the detected language not being part of the list of supported languages. r=mdeboer
authorFelipe Gomes <felipc@gmail.com>
Thu, 19 Jun 2014 13:42:29 -0300
changeset 189619 f480ffb3e0b377749d938b39e831b8689372a664
parent 189618 3e7098e4cc46ca5a5976fd8b9af65a9e5a057566
child 189620 6781dc563e9506d03f14f9947c39fa39900e8d92
push id26992
push userkwierso@gmail.com
push dateFri, 20 Jun 2014 01:07:53 +0000
treeherdermozilla-central@bdac18bd6c74 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmdeboer
bugs1024757
milestone33.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 1024757 - Translation FHR should report missed opportunities due to the detected language not being part of the list of supported languages. r=mdeboer
browser/components/translation/Translation.jsm
browser/components/translation/test/unit/test_healthreport.js
services/healthreport/docs/dataformat.rst
--- a/browser/components/translation/Translation.jsm
+++ b/browser/components/translation/Translation.jsm
@@ -43,19 +43,26 @@ this.Translation = {
                                       .getSelectedLocale("global")
                                       .split("-")[0];
     }
     return this._defaultTargetLanguage;
   },
 
   documentStateReceived: function(aBrowser, aData) {
     if (aData.state == this.STATE_OFFER) {
-      if (this.supportedSourceLanguages.indexOf(aData.detectedLanguage) == -1 ||
-          aData.detectedLanguage == this.defaultTargetLanguage)
+      if (aData.detectedLanguage == this.defaultTargetLanguage) {
+        // Detected language is the same as the user's locale.
         return;
+      }
+
+      if (this.supportedSourceLanguages.indexOf(aData.detectedLanguage) == -1) {
+        // Detected language is not part of the supported languages.
+        TranslationHealthReport.recordMissedTranslationOpportunity(aData.detectedLanguage);
+        return;
+      }
 
       TranslationHealthReport.recordTranslationOpportunity(aData.detectedLanguage);
     }
 
     if (!Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI))
       return;
 
     if (!aBrowser.translationUI)
@@ -237,16 +244,27 @@ let TranslationHealthReport = {
    * Record a translation opportunity in the health report.
    * @param language
    *        The language of the page.
    */
   recordTranslationOpportunity: function (language) {
     this._withProvider(provider => provider.recordTranslationOpportunity(language));
    },
 
+  /**
+   * Record a missed translation opportunity in the health report.
+   * A missed opportunity is when the language detected is not part
+   * of the supported languages.
+   * @param language
+   *        The language of the page.
+   */
+  recordMissedTranslationOpportunity: function (language) {
+    this._withProvider(provider => provider.recordMissedTranslationOpportunity(language));
+  },
+
    /**
    * Record a translation in the health report.
    * @param langFrom
    *        The language of the page.
    * @param langTo
    *        The language translated to
    * @param numCharacters
    *        The number of characters that were translated
@@ -316,19 +334,21 @@ function TranslationMeasurement1() {
 TranslationMeasurement1.prototype = Object.freeze({
   __proto__: Metrics.Measurement.prototype,
 
   name: "translation",
   version: 1,
 
   fields: {
     translationOpportunityCount: DAILY_COUNTER_FIELD,
+    missedTranslationOpportunityCount: DAILY_COUNTER_FIELD,
     pageTranslatedCount: DAILY_COUNTER_FIELD,
     charactersTranslatedCount: DAILY_COUNTER_FIELD,
     translationOpportunityCountsByLanguage: DAILY_LAST_TEXT_FIELD,
+    missedTranslationOpportunityCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     pageTranslatedCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     detectedLanguageChangedBefore: DAILY_COUNTER_FIELD,
     detectedLanguageChangedAfter: DAILY_COUNTER_FIELD,
     detectLanguageEnabled: DAILY_LAST_NUMERIC_FIELD,
     showTranslationUI: DAILY_LAST_NUMERIC_FIELD,
   },
 
   shouldIncludeField: function (field) {
@@ -363,16 +383,17 @@ TranslationMeasurement1.prototype = Obje
     };
 
     return function (data) {
       let result = serializer(data);
 
       // Special case the serialization of these fields so that
       // they are sent as objects, not stringified objects.
       _parseInPlace(result, "translationOpportunityCountsByLanguage");
+      _parseInPlace(result, "missedTranslationOpportunityCountsByLanguage");
       _parseInPlace(result, "pageTranslatedCountsByLanguage");
 
       return result;
     }
   }
 });
 
 this.TranslationProvider = function () {
@@ -402,16 +423,35 @@ TranslationProvider.prototype = Object.f
       langCounts = JSON.stringify(langCounts);
 
       yield m.setDailyLastText("translationOpportunityCountsByLanguage",
                                langCounts, date);
 
     }.bind(this));
   },
 
+  recordMissedTranslationOpportunity: function (language, date=new Date()) {
+    let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
+                                TranslationMeasurement1.prototype.version);
+
+    return this._enqueueTelemetryStorageTask(function* recordTask() {
+      yield m.incrementDailyCounter("missedTranslationOpportunityCount", date);
+
+      let langCounts = yield m._getDailyLastTextFieldAsJSON(
+        "missedTranslationOpportunityCountsByLanguage", date);
+
+      langCounts[language] = (langCounts[language] || 0) + 1;
+      langCounts = JSON.stringify(langCounts);
+
+      yield m.setDailyLastText("missedTranslationOpportunityCountsByLanguage",
+                               langCounts, date);
+
+    }.bind(this));
+  },
+
   recordTranslation: function (langFrom, langTo, numCharacters, date=new Date()) {
     let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
                                 TranslationMeasurement1.prototype.version);
 
     return this._enqueueTelemetryStorageTask(function* recordTask() {
       yield m.incrementDailyCounter("pageTranslatedCount", date);
       yield m.incrementDailyCounter("charactersTranslatedCount", date,
                                     numCharacters);
--- a/browser/components/translation/test/unit/test_healthreport.js
+++ b/browser/components/translation/test/unit/test_healthreport.js
@@ -64,31 +64,57 @@ add_task(function* test_translation_oppo
   let day = values.days.getDay(now);
   Assert.ok(day.has("translationOpportunityCount"));
   Assert.equal(day.get("translationOpportunityCount"), 1);
 
   Assert.ok(day.has("translationOpportunityCountsByLanguage"));
   let countsByLanguage = JSON.parse(day.get("translationOpportunityCountsByLanguage"));
   Assert.equal(countsByLanguage["fr"], 1);
 
+  // Record a missed opportunity.
+  yield provider.recordMissedTranslationOpportunity("it", now);
+
+  values = yield m.getValues();
+  day = values.days.getDay(now);
+  Assert.equal(values.days.size, 1);
+  Assert.ok(values.days.hasDay(now));
+  Assert.ok(day.has("missedTranslationOpportunityCount"));
+  Assert.equal(day.get("missedTranslationOpportunityCount"), 1);
+
+  Assert.ok(day.has("missedTranslationOpportunityCountsByLanguage"));
+  let missedCountsByLanguage = JSON.parse(day.get("missedTranslationOpportunityCountsByLanguage"));
+  Assert.equal(missedCountsByLanguage["it"], 1);
+
   // Record more opportunities.
   yield provider.recordTranslationOpportunity("fr", now);
   yield provider.recordTranslationOpportunity("fr", now);
   yield provider.recordTranslationOpportunity("es", now);
 
+  yield provider.recordMissedTranslationOpportunity("it", now);
+  yield provider.recordMissedTranslationOpportunity("cs", now);
+  yield provider.recordMissedTranslationOpportunity("fi", now);
+
   values = yield m.getValues();
-  let day = values.days.getDay(now);
+  day = values.days.getDay(now);
   Assert.ok(day.has("translationOpportunityCount"));
   Assert.equal(day.get("translationOpportunityCount"), 4);
+  Assert.ok(day.has("missedTranslationOpportunityCount"));
+  Assert.equal(day.get("missedTranslationOpportunityCount"), 4);
 
   Assert.ok(day.has("translationOpportunityCountsByLanguage"));
   countsByLanguage = JSON.parse(day.get("translationOpportunityCountsByLanguage"));
   Assert.equal(countsByLanguage["fr"], 3);
   Assert.equal(countsByLanguage["es"], 1);
 
+  Assert.ok(day.has("missedTranslationOpportunityCountsByLanguage"));
+  missedCountsByLanguage = JSON.parse(day.get("missedTranslationOpportunityCountsByLanguage"));
+  Assert.equal(missedCountsByLanguage["it"], 2);
+  Assert.equal(missedCountsByLanguage["cs"], 1);
+  Assert.equal(missedCountsByLanguage["fi"], 1);
+
   yield provider.shutdown();
   yield storage.close();
 });
 
 // Test recording a translation.
 add_task(function* test_record_translation() {
   let storage = yield Metrics.Storage("translation");
   let provider = new TranslationProvider();
--- a/services/healthreport/docs/dataformat.rst
+++ b/services/healthreport/docs/dataformat.rst
@@ -1537,16 +1537,20 @@ FHR if telemetry is enabled.
 
 Version 1
 ^^^^^^^^^
 
 Daily counts are reported in the following properties:
 
 translationOpportunityCount
     Integer count of the number of opportunities there were to translate a page.
+missedTranslationOpportunityCount
+    Integer count of the number of missed opportunities there were to translate a page.
+    A missed opportunity is when the page language is not supported by the translation
+    provider.
 pageTranslatedCount
     Integer count of the number of pages translated.
 charactersTranslatedCount
     Integer count of the number of characters translated.
 detectedLanguageChangedBefore
     Integer count of the number of times the user manually adjusted the detected
     language before translating.
 detectedLanguageChangedAfter
@@ -1554,16 +1558,19 @@ detectedLanguageChangedAfter
     language after having first translated the page.
 
 Additional daily counts broken down by language are reported in the following
 properties:
 
 translationOpportunityCountsByLanguage
     A mapping from language to count of opportunities to translate that
     language.
+missedTranslationOpportunityCountsByLanguage
+    A mapping from language to count of missed opportunities to translate that
+    language.
 pageTranslatedCountsByLanguage
     A mapping from language to the counts of pages translated from that
     language. Each language entry will be an object containing a "total" member
     along with individual counts for each language translated to.
 
 Other properties:
 
 detectLanguageEnabled