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/time/time.h" 10 #include "components/autofill/core/browser/autofill_type.h" 11 #include "components/autofill/core/browser/form_structure.h" 12 #include "components/autofill/core/common/form_data.h" 13 14 namespace autofill { 15 16 namespace { 17 18 // Server experiments we support. 19 enum ServerExperiment { 20 NO_EXPERIMENT = 0, 21 UNKNOWN_EXPERIMENT, 22 ACCEPTANCE_RATIO_06, 23 ACCEPTANCE_RATIO_1, 24 ACCEPTANCE_RATIO_2, 25 ACCEPTANCE_RATIO_4, 26 ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15, 27 ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25, 28 ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5, 29 TOOLBAR_DATA_ONLY, 30 ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4, 31 NO_SERVER_RESPONSE, 32 PROBABILITY_PICKER_05, 33 PROBABILITY_PICKER_025, 34 PROBABILITY_PICKER_025_CC_THRESHOLD_03, 35 PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03, 36 PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK, 37 PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1, 38 NUM_SERVER_EXPERIMENTS 39 }; 40 41 enum FieldTypeGroupForMetrics { 42 AMBIGUOUS = 0, 43 NAME, 44 COMPANY, 45 ADDRESS_LINE_1, 46 ADDRESS_LINE_2, 47 ADDRESS_CITY, 48 ADDRESS_STATE, 49 ADDRESS_ZIP, 50 ADDRESS_COUNTRY, 51 PHONE, 52 FAX, // Deprecated. 53 EMAIL, 54 CREDIT_CARD_NAME, 55 CREDIT_CARD_NUMBER, 56 CREDIT_CARD_DATE, 57 CREDIT_CARD_TYPE, 58 NUM_FIELD_TYPE_GROUPS_FOR_METRICS 59 }; 60 61 // First, translates |field_type| to the corresponding logical |group| from 62 // |FieldTypeGroupForMetrics|. Then, interpolates this with the given |metric|, 63 // which should be in the range [0, |num_possible_metrics|). 64 // Returns the interpolated index. 65 // 66 // The interpolation maps the pair (|group|, |metric|) to a single index, so 67 // that all the indicies for a given group are adjacent. In particular, with 68 // the groups {AMBIGUOUS, NAME, ...} combining with the metrics {UNKNOWN, MATCH, 69 // MISMATCH}, we create this set of mapped indices: 70 // { 71 // AMBIGUOUS+UNKNOWN, 72 // AMBIGUOUS+MATCH, 73 // AMBIGUOUS+MISMATCH, 74 // NAME+UNKNOWN, 75 // NAME+MATCH, 76 // NAME+MISMATCH, 77 // ... 78 // }. 79 // 80 // Clients must ensure that |field_type| is one of the types Chrome supports 81 // natively, e.g. |field_type| must not be a billng address. 82 int GetFieldTypeGroupMetric(const ServerFieldType field_type, 83 const int metric, 84 const int num_possible_metrics) { 85 DCHECK_LT(metric, num_possible_metrics); 86 87 FieldTypeGroupForMetrics group; 88 switch (AutofillType(field_type).group()) { 89 case ::autofill::NO_GROUP: 90 group = AMBIGUOUS; 91 break; 92 93 case ::autofill::NAME: 94 group = NAME; 95 break; 96 97 case ::autofill::COMPANY: 98 group = COMPANY; 99 break; 100 101 case ::autofill::ADDRESS_HOME: 102 switch (field_type) { 103 case ADDRESS_HOME_LINE1: 104 group = ADDRESS_LINE_1; 105 break; 106 case ADDRESS_HOME_LINE2: 107 group = ADDRESS_LINE_2; 108 break; 109 case ADDRESS_HOME_CITY: 110 group = ADDRESS_CITY; 111 break; 112 case ADDRESS_HOME_STATE: 113 group = ADDRESS_STATE; 114 break; 115 case ADDRESS_HOME_ZIP: 116 group = ADDRESS_ZIP; 117 break; 118 case ADDRESS_HOME_COUNTRY: 119 group = ADDRESS_COUNTRY; 120 break; 121 default: 122 NOTREACHED(); 123 group = AMBIGUOUS; 124 } 125 break; 126 127 case ::autofill::EMAIL: 128 group = EMAIL; 129 break; 130 131 case ::autofill::PHONE_HOME: 132 group = PHONE; 133 break; 134 135 case ::autofill::CREDIT_CARD: 136 switch (field_type) { 137 case ::autofill::CREDIT_CARD_NAME: 138 group = CREDIT_CARD_NAME; 139 break; 140 case ::autofill::CREDIT_CARD_NUMBER: 141 group = CREDIT_CARD_NUMBER; 142 break; 143 case ::autofill::CREDIT_CARD_TYPE: 144 group = CREDIT_CARD_TYPE; 145 default: 146 group = CREDIT_CARD_DATE; 147 } 148 break; 149 150 default: 151 NOTREACHED(); 152 group = AMBIGUOUS; 153 } 154 155 // Interpolate the |metric| with the |group|, so that all metrics for a given 156 // |group| are adjacent. 157 return (group * num_possible_metrics) + metric; 158 } 159 160 // Returns the histogram prefix to use for reporting metrics for |dialog_type|. 161 std::string GetPrefixForDialogType(autofill::DialogType dialog_type) { 162 switch (dialog_type) { 163 case autofill::DIALOG_TYPE_AUTOCHECKOUT: 164 return "Autocheckout"; 165 166 case autofill::DIALOG_TYPE_REQUEST_AUTOCOMPLETE: 167 return "RequestAutocomplete"; 168 } 169 170 NOTREACHED(); 171 return "UnknownDialogType"; 172 } 173 174 std::string WalletApiMetricToString( 175 AutofillMetrics::WalletApiCallMetric metric) { 176 switch (metric) { 177 case AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS: 178 return "AcceptLegalDocuments"; 179 case AutofillMetrics::AUTHENTICATE_INSTRUMENT: 180 return "AuthenticateInstrument"; 181 case AutofillMetrics::GET_FULL_WALLET: 182 return "GetFullWallet"; 183 case AutofillMetrics::GET_WALLET_ITEMS: 184 return "GetWalletItems"; 185 case AutofillMetrics::SAVE_TO_WALLET: 186 return "SaveToWallet"; 187 case AutofillMetrics::SEND_STATUS: 188 return "SendStatus"; 189 case AutofillMetrics::UNKNOWN_API_CALL: 190 NOTREACHED(); 191 return "UnknownApiCall"; 192 } 193 194 NOTREACHED(); 195 return "UnknownApiCall"; 196 } 197 198 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| 199 // to vary over the program's runtime. 200 void LogUMAHistogramEnumeration(const std::string& name, 201 int sample, 202 int boundary_value) { 203 DCHECK_LT(sample, boundary_value); 204 205 // Note: This leaks memory, which is expected behavior. 206 base::HistogramBase* histogram = 207 base::LinearHistogram::FactoryGet( 208 name, 209 1, 210 boundary_value, 211 boundary_value + 1, 212 base::HistogramBase::kUmaTargetedHistogramFlag); 213 histogram->Add(sample); 214 } 215 216 // A version of the UMA_HISTOGRAM_TIMES macro that allows the |name| 217 // to vary over the program's runtime. 218 void LogUMAHistogramTimes(const std::string& name, 219 const base::TimeDelta& duration) { 220 // Note: This leaks memory, which is expected behavior. 221 base::HistogramBase* histogram = 222 base::Histogram::FactoryTimeGet( 223 name, 224 base::TimeDelta::FromMilliseconds(1), 225 base::TimeDelta::FromSeconds(10), 226 50, 227 base::HistogramBase::kUmaTargetedHistogramFlag); 228 histogram->AddTime(duration); 229 } 230 231 // A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name| 232 // to vary over the program's runtime. 233 void LogUMAHistogramLongTimes(const std::string& name, 234 const base::TimeDelta& duration) { 235 // Note: This leaks memory, which is expected behavior. 236 base::HistogramBase* histogram = 237 base::Histogram::FactoryTimeGet( 238 name, 239 base::TimeDelta::FromMilliseconds(1), 240 base::TimeDelta::FromHours(1), 241 50, 242 base::HistogramBase::kUmaTargetedHistogramFlag); 243 histogram->AddTime(duration); 244 } 245 246 // Logs a type quality metric. The primary histogram name is constructed based 247 // on |base_name| and |experiment_id|. The field-specific histogram name also 248 // factors in the |field_type|. Logs a sample of |metric|, which should be in 249 // the range [0, |num_possible_metrics|). 250 void LogTypeQualityMetric(const std::string& base_name, 251 const int metric, 252 const int num_possible_metrics, 253 const ServerFieldType field_type, 254 const std::string& experiment_id) { 255 DCHECK_LT(metric, num_possible_metrics); 256 257 std::string histogram_name = base_name; 258 if (!experiment_id.empty()) 259 histogram_name += "_" + experiment_id; 260 LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics); 261 262 std::string sub_histogram_name = base_name + ".ByFieldType"; 263 if (!experiment_id.empty()) 264 sub_histogram_name += "_" + experiment_id; 265 const int field_type_group_metric = 266 GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics); 267 const int num_field_type_group_metrics = 268 num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS; 269 LogUMAHistogramEnumeration(sub_histogram_name, 270 field_type_group_metric, 271 num_field_type_group_metrics); 272 } 273 274 void LogServerExperimentId(const std::string& histogram_name, 275 const std::string& experiment_id) { 276 ServerExperiment metric = UNKNOWN_EXPERIMENT; 277 278 const std::string default_experiment_name = 279 FormStructure(FormData(), std::string()).server_experiment_id(); 280 if (experiment_id.empty()) 281 metric = NO_EXPERIMENT; 282 else if (experiment_id == "ar06") 283 metric = ACCEPTANCE_RATIO_06; 284 else if (experiment_id == "ar1") 285 metric = ACCEPTANCE_RATIO_1; 286 else if (experiment_id == "ar2") 287 metric = ACCEPTANCE_RATIO_2; 288 else if (experiment_id == "ar4") 289 metric = ACCEPTANCE_RATIO_4; 290 else if (experiment_id == "ar05wlr15") 291 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15; 292 else if (experiment_id == "ar05wlr25") 293 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25; 294 else if (experiment_id == "ar05wr15fs5") 295 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5; 296 else if (experiment_id == "tbar1") 297 metric = TOOLBAR_DATA_ONLY; 298 else if (experiment_id == "ar04wr3fs4") 299 metric = ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4; 300 else if (experiment_id == default_experiment_name) 301 metric = NO_SERVER_RESPONSE; 302 else if (experiment_id == "fp05") 303 metric = PROBABILITY_PICKER_05; 304 else if (experiment_id == "fp025") 305 metric = PROBABILITY_PICKER_025; 306 else if (experiment_id == "fp05cc03") 307 metric = PROBABILITY_PICKER_025_CC_THRESHOLD_03; 308 else if (experiment_id == "fp05cco03") 309 metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03; 310 else if (experiment_id == "fp05cco03cstd") 311 metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK; 312 else if (experiment_id == "fp05cc03e1") 313 metric = PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1; 314 315 DCHECK_LT(metric, NUM_SERVER_EXPERIMENTS); 316 LogUMAHistogramEnumeration(histogram_name, metric, NUM_SERVER_EXPERIMENTS); 317 } 318 319 } // namespace 320 321 AutofillMetrics::AutofillMetrics() { 322 } 323 324 AutofillMetrics::~AutofillMetrics() { 325 } 326 327 void AutofillMetrics::LogAutocheckoutBubbleMetric(BubbleMetric metric) const { 328 DCHECK_LT(metric, NUM_BUBBLE_METRICS); 329 330 UMA_HISTOGRAM_ENUMERATION("Autocheckout.Bubble", metric, NUM_BUBBLE_METRICS); 331 } 332 333 void AutofillMetrics::LogAutocheckoutBuyFlowMetric( 334 AutocheckoutBuyFlowMetric metric) const { 335 DCHECK_LT(metric, NUM_AUTOCHECKOUT_BUY_FLOW_METRICS); 336 337 UMA_HISTOGRAM_ENUMERATION("Autocheckout.BuyFlow", metric, 338 NUM_AUTOCHECKOUT_BUY_FLOW_METRICS); 339 } 340 341 void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const { 342 DCHECK_LT(metric, NUM_INFO_BAR_METRICS); 343 344 UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric, 345 NUM_INFO_BAR_METRICS); 346 } 347 348 void AutofillMetrics::LogDialogDismissalState( 349 autofill::DialogType dialog_type, 350 DialogDismissalState state) const { 351 std::string name = GetPrefixForDialogType(dialog_type) + ".DismissalState"; 352 LogUMAHistogramEnumeration(name, state, NUM_DIALOG_DISMISSAL_STATES); 353 } 354 355 void AutofillMetrics::LogDialogInitialUserState( 356 autofill::DialogType dialog_type, 357 DialogInitialUserStateMetric user_type) const { 358 std::string name = GetPrefixForDialogType(dialog_type) + ".InitialUserState"; 359 LogUMAHistogramEnumeration( 360 name, user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS); 361 } 362 363 void AutofillMetrics::LogDialogLatencyToShow( 364 autofill::DialogType dialog_type, 365 const base::TimeDelta& duration) const { 366 std::string name = 367 GetPrefixForDialogType(dialog_type) + ".UiLatencyToShow"; 368 LogUMAHistogramTimes(name, duration); 369 } 370 371 void AutofillMetrics::LogDialogPopupEvent(autofill::DialogType dialog_type, 372 DialogPopupEvent event) const { 373 std::string name = GetPrefixForDialogType(dialog_type) + ".PopupInDialog"; 374 LogUMAHistogramEnumeration(name, event, NUM_DIALOG_POPUP_EVENTS); 375 } 376 377 void AutofillMetrics::LogDialogSecurityMetric( 378 autofill::DialogType dialog_type, 379 DialogSecurityMetric metric) const { 380 std::string name = GetPrefixForDialogType(dialog_type) + ".Security"; 381 LogUMAHistogramEnumeration(name, metric, NUM_DIALOG_SECURITY_METRICS); 382 } 383 384 void AutofillMetrics::LogDialogUiDuration( 385 const base::TimeDelta& duration, 386 autofill::DialogType dialog_type, 387 DialogDismissalAction dismissal_action) const { 388 std::string prefix = GetPrefixForDialogType(dialog_type); 389 390 std::string suffix; 391 switch (dismissal_action) { 392 case DIALOG_ACCEPTED: 393 suffix = "Submit"; 394 break; 395 396 case DIALOG_CANCELED: 397 suffix = "Cancel"; 398 break; 399 } 400 401 LogUMAHistogramLongTimes(prefix + ".UiDuration", duration); 402 LogUMAHistogramLongTimes(prefix + ".UiDuration." + suffix, duration); 403 } 404 405 void AutofillMetrics::LogDialogUiEvent(autofill::DialogType dialog_type, 406 DialogUiEvent event) const { 407 std::string name = GetPrefixForDialogType(dialog_type) + ".UiEvents"; 408 LogUMAHistogramEnumeration(name, event, NUM_DIALOG_UI_EVENTS); 409 } 410 411 void AutofillMetrics::LogWalletErrorMetric(autofill::DialogType dialog_type, 412 WalletErrorMetric metric) const { 413 std::string name = GetPrefixForDialogType(dialog_type) + ".WalletErrors"; 414 LogUMAHistogramEnumeration(name, metric, NUM_WALLET_ERROR_METRICS); 415 } 416 417 void AutofillMetrics::LogWalletApiCallDuration( 418 WalletApiCallMetric metric, 419 const base::TimeDelta& duration) const { 420 LogUMAHistogramTimes("Wallet.ApiCallDuration." + 421 WalletApiMetricToString(metric), duration); 422 } 423 424 void AutofillMetrics::LogWalletRequiredActionMetric( 425 autofill::DialogType dialog_type, 426 WalletRequiredActionMetric required_action) const { 427 std::string name = 428 GetPrefixForDialogType(dialog_type) + ".WalletRequiredActions"; 429 LogUMAHistogramEnumeration( 430 name, required_action, NUM_WALLET_REQUIRED_ACTIONS); 431 } 432 433 void AutofillMetrics::LogAutocheckoutDuration( 434 const base::TimeDelta& duration, 435 AutocheckoutCompletionStatus status) const { 436 std::string suffix; 437 switch (status) { 438 case AUTOCHECKOUT_CANCELLED: 439 suffix = "Cancelled"; 440 break; 441 442 case AUTOCHECKOUT_FAILED: 443 suffix = "Failed"; 444 break; 445 446 case AUTOCHECKOUT_SUCCEEDED: 447 suffix = "Succeeded"; 448 break; 449 } 450 451 LogUMAHistogramLongTimes("Autocheckout.FlowDuration", duration); 452 LogUMAHistogramLongTimes("Autocheckout.FlowDuration." + suffix, duration); 453 } 454 455 void AutofillMetrics::LogAutocheckoutWhitelistDownloadDuration( 456 const base::TimeDelta& duration, 457 AutocheckoutWhitelistDownloadStatus status) const { 458 std::string suffix; 459 switch (status) { 460 case AUTOCHECKOUT_WHITELIST_DOWNLOAD_FAILED: 461 suffix = "Failed"; 462 break; 463 464 case AUTOCHECKOUT_WHITELIST_DOWNLOAD_SUCCEEDED: 465 suffix = "Succeeded"; 466 break; 467 } 468 469 LogUMAHistogramTimes("Autocheckout.WhitelistDownloadDuration", duration); 470 LogUMAHistogramTimes( 471 "Autocheckout.WhitelistDownloadDuration." + suffix, duration); 472 } 473 474 void AutofillMetrics::LogDeveloperEngagementMetric( 475 DeveloperEngagementMetric metric) const { 476 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); 477 478 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, 479 NUM_DEVELOPER_ENGAGEMENT_METRICS); 480 } 481 482 void AutofillMetrics::LogHeuristicTypePrediction( 483 FieldTypeQualityMetric metric, 484 ServerFieldType field_type, 485 const std::string& experiment_id) const { 486 LogTypeQualityMetric("Autofill.Quality.HeuristicType", 487 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 488 field_type, experiment_id); 489 } 490 491 void AutofillMetrics::LogOverallTypePrediction( 492 FieldTypeQualityMetric metric, 493 ServerFieldType field_type, 494 const std::string& experiment_id) const { 495 LogTypeQualityMetric("Autofill.Quality.PredictedType", 496 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 497 field_type, experiment_id); 498 } 499 500 void AutofillMetrics::LogServerTypePrediction( 501 FieldTypeQualityMetric metric, 502 ServerFieldType field_type, 503 const std::string& experiment_id) const { 504 LogTypeQualityMetric("Autofill.Quality.ServerType", 505 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 506 field_type, experiment_id); 507 } 508 509 void AutofillMetrics::LogQualityMetric(QualityMetric metric, 510 const std::string& experiment_id) const { 511 DCHECK_LT(metric, NUM_QUALITY_METRICS); 512 513 std::string histogram_name = "Autofill.Quality"; 514 if (!experiment_id.empty()) 515 histogram_name += "_" + experiment_id; 516 517 LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS); 518 } 519 520 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const { 521 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); 522 523 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 524 NUM_SERVER_QUERY_METRICS); 525 } 526 527 void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const { 528 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS); 529 530 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric, 531 NUM_USER_HAPPINESS_METRICS); 532 } 533 534 void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill( 535 const base::TimeDelta& duration) const { 536 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill", 537 duration, 538 base::TimeDelta::FromMilliseconds(100), 539 base::TimeDelta::FromMinutes(10), 540 50); 541 } 542 543 void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill( 544 const base::TimeDelta& duration) const { 545 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill", 546 duration, 547 base::TimeDelta::FromMilliseconds(100), 548 base::TimeDelta::FromMinutes(10), 549 50); 550 } 551 552 void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( 553 const base::TimeDelta& duration) const { 554 UMA_HISTOGRAM_CUSTOM_TIMES( 555 "Autofill.FillDuration.FromInteraction.WithAutofill", 556 duration, 557 base::TimeDelta::FromMilliseconds(100), 558 base::TimeDelta::FromMinutes(10), 559 50); 560 } 561 562 void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( 563 const base::TimeDelta& duration) const { 564 UMA_HISTOGRAM_CUSTOM_TIMES( 565 "Autofill.FillDuration.FromInteraction.WithoutAutofill", 566 duration, 567 base::TimeDelta::FromMilliseconds(100), 568 base::TimeDelta::FromMinutes(10), 569 50); 570 } 571 572 void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const { 573 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled); 574 } 575 576 void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const { 577 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); 578 } 579 580 void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const { 581 UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles); 582 } 583 584 void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const { 585 UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions); 586 } 587 588 void AutofillMetrics::LogServerExperimentIdForQuery( 589 const std::string& experiment_id) const { 590 LogServerExperimentId("Autofill.ServerExperimentId.Query", experiment_id); 591 } 592 593 void AutofillMetrics::LogServerExperimentIdForUpload( 594 const std::string& experiment_id) const { 595 LogServerExperimentId("Autofill.ServerExperimentId.Upload", experiment_id); 596 } 597 598 } // namespace autofill 599