// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/autofill/autofill_metrics.h" #include "base/logging.h" #include "base/metrics/histogram.h" #include "chrome/browser/autofill/autofill_type.h" namespace { enum FieldTypeGroupForMetrics { AMBIGUOUS = 0, NAME, COMPANY, ADDRESS_LINE_1, ADDRESS_LINE_2, ADDRESS_CITY, ADDRESS_STATE, ADDRESS_ZIP, ADDRESS_COUNTRY, PHONE, FAX, EMAIL, CREDIT_CARD_NAME, CREDIT_CARD_NUMBER, CREDIT_CARD_DATE, NUM_FIELD_TYPE_GROUPS_FOR_METRICS }; // Translates |field_type| to the corresponding logical grouping for metrics, // and then interpolates this with the given |metric|, which should be in the // range [0, |num_possible_metrics|). Returns the interpolated metric. // Clients must ensure that |field_type| is one of the types Chrome supports // natively, e.g. |field_type| must not be a billng address. int GetFieldTypeGroupMetric(const AutofillFieldType field_type, const int metric, const int num_possible_metrics) { DCHECK(metric < num_possible_metrics); FieldTypeGroupForMetrics group; switch (AutofillType(field_type).group()) { case AutofillType::NO_GROUP: group = AMBIGUOUS; break; case AutofillType::NAME: group = NAME; break; case AutofillType::COMPANY: group = COMPANY; break; case AutofillType::ADDRESS_HOME: switch (field_type) { case ADDRESS_HOME_LINE1: group = ADDRESS_LINE_1; break; case ADDRESS_HOME_LINE2: group = ADDRESS_LINE_2; break; case ADDRESS_HOME_CITY: group = ADDRESS_CITY; break; case ADDRESS_HOME_STATE: group = ADDRESS_STATE; break; case ADDRESS_HOME_ZIP: group = ADDRESS_ZIP; break; case ADDRESS_HOME_COUNTRY: group = ADDRESS_COUNTRY; break; default: NOTREACHED(); group = AMBIGUOUS; } break; case AutofillType::EMAIL: group = EMAIL; break; case AutofillType::PHONE_HOME: group = PHONE; break; case AutofillType::PHONE_FAX: group = FAX; break; case AutofillType::CREDIT_CARD: switch (field_type) { case ::CREDIT_CARD_NAME: group = CREDIT_CARD_NAME; break; case ::CREDIT_CARD_NUMBER: group = CREDIT_CARD_NUMBER; break; default: group = CREDIT_CARD_DATE; } break; default: NOTREACHED(); group = AMBIGUOUS; } // Interpolate the |metric| with the |group|, so that all metrics for a given // |group| are adjacent. The resulting metrics will be arranged as: // AMBIGUOUS_UNKNOWN // AMBIGUOUS_MATCH // AMBIGUOUS_MISMATCH // NAME_UNKNOWN // NAME_MATCH // NAME_MISMATCH // ... return (group * num_possible_metrics) + metric; } // A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| // to vary over the program's runtime. void LogUMAHistogramEnumeration(const std::string& name, int sample, int boundary_value) { // We can't use the UMA_HISTOGRAM_ENUMERATION macro here because the histogram // name can vary over the duration of the program. // Note that this leaks memory; that is expected behavior. base::Histogram* counter = base::LinearHistogram::FactoryGet( name, 1, boundary_value, boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); counter->Add(sample); } // Logs a type quality metric. The primary histogram name is constructed based // on |base_name| and |experiment_id|. The field-specific histogram name also // factors in the |field_type|. Logs a sample of |metric|, which should be in // the range [0, |num_possible_metrics|). void LogTypeQualityMetric(const std::string& base_name, const int metric, const int num_possible_metrics, const AutofillFieldType field_type, const std::string& experiment_id) { DCHECK(metric < num_possible_metrics); std::string histogram_name = base_name; if (!experiment_id.empty()) histogram_name += "_" + experiment_id; LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics); std::string sub_histogram_name = base_name + ".ByFieldType"; if (!experiment_id.empty()) sub_histogram_name += "_" + experiment_id; const int field_type_group_metric = GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics); const int num_field_type_group_metrics = num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS; LogUMAHistogramEnumeration(sub_histogram_name, field_type_group_metric, num_field_type_group_metrics); } } // namespace AutofillMetrics::AutofillMetrics() { } AutofillMetrics::~AutofillMetrics() { } void AutofillMetrics::Log(CreditCardInfoBarMetric metric) const { DCHECK(metric < NUM_CREDIT_CARD_INFO_BAR_METRICS); UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric, NUM_CREDIT_CARD_INFO_BAR_METRICS); } void AutofillMetrics::Log(HeuristicTypeQualityMetric metric, AutofillFieldType field_type, const std::string& experiment_id) const { LogTypeQualityMetric("Autofill.Quality.HeuristicType", metric, NUM_HEURISTIC_TYPE_QUALITY_METRICS, field_type, experiment_id); } void AutofillMetrics::Log(PredictedTypeQualityMetric metric, AutofillFieldType field_type, const std::string& experiment_id) const { LogTypeQualityMetric("Autofill.Quality.PredictedType", metric, NUM_PREDICTED_TYPE_QUALITY_METRICS, field_type, experiment_id); } void AutofillMetrics::Log(QualityMetric metric, const std::string& experiment_id) const { DCHECK(metric < NUM_QUALITY_METRICS); std::string histogram_name = "Autofill.Quality"; if (!experiment_id.empty()) histogram_name += "_" + experiment_id; LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS); } void AutofillMetrics::Log(ServerQueryMetric metric) const { DCHECK(metric < NUM_SERVER_QUERY_METRICS); UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, NUM_SERVER_QUERY_METRICS); } void AutofillMetrics::Log(ServerTypeQualityMetric metric, AutofillFieldType field_type, const std::string& experiment_id) const { LogTypeQualityMetric("Autofill.Quality.ServerType", metric, NUM_SERVER_TYPE_QUALITY_METRICS, field_type, experiment_id); } void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const { UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled); } void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const { UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); } void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const { UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles); } void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const { UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions); }