Commit c3cb3aa6 authored by Max Curran's avatar Max Curran Committed by Commit Bot

Added UMA metrics to track the source and target language over the

course of a page load.

Two key values within Translate are the source language (language of the
web page) and the target language (the user's language). This new code
will track the source and target language over the course of a page load
and record the initial and final languages for every page load. We want
to record both the initial and final values, because the user can
manually change both the source and target language. In addition, this
new code will record the number of times the target language is changed.
We do not do the same for source language, because we expect the user to
change that much less frequently.

Full design doc: https://docs.google.com/document/d/1dyWh1Xw5VgUA00VA-5PTgKQ6ItziPBnSyeDR8saJ9vM/edit?usp=sharing

Bug: 111486
Change-Id: Ibb9fec8f2f831aaf7bea09a543167c0220d795ca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2543342Reviewed-by: default avatarScott Little <sclittle@chromium.org>
Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Reviewed-by: default avatarMark Pearson <mpearson@chromium.org>
Commit-Queue: Max Curran <curranmax@chromium.org>
Cr-Commit-Position: refs/heads/master@{#830668}
parent 4d43cef1
...@@ -74,6 +74,14 @@ class MockTranslateMetricsLoggerContainer ...@@ -74,6 +74,14 @@ class MockTranslateMetricsLoggerContainer
mock_translate_metrics_logger_->LogOmniboxIconChange(is_omnibox_icon_shown); mock_translate_metrics_logger_->LogOmniboxIconChange(is_omnibox_icon_shown);
} }
void LogSourceLanguage(const std::string& source_language_code) override {
mock_translate_metrics_logger_->LogSourceLanguage(source_language_code);
}
void LogTargetLanguage(const std::string& target_language_code) override {
mock_translate_metrics_logger_->LogTargetLanguage(target_language_code);
}
private: private:
translate::testing::MockTranslateMetricsLogger* translate::testing::MockTranslateMetricsLogger*
mock_translate_metrics_logger_; // Weak. mock_translate_metrics_logger_; // Weak.
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "components/translate/core/browser/translate_metrics_logger.h" #include "components/translate/core/browser/translate_metrics_logger.h"
#include <string>
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -37,6 +39,8 @@ class MockTranslateMetricsLogger : public TranslateMetricsLogger { ...@@ -37,6 +39,8 @@ class MockTranslateMetricsLogger : public TranslateMetricsLogger {
MOCK_METHOD0(LogReversion, void()); MOCK_METHOD0(LogReversion, void());
MOCK_METHOD1(LogUIChange, void(bool)); MOCK_METHOD1(LogUIChange, void(bool));
MOCK_METHOD1(LogOmniboxIconChange, void(bool)); MOCK_METHOD1(LogOmniboxIconChange, void(bool));
MOCK_METHOD1(LogSourceLanguage, void(const std::string&));
MOCK_METHOD1(LogTargetLanguage, void(const std::string&));
private: private:
base::WeakPtrFactory<MockTranslateMetricsLogger> weak_method_factory_{this}; base::WeakPtrFactory<MockTranslateMetricsLogger> weak_method_factory_{this};
......
...@@ -161,6 +161,8 @@ void TranslateManager::InitiateTranslation(const std::string& page_lang) { ...@@ -161,6 +161,8 @@ void TranslateManager::InitiateTranslation(const std::string& page_lang) {
// TODO(crbug.com/924980): The ranker event shouldn't be a global on this // TODO(crbug.com/924980): The ranker event shouldn't be a global on this
// object. It should instead be passed around to code that uses it. // object. It should instead be passed around to code that uses it.
InitTranslateEvent(page_language_code, target_lang, *translate_prefs); InitTranslateEvent(page_language_code, target_lang, *translate_prefs);
GetActiveTranslateMetricsLogger()->LogSourceLanguage(page_language_code);
GetActiveTranslateMetricsLogger()->LogTargetLanguage(target_lang);
const TranslateTriggerDecision& decision = ComputePossibleOutcomes( const TranslateTriggerDecision& decision = ComputePossibleOutcomes(
translate_prefs.get(), page_language_code, target_lang); translate_prefs.get(), page_language_code, target_lang);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_METRICS_LOGGER_H_ #define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_METRICS_LOGGER_H_
#include <stdint.h> #include <stdint.h>
#include <string>
namespace translate { namespace translate {
...@@ -88,6 +89,11 @@ class TranslateMetricsLogger { ...@@ -88,6 +89,11 @@ class TranslateMetricsLogger {
virtual void LogReversion() = 0; virtual void LogReversion() = 0;
virtual void LogUIChange(bool is_ui_shown) = 0; virtual void LogUIChange(bool is_ui_shown) = 0;
virtual void LogOmniboxIconChange(bool is_omnibox_icon_show) = 0; virtual void LogOmniboxIconChange(bool is_omnibox_icon_show) = 0;
// Used to record the source language and target language both initially and
// if the user changes these values.
virtual void LogSourceLanguage(const std::string& source_language_code) = 0;
virtual void LogTargetLanguage(const std::string& target_language_code) = 0;
}; };
} // namespace translate } // namespace translate
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "components/translate/core/browser/translate_metrics_logger_impl.h" #include "components/translate/core/browser/translate_metrics_logger_impl.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/metrics/metrics_hashes.h"
#include "base/time/default_tick_clock.h" #include "base/time/default_tick_clock.h"
#include "components/translate/core/browser/translate_manager.h" #include "components/translate/core/browser/translate_manager.h"
...@@ -12,8 +13,18 @@ namespace translate { ...@@ -12,8 +13,18 @@ namespace translate {
const char kTranslatePageLoadAutofillAssistantDeferredTriggerDecision[] = const char kTranslatePageLoadAutofillAssistantDeferredTriggerDecision[] =
"Translate.PageLoad.AutofillAssistantDeferredTriggerDecision"; "Translate.PageLoad.AutofillAssistantDeferredTriggerDecision";
const char kTranslatePageLoadFinalSourceLanguage[] =
"Translate.PageLoad.FinalSourceLanguage";
const char kTranslatePageLoadFinalState[] = "Translate.PageLoad.FinalState"; const char kTranslatePageLoadFinalState[] = "Translate.PageLoad.FinalState";
const char kTranslatePageLoadFinalTargetLanguage[] =
"Translate.PageLoad.FinalTargetLanguage";
const char kTranslatePageLoadInitialSourceLanguage[] =
"Translate.PageLoad.InitialSourceLanguage";
const char kTranslatePageLoadInitialState[] = "Translate.PageLoad.InitialState"; const char kTranslatePageLoadInitialState[] = "Translate.PageLoad.InitialState";
const char kTranslatePageLoadInitialTargetLanguage[] =
"Translate.PageLoad.InitialTargetLanguage";
const char kTranslatePageLoadNumTargetLanguageChanges[] =
"Translate.PageLoad.NumTargetLanguageChanges";
const char kTranslatePageLoadNumTranslations[] = const char kTranslatePageLoadNumTranslations[] =
"Translate.PageLoad.NumTranslations"; "Translate.PageLoad.NumTranslations";
const char kTranslatePageLoadNumReversions[] = const char kTranslatePageLoadNumReversions[] =
...@@ -95,6 +106,17 @@ void TranslateMetricsLoggerImpl::RecordPageLoadUmaMetrics() { ...@@ -95,6 +106,17 @@ void TranslateMetricsLoggerImpl::RecordPageLoadUmaMetrics() {
num_translations_); num_translations_);
base::UmaHistogramCounts10000(kTranslatePageLoadNumReversions, base::UmaHistogramCounts10000(kTranslatePageLoadNumReversions,
num_reversions_); num_reversions_);
base::UmaHistogramSparse(kTranslatePageLoadInitialSourceLanguage,
base::HashMetricName(initial_source_language_));
base::UmaHistogramSparse(kTranslatePageLoadFinalSourceLanguage,
base::HashMetricName(current_source_language_));
base::UmaHistogramSparse(kTranslatePageLoadInitialTargetLanguage,
base::HashMetricName(initial_target_language_));
base::UmaHistogramSparse(kTranslatePageLoadFinalTargetLanguage,
base::HashMetricName(current_target_language_));
base::UmaHistogramCustomCounts(kTranslatePageLoadNumTargetLanguageChanges,
num_target_language_changes_, 1, 50, 20);
} }
void TranslateMetricsLoggerImpl::LogRankerMetrics( void TranslateMetricsLoggerImpl::LogRankerMetrics(
...@@ -171,6 +193,28 @@ void TranslateMetricsLoggerImpl::LogOmniboxIconChange( ...@@ -171,6 +193,28 @@ void TranslateMetricsLoggerImpl::LogOmniboxIconChange(
current_state_is_omnibox_icon_shown_ = is_omnibox_icon_shown; current_state_is_omnibox_icon_shown_ = is_omnibox_icon_shown;
} }
void TranslateMetricsLoggerImpl::LogSourceLanguage(
const std::string& source_language_code) {
if (initial_source_language_ == "")
initial_source_language_ = source_language_code;
current_source_language_ = source_language_code;
}
void TranslateMetricsLoggerImpl::LogTargetLanguage(
const std::string& target_language_code) {
if (initial_target_language_ == "")
initial_target_language_ = target_language_code;
// Only increment |num_target_language_changes_| if |current_target_language_|
// changes between two languages.
if (current_target_language_ != "" &&
current_target_language_ != target_language_code)
num_target_language_changes_++;
current_target_language_ = target_language_code;
}
TranslateState TranslateMetricsLoggerImpl::ConvertToTranslateState( TranslateState TranslateMetricsLoggerImpl::ConvertToTranslateState(
bool is_translated, bool is_translated,
bool is_ui_shown, bool is_ui_shown,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_METRICS_LOGGER_IMPL_H_ #define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_METRICS_LOGGER_IMPL_H_
#include <memory> #include <memory>
#include <string>
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/translate/core/browser/translate_metrics_logger.h" #include "components/translate/core/browser/translate_metrics_logger.h"
...@@ -17,8 +18,13 @@ class TickClock; ...@@ -17,8 +18,13 @@ class TickClock;
namespace translate { namespace translate {
extern const char kTranslatePageLoadAutofillAssistantDeferredTriggerDecision[]; extern const char kTranslatePageLoadAutofillAssistantDeferredTriggerDecision[];
extern const char kTranslatePageLoadFinalSourceLanguage[];
extern const char kTranslatePageLoadFinalState[]; extern const char kTranslatePageLoadFinalState[];
extern const char kTranslatePageLoadFinalTargetLanguage[];
extern const char kTranslatePageLoadInitialSourceLanguage[];
extern const char kTranslatePageLoadInitialState[]; extern const char kTranslatePageLoadInitialState[];
extern const char kTranslatePageLoadInitialTargetLanguage[];
extern const char kTranslatePageLoadNumTargetLanguageChanges[];
extern const char kTranslatePageLoadNumTranslations[]; extern const char kTranslatePageLoadNumTranslations[];
extern const char kTranslatePageLoadNumReversions[]; extern const char kTranslatePageLoadNumReversions[];
extern const char kTranslatePageLoadRankerDecision[]; extern const char kTranslatePageLoadRankerDecision[];
...@@ -43,6 +49,8 @@ class NullTranslateMetricsLogger : public TranslateMetricsLogger { ...@@ -43,6 +49,8 @@ class NullTranslateMetricsLogger : public TranslateMetricsLogger {
void LogReversion() override {} void LogReversion() override {}
void LogUIChange(bool is_ui_shown) override {} void LogUIChange(bool is_ui_shown) override {}
void LogOmniboxIconChange(bool is_omnibox_icon_shown) override {} void LogOmniboxIconChange(bool is_omnibox_icon_shown) override {}
void LogSourceLanguage(const std::string& source_language_code) override {}
void LogTargetLanguage(const std::string& target_language_code) override {}
}; };
class TranslateManager; class TranslateManager;
...@@ -81,6 +89,8 @@ class TranslateMetricsLoggerImpl : public TranslateMetricsLogger { ...@@ -81,6 +89,8 @@ class TranslateMetricsLoggerImpl : public TranslateMetricsLogger {
void LogReversion() override; void LogReversion() override;
void LogUIChange(bool is_ui_shown) override; void LogUIChange(bool is_ui_shown) override;
void LogOmniboxIconChange(bool is_omnibox_icon_shown) override; void LogOmniboxIconChange(bool is_omnibox_icon_shown) override;
void LogSourceLanguage(const std::string& source_language_code) override;
void LogTargetLanguage(const std::string& target_language_code) override;
// TODO(curranmax): Add appropriate functions for the Translate code to log // TODO(curranmax): Add appropriate functions for the Translate code to log
// relevant events. https://crbug.com/1114868. // relevant events. https://crbug.com/1114868.
...@@ -149,6 +159,14 @@ class TranslateMetricsLoggerImpl : public TranslateMetricsLogger { ...@@ -149,6 +159,14 @@ class TranslateMetricsLoggerImpl : public TranslateMetricsLogger {
base::TimeDelta total_time_translated_; base::TimeDelta total_time_translated_;
base::TimeDelta total_time_not_translated_; base::TimeDelta total_time_not_translated_;
// Tracks the source and target language over the course of the page load.
std::string initial_source_language_;
std::string current_source_language_;
std::string initial_target_language_;
std::string current_target_language_;
int num_target_language_changes_ = 0;
base::WeakPtrFactory<TranslateMetricsLoggerImpl> weak_method_factory_{this}; base::WeakPtrFactory<TranslateMetricsLoggerImpl> weak_method_factory_{this};
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/metrics_hashes.h"
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -362,6 +363,54 @@ TEST_F(TranslateMetricsLoggerImplTest, ...@@ -362,6 +363,54 @@ TEST_F(TranslateMetricsLoggerImplTest,
CheckTotalTimeTranslated(delay3, delay1 + delay2); CheckTotalTimeTranslated(delay3, delay1 + delay2);
} }
TEST_F(TranslateMetricsLoggerImplTest, LogSourceLanguage) {
// Set constants for the test.
std::vector<std::string> source_languages = {"en", "es", "fr", "it", "de"};
// Log the source languages.
for (auto source_language : source_languages)
translate_metrics_logger()->LogSourceLanguage(source_language);
// Record the stored metrics.
translate_metrics_logger()->RecordMetrics(true);
// Check that the histograms match expectations.
histogram_tester()->ExpectUniqueSample(
kTranslatePageLoadInitialSourceLanguage,
base::HashMetricName(source_languages[0]), 1);
histogram_tester()->ExpectUniqueSample(
kTranslatePageLoadFinalSourceLanguage,
base::HashMetricName(source_languages[source_languages.size() - 1]), 1);
}
TEST_F(TranslateMetricsLoggerImplTest, LogTargetLanguage) {
// Set constants for the test.
std::vector<std::string> target_languages = {"de", "en", "en", "de", "fr",
"fr", "es", "it", "it", "es"};
// We only care about changes in the target language, so if the language stays
// the same, we don't count it.
int num_target_language_changes = 6;
// Log the target languages.
for (auto target_language : target_languages)
translate_metrics_logger()->LogTargetLanguage(target_language);
// Record the stored metrics
translate_metrics_logger()->RecordMetrics(true);
// Check that the histograms match expectations.
histogram_tester()->ExpectUniqueSample(
kTranslatePageLoadInitialTargetLanguage,
base::HashMetricName(target_languages[0]), 1);
histogram_tester()->ExpectUniqueSample(
kTranslatePageLoadFinalTargetLanguage,
base::HashMetricName(target_languages[target_languages.size() - 1]), 1);
histogram_tester()->ExpectUniqueSample(
kTranslatePageLoadNumTargetLanguageChanges, num_target_language_changes,
1);
}
} // namespace testing } // namespace testing
} // namespace translate } // namespace translate
...@@ -164,6 +164,12 @@ void TranslateUIDelegate::UpdateOriginalLanguageIndex(size_t language_index) { ...@@ -164,6 +164,12 @@ void TranslateUIDelegate::UpdateOriginalLanguageIndex(size_t language_index) {
UMA_HISTOGRAM_BOOLEAN(kModifyOriginalLang, true); UMA_HISTOGRAM_BOOLEAN(kModifyOriginalLang, true);
original_language_index_ = language_index; original_language_index_ = language_index;
std::string language_code = "und";
if (language_index < GetNumberOfLanguages())
language_code = GetLanguageCodeAt(language_index);
translate_manager_->GetActiveTranslateMetricsLogger()->LogSourceLanguage(
language_code);
} }
void TranslateUIDelegate::UpdateOriginalLanguage( void TranslateUIDelegate::UpdateOriginalLanguage(
...@@ -186,6 +192,9 @@ void TranslateUIDelegate::UpdateTargetLanguageIndex(size_t language_index) { ...@@ -186,6 +192,9 @@ void TranslateUIDelegate::UpdateTargetLanguageIndex(size_t language_index) {
DCHECK_LT(language_index, GetNumberOfLanguages()); DCHECK_LT(language_index, GetNumberOfLanguages());
UMA_HISTOGRAM_BOOLEAN(kModifyTargetLang, true); UMA_HISTOGRAM_BOOLEAN(kModifyTargetLang, true);
target_language_index_ = language_index; target_language_index_ = language_index;
translate_manager_->GetActiveTranslateMetricsLogger()->LogTargetLanguage(
GetLanguageCodeAt(language_index));
} }
void TranslateUIDelegate::UpdateTargetLanguage( void TranslateUIDelegate::UpdateTargetLanguage(
......
...@@ -471,6 +471,20 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -471,6 +471,20 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="Translate.PageLoad.FinalSourceLanguage" enum="LanguageCode"
expires_after="2021-04-04">
<owner>curranmax@google.com</owner>
<owner>megjablon@google.com</owner>
<owner>chrome-language@google.com</owner>
<summary>
Records the hashcode of the source language at the end of the page load.
This may differ from the initial source language determined by Chrome,
because the user can manually change the source language. This value is
logged once the page load is completed or the first time Chrome is
backgrounded during the course of the page load, whichever comes first.
</summary>
</histogram>
<histogram name="Translate.PageLoad.FinalState" enum="TranslateState" <histogram name="Translate.PageLoad.FinalState" enum="TranslateState"
expires_after="2021-04-04"> expires_after="2021-04-04">
<owner>curranmax@google.com</owner> <owner>curranmax@google.com</owner>
...@@ -485,6 +499,34 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -485,6 +499,34 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="Translate.PageLoad.FinalTargetLanguage" enum="LanguageCode"
expires_after="2021-04-04">
<owner>curranmax@google.com</owner>
<owner>megjablon@google.com</owner>
<owner>chrome-language@google.com</owner>
<summary>
Records the hashcode of the target language at the end of the page load.
This may differ from the initial target language determined by Chrome,
because the user can manually change the target language. This value is
logged once the page load is completed or the first time Chrome is
backgrounded during the course of the page load, whichever comes first.
</summary>
</histogram>
<histogram name="Translate.PageLoad.InitialSourceLanguage" enum="LanguageCode"
expires_after="2021-04-04">
<owner>curranmax@google.com</owner>
<owner>megjablon@google.com</owner>
<owner>chrome-language@google.com</owner>
<summary>
Records the hashcode of the source language at the beginning of the page
load. The initial source language is automatically determined by Chrome.
This value is logged once the page load is completed or the first time
Chrome is backgrounded during the course of the page load, whichever comes
first.
</summary>
</histogram>
<histogram name="Translate.PageLoad.InitialState" enum="TranslateState" <histogram name="Translate.PageLoad.InitialState" enum="TranslateState"
expires_after="2021-04-04"> expires_after="2021-04-04">
<owner>curranmax@google.com</owner> <owner>curranmax@google.com</owner>
...@@ -499,6 +541,20 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -499,6 +541,20 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="Translate.PageLoad.InitialTargetLanguage" enum="LanguageCode"
expires_after="2021-04-04">
<owner>curranmax@google.com</owner>
<owner>megjablon@google.com</owner>
<owner>chrome-language@google.com</owner>
<summary>
Records the hashcode of the target language at the beginning of the page
load. The initial target language is automatically determined by Chrome.
This value is logged once the page load is completed or the first time
Chrome is backgrounded during the course of the page load, whichever comes
first.
</summary>
</histogram>
<histogram name="Translate.PageLoad.NumReversions" units="reversions" <histogram name="Translate.PageLoad.NumReversions" units="reversions"
expires_after="2021-04-04"> expires_after="2021-04-04">
<owner>curranmax@google.com</owner> <owner>curranmax@google.com</owner>
...@@ -512,6 +568,19 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -512,6 +568,19 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="Translate.PageLoad.NumTargetLanguageChanges"
units="target language changes" expires_after="2021-04-04">
<owner>curranmax@google.com</owner>
<owner>megjablon@google.com</owner>
<owner>chrome-language@google.com</owner>
<summary>
The number of times the user changed the target language over the course of
the page load. This value is logged once the page load is completed or the
first time Chrome is backgrounded during the course of the page load,
whichever comes first.
</summary>
</histogram>
<histogram name="Translate.PageLoad.NumTranslations" units="translations" <histogram name="Translate.PageLoad.NumTranslations" units="translations"
expires_after="2021-04-04"> expires_after="2021-04-04">
<owner>curranmax@google.com</owner> <owner>curranmax@google.com</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment