// 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);
}