1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/autofill/core/browser/autofill_metrics.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "base/metrics/sparse_histogram.h"
10 #include "base/time/time.h"
11 #include "components/autofill/core/browser/autofill_type.h"
12 #include "components/autofill/core/browser/form_structure.h"
13 #include "components/autofill/core/common/form_data.h"
19 enum FieldTypeGroupForMetrics {
38 NUM_FIELD_TYPE_GROUPS_FOR_METRICS
41 // First, translates |field_type| to the corresponding logical |group| from
42 // |FieldTypeGroupForMetrics|. Then, interpolates this with the given |metric|,
43 // which should be in the range [0, |num_possible_metrics|).
44 // Returns the interpolated index.
46 // The interpolation maps the pair (|group|, |metric|) to a single index, so
47 // that all the indicies for a given group are adjacent. In particular, with
48 // the groups {AMBIGUOUS, NAME, ...} combining with the metrics {UNKNOWN, MATCH,
49 // MISMATCH}, we create this set of mapped indices:
53 // AMBIGUOUS+MISMATCH,
60 // Clients must ensure that |field_type| is one of the types Chrome supports
61 // natively, e.g. |field_type| must not be a billng address.
62 int GetFieldTypeGroupMetric(const ServerFieldType field_type,
64 const int num_possible_metrics) {
65 DCHECK_LT(metric, num_possible_metrics);
67 FieldTypeGroupForMetrics group = AMBIGUOUS;
68 switch (AutofillType(field_type).group()) {
69 case ::autofill::NO_GROUP:
73 case ::autofill::NAME:
74 case ::autofill::NAME_BILLING:
78 case ::autofill::COMPANY:
82 case ::autofill::ADDRESS_HOME:
83 case ::autofill::ADDRESS_BILLING:
84 switch (AutofillType(field_type).GetStorableType()) {
85 case ADDRESS_HOME_LINE1:
86 group = ADDRESS_LINE_1;
88 case ADDRESS_HOME_LINE2:
89 group = ADDRESS_LINE_2;
91 case ADDRESS_HOME_LINE3:
92 group = ADDRESS_LINE_3;
94 case ADDRESS_HOME_CITY:
97 case ADDRESS_HOME_STATE:
98 group = ADDRESS_STATE;
100 case ADDRESS_HOME_ZIP:
103 case ADDRESS_HOME_COUNTRY:
104 group = ADDRESS_COUNTRY;
113 case ::autofill::EMAIL:
117 case ::autofill::PHONE_HOME:
118 case ::autofill::PHONE_BILLING:
122 case ::autofill::CREDIT_CARD:
123 switch (field_type) {
124 case ::autofill::CREDIT_CARD_NAME:
125 group = CREDIT_CARD_NAME;
127 case ::autofill::CREDIT_CARD_NUMBER:
128 group = CREDIT_CARD_NUMBER;
130 case ::autofill::CREDIT_CARD_TYPE:
131 group = CREDIT_CARD_TYPE;
133 case ::autofill::CREDIT_CARD_EXP_MONTH:
134 case ::autofill::CREDIT_CARD_EXP_2_DIGIT_YEAR:
135 case ::autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR:
136 case ::autofill::CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
137 case ::autofill::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
138 group = CREDIT_CARD_DATE;
147 case ::autofill::PASSWORD_FIELD:
151 case ::autofill::TRANSACTION:
156 // Interpolate the |metric| with the |group|, so that all metrics for a given
157 // |group| are adjacent.
158 return (group * num_possible_metrics) + metric;
161 std::string WalletApiMetricToString(
162 AutofillMetrics::WalletApiCallMetric metric) {
164 case AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS:
165 return "AcceptLegalDocuments";
166 case AutofillMetrics::AUTHENTICATE_INSTRUMENT:
167 return "AuthenticateInstrument";
168 case AutofillMetrics::GET_FULL_WALLET:
169 return "GetFullWallet";
170 case AutofillMetrics::GET_WALLET_ITEMS:
171 return "GetWalletItems";
172 case AutofillMetrics::SAVE_TO_WALLET:
173 return "SaveToWallet";
174 case AutofillMetrics::UNKNOWN_API_CALL:
175 case AutofillMetrics::NUM_WALLET_API_CALLS:
177 return "UnknownApiCall";
181 return "UnknownApiCall";
184 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name|
185 // to vary over the program's runtime.
186 void LogUMAHistogramEnumeration(const std::string& name,
188 int boundary_value) {
189 DCHECK_LT(sample, boundary_value);
191 // Note: This leaks memory, which is expected behavior.
192 base::HistogramBase* histogram =
193 base::LinearHistogram::FactoryGet(
198 base::HistogramBase::kUmaTargetedHistogramFlag);
199 histogram->Add(sample);
202 // A version of the UMA_HISTOGRAM_TIMES macro that allows the |name|
203 // to vary over the program's runtime.
204 void LogUMAHistogramTimes(const std::string& name,
205 const base::TimeDelta& duration) {
206 // Note: This leaks memory, which is expected behavior.
207 base::HistogramBase* histogram =
208 base::Histogram::FactoryTimeGet(
210 base::TimeDelta::FromMilliseconds(1),
211 base::TimeDelta::FromSeconds(10),
213 base::HistogramBase::kUmaTargetedHistogramFlag);
214 histogram->AddTime(duration);
217 // A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name|
218 // to vary over the program's runtime.
219 void LogUMAHistogramLongTimes(const std::string& name,
220 const base::TimeDelta& duration) {
221 // Note: This leaks memory, which is expected behavior.
222 base::HistogramBase* histogram =
223 base::Histogram::FactoryTimeGet(
225 base::TimeDelta::FromMilliseconds(1),
226 base::TimeDelta::FromHours(1),
228 base::HistogramBase::kUmaTargetedHistogramFlag);
229 histogram->AddTime(duration);
232 // Logs a type quality metric. The primary histogram name is constructed based
233 // on |base_name|. The field-specific histogram name also factors in the
234 // |field_type|. Logs a sample of |metric|, which should be in the range
235 // [0, |num_possible_metrics|).
236 void LogTypeQualityMetric(const std::string& base_name,
238 const int num_possible_metrics,
239 const ServerFieldType field_type) {
240 DCHECK_LT(metric, num_possible_metrics);
242 std::string histogram_name = base_name;
243 LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics);
245 std::string sub_histogram_name = base_name + ".ByFieldType";
246 const int field_type_group_metric =
247 GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics);
248 const int num_field_type_group_metrics =
249 num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS;
250 LogUMAHistogramEnumeration(sub_histogram_name,
251 field_type_group_metric,
252 num_field_type_group_metrics);
257 AutofillMetrics::AutofillMetrics() {
260 AutofillMetrics::~AutofillMetrics() {
263 void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const {
264 DCHECK_LT(metric, NUM_INFO_BAR_METRICS);
266 UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric,
267 NUM_INFO_BAR_METRICS);
270 void AutofillMetrics::LogDialogDismissalState(
271 DialogDismissalState state) const {
272 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.DismissalState",
273 state, NUM_DIALOG_DISMISSAL_STATES);
276 void AutofillMetrics::LogDialogInitialUserState(
277 DialogInitialUserStateMetric user_type) const {
278 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.InitialUserState",
279 user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS);
282 void AutofillMetrics::LogDialogLatencyToShow(
283 const base::TimeDelta& duration) const {
284 LogUMAHistogramTimes("RequestAutocomplete.UiLatencyToShow", duration);
287 void AutofillMetrics::LogDialogPopupEvent(DialogPopupEvent event) const {
288 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.PopupInDialog",
289 event, NUM_DIALOG_POPUP_EVENTS);
292 void AutofillMetrics::LogDialogSecurityMetric(
293 DialogSecurityMetric metric) const {
294 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.Security",
295 metric, NUM_DIALOG_SECURITY_METRICS);
298 void AutofillMetrics::LogDialogUiDuration(
299 const base::TimeDelta& duration,
300 DialogDismissalAction dismissal_action) const {
302 switch (dismissal_action) {
303 case DIALOG_ACCEPTED:
307 case DIALOG_CANCELED:
312 LogUMAHistogramLongTimes("RequestAutocomplete.UiDuration", duration);
313 LogUMAHistogramLongTimes("RequestAutocomplete.UiDuration." + suffix,
317 void AutofillMetrics::LogDialogUiEvent(DialogUiEvent event) const {
318 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.UiEvents", event,
319 NUM_DIALOG_UI_EVENTS);
322 void AutofillMetrics::LogWalletErrorMetric(WalletErrorMetric metric) const {
323 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.WalletErrors", metric,
324 NUM_WALLET_ERROR_METRICS);
327 void AutofillMetrics::LogWalletApiCallDuration(
328 WalletApiCallMetric metric,
329 const base::TimeDelta& duration) const {
330 LogUMAHistogramTimes("Wallet.ApiCallDuration." +
331 WalletApiMetricToString(metric), duration);
334 void AutofillMetrics::LogWalletMalformedResponseMetric(
335 WalletApiCallMetric metric) const {
336 UMA_HISTOGRAM_ENUMERATION("Wallet.MalformedResponse", metric,
337 NUM_WALLET_API_CALLS);
340 void AutofillMetrics::LogWalletRequiredActionMetric(
341 WalletRequiredActionMetric required_action) const {
342 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.WalletRequiredActions",
343 required_action, NUM_WALLET_REQUIRED_ACTIONS);
346 void AutofillMetrics::LogWalletResponseCode(int response_code) const {
347 UMA_HISTOGRAM_SPARSE_SLOWLY("Wallet.ResponseCode", response_code);
350 void AutofillMetrics::LogDeveloperEngagementMetric(
351 DeveloperEngagementMetric metric) const {
352 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS);
354 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric,
355 NUM_DEVELOPER_ENGAGEMENT_METRICS);
358 void AutofillMetrics::LogHeuristicTypePrediction(
359 FieldTypeQualityMetric metric,
360 ServerFieldType field_type) const {
361 LogTypeQualityMetric("Autofill.Quality.HeuristicType",
362 metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type);
365 void AutofillMetrics::LogOverallTypePrediction(
366 FieldTypeQualityMetric metric,
367 ServerFieldType field_type) const {
368 LogTypeQualityMetric("Autofill.Quality.PredictedType",
369 metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type);
372 void AutofillMetrics::LogServerTypePrediction(
373 FieldTypeQualityMetric metric,
374 ServerFieldType field_type) const {
375 LogTypeQualityMetric("Autofill.Quality.ServerType",
376 metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type);
379 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const {
380 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS);
382 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric,
383 NUM_SERVER_QUERY_METRICS);
386 void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const {
387 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS);
389 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric,
390 NUM_USER_HAPPINESS_METRICS);
393 void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill(
394 const base::TimeDelta& duration) const {
395 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill",
397 base::TimeDelta::FromMilliseconds(100),
398 base::TimeDelta::FromMinutes(10),
402 void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill(
403 const base::TimeDelta& duration) const {
404 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill",
406 base::TimeDelta::FromMilliseconds(100),
407 base::TimeDelta::FromMinutes(10),
411 void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill(
412 const base::TimeDelta& duration) const {
413 UMA_HISTOGRAM_CUSTOM_TIMES(
414 "Autofill.FillDuration.FromInteraction.WithAutofill",
416 base::TimeDelta::FromMilliseconds(100),
417 base::TimeDelta::FromMinutes(10),
421 void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill(
422 const base::TimeDelta& duration) const {
423 UMA_HISTOGRAM_CUSTOM_TIMES(
424 "Autofill.FillDuration.FromInteraction.WithoutAutofill",
426 base::TimeDelta::FromMilliseconds(100),
427 base::TimeDelta::FromMinutes(10),
431 void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const {
432 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled);
435 void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const {
436 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled);
439 void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const {
440 UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles);
443 void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const {
444 UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions);
447 } // namespace autofill