Skip to content

Commit

Permalink
Split StoredProfileCount metrics by profile category.
Browse files Browse the repository at this point in the history
Currently metrics about the stored profiles are only emitted for
kLocalOrSyncable profiles. This CL extends the following metrics to
kAccount profiles:
- Autofill.StoredProfileCount
- Autofill.StoredProfileUsedCount
- Autofill.StoredProfileDisusedCount
- Autofill.StoredProfileUsedPercentage
- Autofill.DaysSinceLastUse.StoredProfile

Autofill.StoredProfileWithoutCountryCount is not extended to kAccount
profiles, since they are guaranteed to have a country.

As described in the PRD, to get a valuable signal, kAccount profiles
need to be further distinguished by their initial creator. To do so,
this CL introduces the notion of a ProfileCategory for metrics, which
is one of kLocalOrSyncable, kAccountChrome, kAccountNonChrome or kMixed,
indicating the types of profiles that went into the aggregation. Each
of the metrics mentioned above is then emitted once per category.

The unit tests are parameterized by category.

Bug: 1348294
Change-Id: Ic30b25f4a78b8659701d46c7af4154a3750fd08b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4136196
Reviewed-by: Matthias Körber <koerber@google.com>
Reviewed-by: Vidhan Jain <vidhanj@google.com>
Commit-Queue: Florian Leimgruber <fleimgruber@google.com>
Cr-Commit-Position: refs/heads/main@{#1099145}
  • Loading branch information
florianleimgruber authored and Chromium LUCI CQ committed Jan 31, 2023
1 parent fc55da6 commit 0d09e66
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 130 deletions.
80 changes: 59 additions & 21 deletions components/autofill/core/browser/metrics/autofill_metrics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1544,35 +1544,73 @@ void AutofillMetrics::LogIsAutofillCreditCardEnabledAtPageLoad(
enabled);
}

// static
AutofillMetrics::AutofillProfileSourceCategory
AutofillMetrics::GetCategoryOfProfile(const AutofillProfile& profile) {
switch (profile.source()) {
case AutofillProfile::Source::kLocalOrSyncable:
return AutofillMetrics::AutofillProfileSourceCategory::kLocalOrSyncable;
case AutofillProfile::Source::kAccount:
return profile.initial_creator_id() ==
AutofillProfile::kInitialCreatorOrModifierChrome
? AutofillMetrics::AutofillProfileSourceCategory::
kAccountChrome
: AutofillMetrics::AutofillProfileSourceCategory::
kAccountNonChrome;
}
}

// static
const char* AutofillMetrics::GetProfileCategorySuffix(
AutofillMetrics::AutofillProfileSourceCategory category) {
switch (category) {
case AutofillMetrics::AutofillProfileSourceCategory::kLocalOrSyncable:
return "Legacy";
case AutofillMetrics::AutofillProfileSourceCategory::kAccountChrome:
return "AccountChrome";
case AutofillMetrics::AutofillProfileSourceCategory::kAccountNonChrome:
return "AccountNonChrome";
}
}

// static
void AutofillMetrics::LogStoredProfileCountStatistics(
size_t num_profiles,
size_t num_disused_profiles,
size_t num_countryless_profiles) {
UMA_HISTOGRAM_COUNTS_1M("Autofill.StoredProfileCount", num_profiles);
AutofillProfileSourceCategory category,
const StoredProfileCounts& counts) {
const std::string kSuffix = GetProfileCategorySuffix(category);

base::UmaHistogramCounts1M("Autofill.StoredProfileCount." + kSuffix,
counts.total);
// For users without any profiles do not record the other metrics.
if (num_profiles == 0)
if (counts.total == 0) {
return;

DCHECK_LE(num_disused_profiles, num_profiles);
size_t num_used_profiles = num_profiles - num_disused_profiles;

UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredProfileUsedCount",
num_used_profiles);
UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredProfileDisusedCount",
num_disused_profiles);
UMA_HISTOGRAM_COUNTS_1M("Autofill.StoredProfileWithoutCountryCount",
num_countryless_profiles);

int use_percentage = (100 * num_used_profiles) / num_profiles;
UMA_HISTOGRAM_PERCENTAGE("Autofill.StoredProfileUsedPercentage",
use_percentage);
}
DCHECK_LE(counts.disused, counts.total);
size_t used = counts.total - counts.disused;
base::UmaHistogramCounts1000("Autofill.StoredProfileUsedCount." + kSuffix,
used);
base::UmaHistogramCounts1000("Autofill.StoredProfileDisusedCount." + kSuffix,
counts.disused);
base::UmaHistogramPercentage(
"Autofill.StoredProfileUsedPercentage." + kSuffix,
100 * used / counts.total);
// `kAccount` profiles are guaranteed to have a country, so this metric is
// only tracked for the `kLocalOrSyncable` category. For this reason `kSuffix`
// is not applied to the metrics name either.
if (category == AutofillProfileSourceCategory::kLocalOrSyncable) {
UMA_HISTOGRAM_COUNTS_1M("Autofill.StoredProfileWithoutCountryCount",
counts.without_country);
}
}

