autofill_metrics.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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_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.
200void 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.
218void 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.
233void 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|).
250void LogTypeQualityMetric(const std::string& base_name,
251                          const int metric,
252                          const int num_possible_metrics,
253                          const AutofillFieldType 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
274void 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
321AutofillMetrics::AutofillMetrics() {
322}
323
324AutofillMetrics::~AutofillMetrics() {
325}
326
327void 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
333void 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
341void 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
348void 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
355void 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
363void 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
371void 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
377void 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
384void 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
405void 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
411void 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
417void AutofillMetrics::LogWalletApiCallDuration(
418    WalletApiCallMetric metric,
419    const base::TimeDelta& duration) const {
420  LogUMAHistogramTimes("Wallet.ApiCallDuration." +
421                       WalletApiMetricToString(metric), duration);
422}
423
424void 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
433void 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
455void 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
474void 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
482void AutofillMetrics::LogHeuristicTypePrediction(
483    FieldTypeQualityMetric metric,
484    AutofillFieldType 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
491void AutofillMetrics::LogOverallTypePrediction(
492    FieldTypeQualityMetric metric,
493    AutofillFieldType 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
500void AutofillMetrics::LogServerTypePrediction(
501    FieldTypeQualityMetric metric,
502    AutofillFieldType 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
509void 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
520void 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
527void 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
534void 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
543void 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
552void 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
562void 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
572void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const {
573  UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled);
574}
575
576void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const {
577  UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled);
578}
579
580void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const {
581  UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles);
582}
583
584void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const {
585  UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions);
586}
587
588void AutofillMetrics::LogServerExperimentIdForQuery(
589    const std::string& experiment_id) const {
590  LogServerExperimentId("Autofill.ServerExperimentId.Query", experiment_id);
591}
592
593void AutofillMetrics::LogServerExperimentIdForUpload(
594    const std::string& experiment_id) const {
595  LogServerExperimentId("Autofill.ServerExperimentId.Upload", experiment_id);
596}
597
598}  // namespace autofill
599