autofill_metrics.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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. 4 5#include "components/autofill/core/browser/autofill_metrics.h" 6 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" 14 15namespace autofill { 16 17namespace { 18 19enum FieldTypeGroupForMetrics { 20 AMBIGUOUS = 0, 21 NAME, 22 COMPANY, 23 ADDRESS_LINE_1, 24 ADDRESS_LINE_2, 25 ADDRESS_CITY, 26 ADDRESS_STATE, 27 ADDRESS_ZIP, 28 ADDRESS_COUNTRY, 29 PHONE, 30 FAX, // Deprecated. 31 EMAIL, 32 CREDIT_CARD_NAME, 33 CREDIT_CARD_NUMBER, 34 CREDIT_CARD_DATE, 35 CREDIT_CARD_TYPE, 36 PASSWORD, 37 NUM_FIELD_TYPE_GROUPS_FOR_METRICS 38}; 39 40// First, translates |field_type| to the corresponding logical |group| from 41// |FieldTypeGroupForMetrics|. Then, interpolates this with the given |metric|, 42// which should be in the range [0, |num_possible_metrics|). 43// Returns the interpolated index. 44// 45// The interpolation maps the pair (|group|, |metric|) to a single index, so 46// that all the indicies for a given group are adjacent. In particular, with 47// the groups {AMBIGUOUS, NAME, ...} combining with the metrics {UNKNOWN, MATCH, 48// MISMATCH}, we create this set of mapped indices: 49// { 50// AMBIGUOUS+UNKNOWN, 51// AMBIGUOUS+MATCH, 52// AMBIGUOUS+MISMATCH, 53// NAME+UNKNOWN, 54// NAME+MATCH, 55// NAME+MISMATCH, 56// ... 57// }. 58// 59// Clients must ensure that |field_type| is one of the types Chrome supports 60// natively, e.g. |field_type| must not be a billng address. 61int GetFieldTypeGroupMetric(const ServerFieldType field_type, 62 const int metric, 63 const int num_possible_metrics) { 64 DCHECK_LT(metric, num_possible_metrics); 65 66 FieldTypeGroupForMetrics group = AMBIGUOUS; 67 switch (AutofillType(field_type).group()) { 68 case ::autofill::NO_GROUP: 69 group = AMBIGUOUS; 70 break; 71 72 case ::autofill::NAME: 73 case ::autofill::NAME_BILLING: 74 group = NAME; 75 break; 76 77 case ::autofill::COMPANY: 78 group = COMPANY; 79 break; 80 81 case ::autofill::ADDRESS_HOME: 82 case ::autofill::ADDRESS_BILLING: 83 switch (AutofillType(field_type).GetStorableType()) { 84 case ADDRESS_HOME_LINE1: 85 group = ADDRESS_LINE_1; 86 break; 87 case ADDRESS_HOME_LINE2: 88 group = ADDRESS_LINE_2; 89 break; 90 case ADDRESS_HOME_CITY: 91 group = ADDRESS_CITY; 92 break; 93 case ADDRESS_HOME_STATE: 94 group = ADDRESS_STATE; 95 break; 96 case ADDRESS_HOME_ZIP: 97 group = ADDRESS_ZIP; 98 break; 99 case ADDRESS_HOME_COUNTRY: 100 group = ADDRESS_COUNTRY; 101 break; 102 default: 103 NOTREACHED(); 104 group = AMBIGUOUS; 105 break; 106 } 107 break; 108 109 case ::autofill::EMAIL: 110 group = EMAIL; 111 break; 112 113 case ::autofill::PHONE_HOME: 114 case ::autofill::PHONE_BILLING: 115 group = PHONE; 116 break; 117 118 case ::autofill::CREDIT_CARD: 119 switch (field_type) { 120 case ::autofill::CREDIT_CARD_NAME: 121 group = CREDIT_CARD_NAME; 122 break; 123 case ::autofill::CREDIT_CARD_NUMBER: 124 group = CREDIT_CARD_NUMBER; 125 break; 126 case ::autofill::CREDIT_CARD_TYPE: 127 group = CREDIT_CARD_TYPE; 128 break; 129 case ::autofill::CREDIT_CARD_EXP_MONTH: 130 case ::autofill::CREDIT_CARD_EXP_2_DIGIT_YEAR: 131 case ::autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR: 132 case ::autofill::CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR: 133 case ::autofill::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: 134 group = CREDIT_CARD_DATE; 135 break; 136 default: 137 NOTREACHED(); 138 group = AMBIGUOUS; 139 break; 140 } 141 break; 142 143 case ::autofill::PASSWORD_FIELD: 144 group = PASSWORD; 145 break; 146 } 147 148 // Interpolate the |metric| with the |group|, so that all metrics for a given 149 // |group| are adjacent. 150 return (group * num_possible_metrics) + metric; 151} 152 153std::string WalletApiMetricToString( 154 AutofillMetrics::WalletApiCallMetric metric) { 155 switch (metric) { 156 case AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS: 157 return "AcceptLegalDocuments"; 158 case AutofillMetrics::AUTHENTICATE_INSTRUMENT: 159 return "AuthenticateInstrument"; 160 case AutofillMetrics::GET_FULL_WALLET: 161 return "GetFullWallet"; 162 case AutofillMetrics::GET_WALLET_ITEMS: 163 return "GetWalletItems"; 164 case AutofillMetrics::SAVE_TO_WALLET: 165 return "SaveToWallet"; 166 case AutofillMetrics::UNKNOWN_API_CALL: 167 case AutofillMetrics::NUM_WALLET_API_CALLS: 168 NOTREACHED(); 169 return "UnknownApiCall"; 170 } 171 172 NOTREACHED(); 173 return "UnknownApiCall"; 174} 175 176// A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| 177// to vary over the program's runtime. 178void LogUMAHistogramEnumeration(const std::string& name, 179 int sample, 180 int boundary_value) { 181 DCHECK_LT(sample, boundary_value); 182 183 // Note: This leaks memory, which is expected behavior. 184 base::HistogramBase* histogram = 185 base::LinearHistogram::FactoryGet( 186 name, 187 1, 188 boundary_value, 189 boundary_value + 1, 190 base::HistogramBase::kUmaTargetedHistogramFlag); 191 histogram->Add(sample); 192} 193 194// A version of the UMA_HISTOGRAM_TIMES macro that allows the |name| 195// to vary over the program's runtime. 196void LogUMAHistogramTimes(const std::string& name, 197 const base::TimeDelta& duration) { 198 // Note: This leaks memory, which is expected behavior. 199 base::HistogramBase* histogram = 200 base::Histogram::FactoryTimeGet( 201 name, 202 base::TimeDelta::FromMilliseconds(1), 203 base::TimeDelta::FromSeconds(10), 204 50, 205 base::HistogramBase::kUmaTargetedHistogramFlag); 206 histogram->AddTime(duration); 207} 208 209// A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name| 210// to vary over the program's runtime. 211void LogUMAHistogramLongTimes(const std::string& name, 212 const base::TimeDelta& duration) { 213 // Note: This leaks memory, which is expected behavior. 214 base::HistogramBase* histogram = 215 base::Histogram::FactoryTimeGet( 216 name, 217 base::TimeDelta::FromMilliseconds(1), 218 base::TimeDelta::FromHours(1), 219 50, 220 base::HistogramBase::kUmaTargetedHistogramFlag); 221 histogram->AddTime(duration); 222} 223 224// Logs a type quality metric. The primary histogram name is constructed based 225// on |base_name|. The field-specific histogram name also factors in the 226// |field_type|. Logs a sample of |metric|, which should be in the range 227// [0, |num_possible_metrics|). 228void LogTypeQualityMetric(const std::string& base_name, 229 const int metric, 230 const int num_possible_metrics, 231 const ServerFieldType field_type) { 232 DCHECK_LT(metric, num_possible_metrics); 233 234 std::string histogram_name = base_name; 235 LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics); 236 237 std::string sub_histogram_name = base_name + ".ByFieldType"; 238 const int field_type_group_metric = 239 GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics); 240 const int num_field_type_group_metrics = 241 num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS; 242 LogUMAHistogramEnumeration(sub_histogram_name, 243 field_type_group_metric, 244 num_field_type_group_metrics); 245} 246 247} // namespace 248 249AutofillMetrics::AutofillMetrics() { 250} 251 252AutofillMetrics::~AutofillMetrics() { 253} 254 255void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const { 256 DCHECK_LT(metric, NUM_INFO_BAR_METRICS); 257 258 UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric, 259 NUM_INFO_BAR_METRICS); 260} 261 262void AutofillMetrics::LogDialogDismissalState( 263 DialogDismissalState state) const { 264 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.DismissalState", 265 state, NUM_DIALOG_DISMISSAL_STATES); 266} 267 268void AutofillMetrics::LogDialogInitialUserState( 269 DialogInitialUserStateMetric user_type) const { 270 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.InitialUserState", 271 user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS); 272} 273 274void AutofillMetrics::LogDialogLatencyToShow( 275 const base::TimeDelta& duration) const { 276 LogUMAHistogramTimes("RequestAutocomplete.UiLatencyToShow", duration); 277} 278 279void AutofillMetrics::LogDialogPopupEvent(DialogPopupEvent event) const { 280 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.PopupInDialog", 281 event, NUM_DIALOG_POPUP_EVENTS); 282} 283 284void AutofillMetrics::LogDialogSecurityMetric( 285 DialogSecurityMetric metric) const { 286 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.Security", 287 metric, NUM_DIALOG_SECURITY_METRICS); 288} 289 290void AutofillMetrics::LogDialogUiDuration( 291 const base::TimeDelta& duration, 292 DialogDismissalAction dismissal_action) const { 293 std::string suffix; 294 switch (dismissal_action) { 295 case DIALOG_ACCEPTED: 296 suffix = "Submit"; 297 break; 298 299 case DIALOG_CANCELED: 300 suffix = "Cancel"; 301 break; 302 } 303 304 LogUMAHistogramLongTimes("RequestAutocomplete.UiDuration", duration); 305 LogUMAHistogramLongTimes("RequestAutocomplete.UiDuration." + suffix, 306 duration); 307} 308 309void AutofillMetrics::LogDialogUiEvent(DialogUiEvent event) const { 310 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.UiEvents", event, 311 NUM_DIALOG_UI_EVENTS); 312} 313 314void AutofillMetrics::LogWalletErrorMetric(WalletErrorMetric metric) const { 315 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.WalletErrors", metric, 316 NUM_WALLET_ERROR_METRICS); 317} 318 319void AutofillMetrics::LogWalletApiCallDuration( 320 WalletApiCallMetric metric, 321 const base::TimeDelta& duration) const { 322 LogUMAHistogramTimes("Wallet.ApiCallDuration." + 323 WalletApiMetricToString(metric), duration); 324} 325 326void AutofillMetrics::LogWalletMalformedResponseMetric( 327 WalletApiCallMetric metric) const { 328 UMA_HISTOGRAM_ENUMERATION("Wallet.MalformedResponse", metric, 329 NUM_WALLET_API_CALLS); 330} 331 332void AutofillMetrics::LogWalletRequiredActionMetric( 333 WalletRequiredActionMetric required_action) const { 334 UMA_HISTOGRAM_ENUMERATION("RequestAutocomplete.WalletRequiredActions", 335 required_action, NUM_WALLET_REQUIRED_ACTIONS); 336} 337 338void AutofillMetrics::LogWalletResponseCode(int response_code) const { 339 UMA_HISTOGRAM_SPARSE_SLOWLY("Wallet.ResponseCode", response_code); 340} 341 342void AutofillMetrics::LogDeveloperEngagementMetric( 343 DeveloperEngagementMetric metric) const { 344 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); 345 346 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, 347 NUM_DEVELOPER_ENGAGEMENT_METRICS); 348} 349 350void AutofillMetrics::LogHeuristicTypePrediction( 351 FieldTypeQualityMetric metric, 352 ServerFieldType field_type) const { 353 LogTypeQualityMetric("Autofill.Quality.HeuristicType", 354 metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type); 355} 356 357void AutofillMetrics::LogOverallTypePrediction( 358 FieldTypeQualityMetric metric, 359 ServerFieldType field_type) const { 360 LogTypeQualityMetric("Autofill.Quality.PredictedType", 361 metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type); 362} 363 364void AutofillMetrics::LogServerTypePrediction( 365 FieldTypeQualityMetric metric, 366 ServerFieldType field_type) const { 367 LogTypeQualityMetric("Autofill.Quality.ServerType", 368 metric, NUM_FIELD_TYPE_QUALITY_METRICS, field_type); 369} 370 371void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const { 372 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); 373 374 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 375 NUM_SERVER_QUERY_METRICS); 376} 377 378void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const { 379 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS); 380 381 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric, 382 NUM_USER_HAPPINESS_METRICS); 383} 384 385void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill( 386 const base::TimeDelta& duration) const { 387 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill", 388 duration, 389 base::TimeDelta::FromMilliseconds(100), 390 base::TimeDelta::FromMinutes(10), 391 50); 392} 393 394void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill( 395 const base::TimeDelta& duration) const { 396 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill", 397 duration, 398 base::TimeDelta::FromMilliseconds(100), 399 base::TimeDelta::FromMinutes(10), 400 50); 401} 402 403void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( 404 const base::TimeDelta& duration) const { 405 UMA_HISTOGRAM_CUSTOM_TIMES( 406 "Autofill.FillDuration.FromInteraction.WithAutofill", 407 duration, 408 base::TimeDelta::FromMilliseconds(100), 409 base::TimeDelta::FromMinutes(10), 410 50); 411} 412 413void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( 414 const base::TimeDelta& duration) const { 415 UMA_HISTOGRAM_CUSTOM_TIMES( 416 "Autofill.FillDuration.FromInteraction.WithoutAutofill", 417 duration, 418 base::TimeDelta::FromMilliseconds(100), 419 base::TimeDelta::FromMinutes(10), 420 50); 421} 422 423void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const { 424 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled); 425} 426 427void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const { 428 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); 429} 430 431void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const { 432 UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles); 433} 434 435void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const { 436 UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions); 437} 438 439} // namespace autofill 440