// static
void AutofillMetrics::LogStoredProfileDaysSinceLastUse(size_t days) {
UMA_HISTOGRAM_COUNTS_1000("Autofill.DaysSinceLastUse.StoredProfile", days);
void AutofillMetrics::LogStoredProfileDaysSinceLastUse(
AutofillProfileSourceCategory category,
size_t days) {
base::UmaHistogramCounts1000(
base::StrCat({"Autofill.DaysSinceLastUse.StoredProfile.",
GetProfileCategorySuffix(category)}),
days);
}

// static
Expand Down
50 changes: 43 additions & 7 deletions components/autofill/core/browser/metrics/autofill_metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,17 @@ class AutofillMetrics {
kMaxValue = kLeftEmpty
};

// kAccount profiles are synced from an external source and have potentially
// originated from outside of Autofill. In order to determine the added value
// for Autofill, the `AutofillProfile::Source` is further resolved in some
// metrics.
enum class AutofillProfileSourceCategory {
kLocalOrSyncable = 0,
kAccountChrome = 1,
kAccountNonChrome = 2,
kMaxValue = kAccountNonChrome
};

// Utility class for determining the seamlessness of a credit card fill.
class CreditCardSeamlessness {
public:
Expand Down Expand Up @@ -1087,15 +1098,40 @@ class AutofillMetrics {
// This should be called each time a new chrome profile is launched.
static void LogIsAutofillCreditCardEnabledAtStartup(bool enabled);

// Records statistics for the number of used, disused and country-less address
// profiles. This is called each time a new chrome profile is launched.
static void LogStoredProfileCountStatistics(size_t num_profiles,
size_t num_disused_profiles,
size_t num_countryless_profiles);
// Maps the `profile` to its category, depending on the profile's `source()`
// and `initial_creator()`.
static AutofillProfileSourceCategory GetCategoryOfProfile(
const AutofillProfile& profile);

// Converts the `category` to the histogram-suffix used for resolving some
// metrics by category.
static const char* GetProfileCategorySuffix(
AutofillProfileSourceCategory category);

// The data logged for the stored profiles metric. This is counted separately
// for each `AutofillProfileCategory`.
struct StoredProfileCounts {
// Total number of stored profiles of the corresponding category.
size_t total = 0;
// The subset of profiles that hasn't been used in a fixed period of time.
size_t disused = 0;
// The subset of profiles that doesn't have a country stored.
size_t without_country = 0;
};
// Records statistics for the number of used, disused, and potentially,
// depending on the `category`, country-less address profiles.
// This metric is emitted each time a new Chrome profile is started. It is
// tracked separately for each `category`.
static void LogStoredProfileCountStatistics(
AutofillProfileSourceCategory category,
const StoredProfileCounts& counts);

// Records the number of days since an address profile was last used. This is
// called once per address profile each time a new chrome profile is launched.
static void LogStoredProfileDaysSinceLastUse(size_t days);
// logged separately for each profile of every `category`, each time a new
// Chrome profile is launched.
static void LogStoredProfileDaysSinceLastUse(
AutofillProfileSourceCategory category,
size_t days);

// Logs various metrics about the local and server cards associated with a
// profile. This should be called each time a new chrome profile is launched.
Expand Down
53 changes: 30 additions & 23 deletions components/autofill/core/browser/personal_data_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2075,32 +2075,39 @@ std::string PersonalDataManager::SaveImportedIBAN(IBAN& imported_iban) {

void PersonalDataManager::LogStoredProfileMetrics() const {
if (!has_logged_stored_profile_metrics_) {
// Track the number of disused profiles and profiles without country
// information.
size_t num_disused_profiles = 0;
size_t num_profiles_without_country = 0;

// Determine the number of disused and country-less profiles
const base::Time now = AutofillClock::Now();
// TODO(crbug.com/1348294): Create a separate metric for `kAccount`
// profiles.
const std::vector<AutofillProfile*> local_profiles =
GetProfilesFromSource(AutofillProfile::Source::kLocalOrSyncable);
for (const AutofillProfile* profile : local_profiles) {
const base::TimeDelta time_since_last_use = now - profile->use_date();
AutofillMetrics::LogStoredProfileDaysSinceLastUse(
time_since_last_use.InDays());
if (time_since_last_use > kDisusedDataModelTimeDelta)
++num_disused_profiles;
if (profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty())
++num_profiles_without_country;
// Counts stored profile metrics for all profile of the given `category` and
// emits UMA metrics for them.
auto count_and_log =
[&](AutofillMetrics::AutofillProfileSourceCategory category) {
AutofillMetrics::StoredProfileCounts counts;
for (const AutofillProfile* profile : GetProfiles()) {
if (category != AutofillMetrics::GetCategoryOfProfile(*profile)) {
continue;
}
const base::TimeDelta time_since_last_use =
now - profile->use_date();
AutofillMetrics::LogStoredProfileDaysSinceLastUse(
category, time_since_last_use.InDays());
counts.total++;
counts.disused += time_since_last_use > kDisusedDataModelTimeDelta;
counts.without_country += profile->HasRawInfo(ADDRESS_HOME_COUNTRY);
}
AutofillMetrics::LogStoredProfileCountStatistics(category, counts);
};

count_and_log(
AutofillMetrics::AutofillProfileSourceCategory::kLocalOrSyncable);
// These metrics are only relevant when kAccount profiles are loaded.
if (base::FeatureList::IsEnabled(
features::kAutofillAccountProfilesUnionView)) {
count_and_log(
AutofillMetrics::AutofillProfileSourceCategory::kAccountChrome);
count_and_log(
AutofillMetrics::AutofillProfileSourceCategory::kAccountNonChrome);
}

AutofillMetrics::LogStoredProfileCountStatistics(
local_profiles.size(), num_disused_profiles,
num_profiles_without_country);

// Only log this info once per chrome user profile load.
// Only log this info once per Chrome user profile load.
has_logged_stored_profile_metrics_ = true;
}
}
Expand Down

0 comments on commit 0d09e66

Please sign in to comment.