1 // Copyright (c) 2011 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 "chrome/browser/autofill/autofill_metrics.h" 6 7 #include "base/logging.h" 8 #include "base/metrics/histogram.h" 9 #include "chrome/browser/autofill/autofill_type.h" 10 11 namespace { 12 13 enum FieldTypeGroupForMetrics { 14 AMBIGUOUS = 0, 15 NAME, 16 COMPANY, 17 ADDRESS_LINE_1, 18 ADDRESS_LINE_2, 19 ADDRESS_CITY, 20 ADDRESS_STATE, 21 ADDRESS_ZIP, 22 ADDRESS_COUNTRY, 23 PHONE, 24 FAX, 25 EMAIL, 26 CREDIT_CARD_NAME, 27 CREDIT_CARD_NUMBER, 28 CREDIT_CARD_DATE, 29 NUM_FIELD_TYPE_GROUPS_FOR_METRICS 30 }; 31 32 // Translates |field_type| to the corresponding logical grouping for metrics, 33 // and then interpolates this with the given |metric|, which should be in the 34 // range [0, |num_possible_metrics|). Returns the interpolated metric. 35 // Clients must ensure that |field_type| is one of the types Chrome supports 36 // natively, e.g. |field_type| must not be a billng address. 37 int GetFieldTypeGroupMetric(const AutofillFieldType field_type, 38 const int metric, 39 const int num_possible_metrics) { 40 DCHECK(metric < num_possible_metrics); 41 42 FieldTypeGroupForMetrics group; 43 switch (AutofillType(field_type).group()) { 44 case AutofillType::NO_GROUP: 45 group = AMBIGUOUS; 46 break; 47 48 case AutofillType::NAME: 49 group = NAME; 50 break; 51 52 case AutofillType::COMPANY: 53 group = COMPANY; 54 break; 55 56 case AutofillType::ADDRESS_HOME: 57 switch (field_type) { 58 case ADDRESS_HOME_LINE1: 59 group = ADDRESS_LINE_1; 60 break; 61 case ADDRESS_HOME_LINE2: 62 group = ADDRESS_LINE_2; 63 break; 64 case ADDRESS_HOME_CITY: 65 group = ADDRESS_CITY; 66 break; 67 case ADDRESS_HOME_STATE: 68 group = ADDRESS_STATE; 69 break; 70 case ADDRESS_HOME_ZIP: 71 group = ADDRESS_ZIP; 72 break; 73 case ADDRESS_HOME_COUNTRY: 74 group = ADDRESS_COUNTRY; 75 break; 76 default: 77 NOTREACHED(); 78 group = AMBIGUOUS; 79 } 80 break; 81 82 case AutofillType::EMAIL: 83 group = EMAIL; 84 break; 85 86 case AutofillType::PHONE_HOME: 87 group = PHONE; 88 break; 89 90 case AutofillType::PHONE_FAX: 91 group = FAX; 92 break; 93 94 case AutofillType::CREDIT_CARD: 95 switch (field_type) { 96 case ::CREDIT_CARD_NAME: 97 group = CREDIT_CARD_NAME; 98 break; 99 case ::CREDIT_CARD_NUMBER: 100 group = CREDIT_CARD_NUMBER; 101 break; 102 default: 103 group = CREDIT_CARD_DATE; 104 } 105 break; 106 107 default: 108 NOTREACHED(); 109 group = AMBIGUOUS; 110 } 111 112 // Interpolate the |metric| with the |group|, so that all metrics for a given 113 // |group| are adjacent. The resulting metrics will be arranged as: 114 // AMBIGUOUS_UNKNOWN 115 // AMBIGUOUS_MATCH 116 // AMBIGUOUS_MISMATCH 117 // NAME_UNKNOWN 118 // NAME_MATCH 119 // NAME_MISMATCH 120 // ... 121 return (group * num_possible_metrics) + metric; 122 } 123 124 // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| 125 // to vary over the program's runtime. 126 void LogUMAHistogramEnumeration(const std::string& name, 127 int sample, 128 int boundary_value) { 129 // We can't use the UMA_HISTOGRAM_ENUMERATION macro here because the histogram 130 // name can vary over the duration of the program. 131 // Note that this leaks memory; that is expected behavior. 132 base::Histogram* counter = 133 base::LinearHistogram::FactoryGet( 134 name, 135 1, 136 boundary_value, 137 boundary_value + 1, 138 base::Histogram::kUmaTargetedHistogramFlag); 139 counter->Add(sample); 140 } 141 142 // Logs a type quality metric. The primary histogram name is constructed based 143 // on |base_name| and |experiment_id|. The field-specific histogram name also 144 // factors in the |field_type|. Logs a sample of |metric|, which should be in 145 // the range [0, |num_possible_metrics|). 146 void LogTypeQualityMetric(const std::string& base_name, 147 const int metric, 148 const int num_possible_metrics, 149 const AutofillFieldType field_type, 150 const std::string& experiment_id) { 151 DCHECK(metric < num_possible_metrics); 152 153 std::string histogram_name = base_name; 154 if (!experiment_id.empty()) 155 histogram_name += "_" + experiment_id; 156 LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics); 157 158 std::string sub_histogram_name = base_name + ".ByFieldType"; 159 if (!experiment_id.empty()) 160 sub_histogram_name += "_" + experiment_id; 161 const int field_type_group_metric = 162 GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics); 163 const int num_field_type_group_metrics = 164 num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS; 165 LogUMAHistogramEnumeration(sub_histogram_name, 166 field_type_group_metric, 167 num_field_type_group_metrics); 168 } 169 170 } // namespace 171 172 AutofillMetrics::AutofillMetrics() { 173 } 174 175 AutofillMetrics::~AutofillMetrics() { 176 } 177 178 void AutofillMetrics::Log(CreditCardInfoBarMetric metric) const { 179 DCHECK(metric < NUM_CREDIT_CARD_INFO_BAR_METRICS); 180 181 UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric, 182 NUM_CREDIT_CARD_INFO_BAR_METRICS); 183 } 184 185 void AutofillMetrics::Log(HeuristicTypeQualityMetric metric, 186 AutofillFieldType field_type, 187 const std::string& experiment_id) const { 188 LogTypeQualityMetric("Autofill.Quality.HeuristicType", 189 metric, NUM_HEURISTIC_TYPE_QUALITY_METRICS, 190 field_type, experiment_id); 191 } 192 193 void AutofillMetrics::Log(PredictedTypeQualityMetric metric, 194 AutofillFieldType field_type, 195 const std::string& experiment_id) const { 196 LogTypeQualityMetric("Autofill.Quality.PredictedType", 197 metric, NUM_PREDICTED_TYPE_QUALITY_METRICS, 198 field_type, experiment_id); 199 } 200 201 void AutofillMetrics::Log(QualityMetric metric, 202 const std::string& experiment_id) const { 203 DCHECK(metric < NUM_QUALITY_METRICS); 204 205 std::string histogram_name = "Autofill.Quality"; 206 if (!experiment_id.empty()) 207 histogram_name += "_" + experiment_id; 208 209 LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS); 210 } 211 212 void AutofillMetrics::Log(ServerQueryMetric metric) const { 213 DCHECK(metric < NUM_SERVER_QUERY_METRICS); 214 215 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 216 NUM_SERVER_QUERY_METRICS); 217 } 218 219 void AutofillMetrics::Log(ServerTypeQualityMetric metric, 220 AutofillFieldType field_type, 221 const std::string& experiment_id) const { 222 LogTypeQualityMetric("Autofill.Quality.ServerType", 223 metric, NUM_SERVER_TYPE_QUALITY_METRICS, 224 field_type, experiment_id); 225 } 226 227 void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const { 228 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled); 229 } 230 231 void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const { 232 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); 233 } 234 235 void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const { 236 UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles); 237 } 238 239 void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const { 240 UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions); 241 } 242