autofill_metrics.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 14namespace autofill { 15 16namespace { 17 18// Server experiments we support. 19enum 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 41enum 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. 82int GetFieldTypeGroupMetric(const AutofillFieldType 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 AutofillType::NO_GROUP: 90 group = AMBIGUOUS; 91 break; 92 93 case AutofillType::NAME: 94 group = NAME; 95 break; 96 97 case AutofillType::COMPANY: 98 group = COMPANY; 99 break; 100 101 case AutofillType::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 AutofillType::EMAIL: 128 group = EMAIL; 129 break; 130 131 case AutofillType::PHONE_HOME: 132 group = PHONE; 133 break; 134 135 case AutofillType::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|. 161std::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 174std::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_ADDRESS: 186 return "SaveAddress"; 187 case AutofillMetrics::SAVE_INSTRUMENT: 188 return "SaveInstrument"; 189 case AutofillMetrics::SAVE_INSTRUMENT_AND_ADDRESS: 190 return "SaveInstrumentAndAddress"; 191 case AutofillMetrics::SEND_STATUS: 192 return "SendStatus"; 193 case AutofillMetrics::UPDATE_ADDRESS: 194 return "UpdateAddress"; 195 case AutofillMetrics::UPDATE_INSTRUMENT: 196 return "UpdateInstrument"; 197 case AutofillMetrics::UNKNOWN_API_CALL: 198 NOTREACHED(); 199 return "UnknownApiCall"; 200 } 201 202 NOTREACHED(); 203 return "UnknownApiCall"; 204} 205 206// A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| 207// to vary over the program's runtime. 208void LogUMAHistogramEnumeration(const std::string& name, 209 int sample, 210 int boundary_value) { 211 DCHECK_LT(sample, boundary_value); 212 213 // Note: This leaks memory, which is expected behavior. 214 base::HistogramBase* histogram = 215 base::LinearHistogram::FactoryGet( 216 name, 217 1, 218 boundary_value, 219 boundary_value + 1, 220 base::HistogramBase::kUmaTargetedHistogramFlag); 221 histogram->Add(sample); 222} 223 224// A version of the UMA_HISTOGRAM_TIMES macro that allows the |name| 225// to vary over the program's runtime. 226void LogUMAHistogramTimes(const std::string& name, 227 const base::TimeDelta& duration) { 228 // Note: This leaks memory, which is expected behavior. 229 base::HistogramBase* histogram = 230 base::Histogram::FactoryTimeGet( 231 name, 232 base::TimeDelta::FromMilliseconds(1), 233 base::TimeDelta::FromSeconds(10), 234 50, 235 base::HistogramBase::kUmaTargetedHistogramFlag); 236 histogram->AddTime(duration); 237} 238 239// A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name| 240// to vary over the program's runtime. 241void LogUMAHistogramLongTimes(const std::string& name, 242 const base::TimeDelta& duration) { 243 // Note: This leaks memory, which is expected behavior. 244 base::HistogramBase* histogram = 245 base::Histogram::FactoryTimeGet( 246 name, 247 base::TimeDelta::FromMilliseconds(1), 248 base::TimeDelta::FromHours(1), 249 50, 250 base::HistogramBase::kUmaTargetedHistogramFlag); 251 histogram->AddTime(duration); 252} 253 254// Logs a type quality metric. The primary histogram name is constructed based 255// on |base_name| and |experiment_id|. The field-specific histogram name also 256// factors in the |field_type|. Logs a sample of |metric|, which should be in 257// the range [0, |num_possible_metrics|). 258void LogTypeQualityMetric(const std::string& base_name, 259 const int metric, 260 const int num_possible_metrics, 261 const AutofillFieldType field_type, 262 const std::string& experiment_id) { 263 DCHECK_LT(metric, num_possible_metrics); 264 265 std::string histogram_name = base_name; 266 if (!experiment_id.empty()) 267 histogram_name += "_" + experiment_id; 268 LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics); 269 270 std::string sub_histogram_name = base_name + ".ByFieldType"; 271 if (!experiment_id.empty()) 272 sub_histogram_name += "_" + experiment_id; 273 const int field_type_group_metric = 274 GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics); 275 const int num_field_type_group_metrics = 276 num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS; 277 LogUMAHistogramEnumeration(sub_histogram_name, 278 field_type_group_metric, 279 num_field_type_group_metrics); 280} 281 282void LogServerExperimentId(const std::string& histogram_name, 283 const std::string& experiment_id) { 284 ServerExperiment metric = UNKNOWN_EXPERIMENT; 285 286 const std::string default_experiment_name = 287 FormStructure(FormData(), std::string()).server_experiment_id(); 288 if (experiment_id.empty()) 289 metric = NO_EXPERIMENT; 290 else if (experiment_id == "ar06") 291 metric = ACCEPTANCE_RATIO_06; 292 else if (experiment_id == "ar1") 293 metric = ACCEPTANCE_RATIO_1; 294 else if (experiment_id == "ar2") 295 metric = ACCEPTANCE_RATIO_2; 296 else if (experiment_id == "ar4") 297 metric = ACCEPTANCE_RATIO_4; 298 else if (experiment_id == "ar05wlr15") 299 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15; 300 else if (experiment_id == "ar05wlr25") 301 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25; 302 else if (experiment_id == "ar05wr15fs5") 303 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5; 304 else if (experiment_id == "tbar1") 305 metric = TOOLBAR_DATA_ONLY; 306 else if (experiment_id == "ar04wr3fs4") 307 metric = ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4; 308 else if (experiment_id == default_experiment_name) 309 metric = NO_SERVER_RESPONSE; 310 else if (experiment_id == "fp05") 311 metric = PROBABILITY_PICKER_05; 312 else if (experiment_id == "fp025") 313 metric = PROBABILITY_PICKER_025; 314 else if (experiment_id == "fp05cc03") 315 metric = PROBABILITY_PICKER_025_CC_THRESHOLD_03; 316 else if (experiment_id == "fp05cco03") 317 metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03; 318 else if (experiment_id == "fp05cco03cstd") 319 metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK; 320 else if (experiment_id == "fp05cc03e1") 321 metric = PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1; 322 323 DCHECK_LT(metric, NUM_SERVER_EXPERIMENTS); 324 LogUMAHistogramEnumeration(histogram_name, metric, NUM_SERVER_EXPERIMENTS); 325} 326 327} // namespace 328 329AutofillMetrics::AutofillMetrics() { 330} 331 332AutofillMetrics::~AutofillMetrics() { 333} 334 335void AutofillMetrics::LogAutocheckoutBubbleMetric(BubbleMetric metric) const { 336 DCHECK_LT(metric, NUM_BUBBLE_METRICS); 337 338 UMA_HISTOGRAM_ENUMERATION("Autocheckout.Bubble", metric, NUM_BUBBLE_METRICS); 339} 340 341void AutofillMetrics::LogAutocheckoutBuyFlowMetric( 342 AutocheckoutBuyFlowMetric metric) const { 343 DCHECK_LT(metric, NUM_AUTOCHECKOUT_BUY_FLOW_METRICS); 344 345 UMA_HISTOGRAM_ENUMERATION("Autocheckout.BuyFlow", metric, 346 NUM_AUTOCHECKOUT_BUY_FLOW_METRICS); 347} 348 349void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const { 350 DCHECK_LT(metric, NUM_INFO_BAR_METRICS); 351 352 UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric, 353 NUM_INFO_BAR_METRICS); 354} 355 356void AutofillMetrics::LogDialogDismissalState( 357 autofill::DialogType dialog_type, 358 DialogDismissalState state) const { 359 std::string name = GetPrefixForDialogType(dialog_type) + ".DismissalState"; 360 LogUMAHistogramEnumeration(name, state, NUM_DIALOG_DISMISSAL_STATES); 361} 362 363void AutofillMetrics::LogDialogInitialUserState( 364 autofill::DialogType dialog_type, 365 DialogInitialUserStateMetric user_type) const { 366 std::string name = GetPrefixForDialogType(dialog_type) + ".InitialUserState"; 367 LogUMAHistogramEnumeration( 368 name, user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS); 369} 370 371void AutofillMetrics::LogDialogLatencyToShow( 372 autofill::DialogType dialog_type, 373 const base::TimeDelta& duration) const { 374 std::string name = 375 GetPrefixForDialogType(dialog_type) + ".UiLatencyToShow"; 376 LogUMAHistogramTimes(name, duration); 377} 378 379void AutofillMetrics::LogDialogPopupEvent(autofill::DialogType dialog_type, 380 DialogPopupEvent event) const { 381 std::string name = GetPrefixForDialogType(dialog_type) + ".PopupInDialog"; 382 LogUMAHistogramEnumeration(name, event, NUM_DIALOG_POPUP_EVENTS); 383} 384 385void AutofillMetrics::LogDialogSecurityMetric( 386 autofill::DialogType dialog_type, 387 DialogSecurityMetric metric) const { 388 std::string name = GetPrefixForDialogType(dialog_type) + ".Security"; 389 LogUMAHistogramEnumeration(name, metric, NUM_DIALOG_SECURITY_METRICS); 390} 391 392void AutofillMetrics::LogDialogUiDuration( 393 const base::TimeDelta& duration, 394 autofill::DialogType dialog_type, 395 DialogDismissalAction dismissal_action) const { 396 std::string prefix = GetPrefixForDialogType(dialog_type); 397 398 std::string suffix; 399 switch (dismissal_action) { 400 case DIALOG_ACCEPTED: 401 suffix = "Submit"; 402 break; 403 404 case DIALOG_CANCELED: 405 suffix = "Cancel"; 406 break; 407 } 408 409 LogUMAHistogramLongTimes(prefix + ".UiDuration", duration); 410 LogUMAHistogramLongTimes(prefix + ".UiDuration." + suffix, duration); 411} 412 413void AutofillMetrics::LogDialogUiEvent(autofill::DialogType dialog_type, 414 DialogUiEvent event) const { 415 std::string name = GetPrefixForDialogType(dialog_type) + ".UiEvents"; 416 LogUMAHistogramEnumeration(name, event, NUM_DIALOG_UI_EVENTS); 417} 418 419void AutofillMetrics::LogWalletErrorMetric(autofill::DialogType dialog_type, 420 WalletErrorMetric metric) const { 421 std::string name = GetPrefixForDialogType(dialog_type) + ".WalletErrors"; 422 LogUMAHistogramEnumeration(name, metric, NUM_WALLET_ERROR_METRICS); 423} 424 425void AutofillMetrics::LogWalletApiCallDuration( 426 WalletApiCallMetric metric, 427 const base::TimeDelta& duration) const { 428 LogUMAHistogramTimes("Wallet.ApiCallDuration." + 429 WalletApiMetricToString(metric), duration); 430} 431 432void AutofillMetrics::LogWalletRequiredActionMetric( 433 autofill::DialogType dialog_type, 434 WalletRequiredActionMetric required_action) const { 435 std::string name = 436 GetPrefixForDialogType(dialog_type) + ".WalletRequiredActions"; 437 LogUMAHistogramEnumeration( 438 name, required_action, NUM_WALLET_REQUIRED_ACTIONS); 439} 440 441void AutofillMetrics::LogAutocheckoutDuration( 442 const base::TimeDelta& duration, 443 AutocheckoutCompletionStatus status) const { 444 std::string suffix; 445 switch (status) { 446 case AUTOCHECKOUT_CANCELLED: 447 suffix = "Cancelled"; 448 break; 449 450 case AUTOCHECKOUT_FAILED: 451 suffix = "Failed"; 452 break; 453 454 case AUTOCHECKOUT_SUCCEEDED: 455 suffix = "Succeeded"; 456 break; 457 } 458 459 LogUMAHistogramLongTimes("Autocheckout.FlowDuration", duration); 460 LogUMAHistogramLongTimes("Autocheckout.FlowDuration." + suffix, duration); 461} 462 463void AutofillMetrics::LogAutocheckoutWhitelistDownloadDuration( 464 const base::TimeDelta& duration, 465 AutocheckoutWhitelistDownloadStatus status) const { 466 std::string suffix; 467 switch (status) { 468 case AUTOCHECKOUT_WHITELIST_DOWNLOAD_FAILED: 469 suffix = "Failed"; 470 break; 471 472 case AUTOCHECKOUT_WHITELIST_DOWNLOAD_SUCCEEDED: 473 suffix = "Succeeded"; 474 break; 475 } 476 477 LogUMAHistogramTimes("Autocheckout.WhitelistDownloadDuration", duration); 478 LogUMAHistogramTimes( 479 "Autocheckout.WhitelistDownloadDuration." + suffix, duration); 480} 481 482void AutofillMetrics::LogDeveloperEngagementMetric( 483 DeveloperEngagementMetric metric) const { 484 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); 485 486 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, 487 NUM_DEVELOPER_ENGAGEMENT_METRICS); 488} 489 490void AutofillMetrics::LogHeuristicTypePrediction( 491 FieldTypeQualityMetric metric, 492 AutofillFieldType field_type, 493 const std::string& experiment_id) const { 494 LogTypeQualityMetric("Autofill.Quality.HeuristicType", 495 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 496 field_type, experiment_id); 497} 498 499void AutofillMetrics::LogOverallTypePrediction( 500 FieldTypeQualityMetric metric, 501 AutofillFieldType field_type, 502 const std::string& experiment_id) const { 503 LogTypeQualityMetric("Autofill.Quality.PredictedType", 504 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 505 field_type, experiment_id); 506} 507 508void AutofillMetrics::LogServerTypePrediction( 509 FieldTypeQualityMetric metric, 510 AutofillFieldType field_type, 511 const std::string& experiment_id) const { 512 LogTypeQualityMetric("Autofill.Quality.ServerType", 513 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 514 field_type, experiment_id); 515} 516 517void AutofillMetrics::LogQualityMetric(QualityMetric metric, 518 const std::string& experiment_id) const { 519 DCHECK_LT(metric, NUM_QUALITY_METRICS); 520 521 std::string histogram_name = "Autofill.Quality"; 522 if (!experiment_id.empty()) 523 histogram_name += "_" + experiment_id; 524 525 LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS); 526} 527 528void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const { 529 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); 530 531 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 532 NUM_SERVER_QUERY_METRICS); 533} 534 535void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const { 536 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS); 537 538 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric, 539 NUM_USER_HAPPINESS_METRICS); 540} 541 542void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill( 543 const base::TimeDelta& duration) const { 544 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill", 545 duration, 546 base::TimeDelta::FromMilliseconds(100), 547 base::TimeDelta::FromMinutes(10), 548 50); 549} 550 551void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill( 552 const base::TimeDelta& duration) const { 553 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill", 554 duration, 555 base::TimeDelta::FromMilliseconds(100), 556 base::TimeDelta::FromMinutes(10), 557 50); 558} 559 560void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( 561 const base::TimeDelta& duration) const { 562 UMA_HISTOGRAM_CUSTOM_TIMES( 563 "Autofill.FillDuration.FromInteraction.WithAutofill", 564 duration, 565 base::TimeDelta::FromMilliseconds(100), 566 base::TimeDelta::FromMinutes(10), 567 50); 568} 569 570void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( 571 const base::TimeDelta& duration) const { 572 UMA_HISTOGRAM_CUSTOM_TIMES( 573 "Autofill.FillDuration.FromInteraction.WithoutAutofill", 574 duration, 575 base::TimeDelta::FromMilliseconds(100), 576 base::TimeDelta::FromMinutes(10), 577 50); 578} 579 580void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const { 581 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled); 582} 583 584void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const { 585 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); 586} 587 588void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const { 589 UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles); 590} 591 592void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const { 593 UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions); 594} 595 596void AutofillMetrics::LogServerExperimentIdForQuery( 597 const std::string& experiment_id) const { 598 LogServerExperimentId("Autofill.ServerExperimentId.Query", experiment_id); 599} 600 601void AutofillMetrics::LogServerExperimentIdForUpload( 602 const std::string& experiment_id) const { 603 LogServerExperimentId("Autofill.ServerExperimentId.Upload", experiment_id); 604} 605 606} // namespace autofill 607