blob: b8fcd6342ece17f16f80bf4cedf0ae9215f57663 [file] [log] [blame]
// Copyright 2014 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cryptohome/cryptohome_metrics.h"
#include <iterator>
#include <string>
#include <utility>
#include <base/logging.h>
#include <base/strings/strcat.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>
#include <metrics/metrics_library.h>
#include <metrics/timer.h>
#include "cryptohome/auth_blocks/auth_block_type.h"
namespace cryptohome {
namespace {
struct TimerHistogramParams {
TimerType timer_type;
const char* metric_name;
int min_sample;
int max_sample;
int num_buckets;
};
constexpr char kCryptohomeErrorHistogram[] = "Cryptohome.Errors";
constexpr char kCredentialRevocationResultHistogram[] =
"Cryptohome.%s.CredentialRevocationResult";
constexpr char kCryptohomeDeletedUserProfilesHistogram[] =
"Cryptohome.DeletedUserProfiles";
constexpr char kCryptohomeGCacheFreedDiskSpaceInMbHistogram[] =
"Cryptohome.GCache.FreedDiskSpaceInMb";
constexpr char kCryptohomeCacheVaultFreedDiskSpaceInMbHistogram[] =
"Cryptohome.FreedCacheVaultDiskSpaceInMb";
constexpr char kCryptohomeDaemonStoreCacheFreedDiskSpaceInMbHistogram[] =
"Cryptohome.FreedDaemonStoreCacheDiskSpaceInMb";
constexpr char
kCryptohomeDaemonStoreCacheMountedUsersFreedDiskSpaceInMbHistogram[] =
"Cryptohome.FreedDaemonStoreCacheMountedUsersDiskSpaceInMb";
constexpr char kCryptohomeFreeDiskSpaceTotalTimeHistogram[] =
"Cryptohome.FreeDiskSpaceTotalTime2";
constexpr char kCryptohomeLoginDiskCleanupTotalTime[] =
"Cryptohome.LoginDiskCleanupTotalTime";
constexpr char kCryptohomeFreeDiskSpaceTotalFreedInMbHistogram[] =
"Cryptohome.FreeDiskSpaceTotalFreedInMb";
constexpr char kCryptohomeFreeDiskSpaceDuringLoginTotalFreedInMbHistogram[] =
"Cryptohome.FreeDiskSpaceDuringLoginTotalFreedInMb";
constexpr char kCryptohomeTimeBetweenFreeDiskSpaceHistogram[] =
"Cryptohome.TimeBetweenFreeDiskSpace";
constexpr char kCryptohomeDiskCleanupProgressHistogram[] =
"Cryptohome.DiskCleanupProgress";
constexpr char kCryptohomeDiskCleanupResultHistogram[] =
"Cryptohome.DiskCleanupResult";
constexpr char kCryptohomeLoginDiskCleanupProgressHistogram[] =
"Cryptohome.LoginDiskCleanupProgress";
constexpr char kCryptohomeLoginDiskCleanupResultHistogram[] =
"Cryptohome.LoginDiskCleanupResult";
constexpr char kCryptohomeLoginDiskCleanupAvailableSpaceHistogram[] =
"Cryptohome.LoginDiskCleanupAvailableSpace";
constexpr char kCryptohomeLEResultHistogramPrefix[] = "Cryptohome.LECredential";
constexpr char kCryptohomeLESyncOutcomeHistogramSuffix[] = ".SyncOutcome";
constexpr char kCryptohomeLELogReplyEntryCountHistogram[] =
"Cryptohome.LECredential.LogReplayEntryCount";
constexpr char kHomedirEncryptionTypeHistogram[] =
"Cryptohome.HomedirEncryptionType";
constexpr char kOOPMountOperationResultHistogram[] =
"Cryptohome.OOPMountOperationResult";
constexpr char kOOPMountCleanupResultHistogram[] =
"Cryptohome.OOPMountCleanupResult";
constexpr char kRecoveryPrepareForRemovalResultHistogram[] =
"Cryptohome.%s.PrepareForRemovalResult";
constexpr char kRestoreSELinuxContextResultForHome[] =
"Cryptohome.RestoreSELinuxContextResultForHome";
constexpr char kRestoreSELinuxContextResultForShadow[] =
"Cryptohome.RestoreSELinuxContextResultForShadow";
constexpr char kCreateAuthBlockTypeHistogram[] =
"Cryptohome.CreateAuthBlockType";
constexpr char kDeriveAuthBlockTypeHistogram[] =
"Cryptohome.DeriveAuthBlockType";
constexpr char kSelectFactorAuthBlockTypeHistogram[] =
"Cryptohome.SelectFactorAuthBlockType";
constexpr char kLegacyCodePathUsageHistogramPrefix[] =
"Cryptohome.LegacyCodePathUsage";
constexpr char kVaultKeysetMetric[] = "Cryptohome.VaultKeysetMetric";
constexpr char kFetchUssExperimentConfigStatus[] =
"Cryptohome.UssExperiment.FetchUssExperimentConfigStatus";
constexpr char kFetchUssExperimentConfigRetries[] =
"Cryptohome.UssExperiment.FetchUssExperimentConfigRetries";
constexpr char kUssExperimentFlag[] =
"Cryptohome.UssExperiment.UssExperimentFlag";
constexpr char kAuthFactorBackingStoreConfig[] =
"Cryptohome.AuthFactorBackingStoreConfig";
constexpr char kVkToUssMigrationStatus[] = "Cryptohome.VkToUssMigrationStatus";
constexpr char kMaskedDownloadsItems[] = "Cryptohome.MaskedDownloadsItems";
constexpr char kDownloadsBindMountMigrationStatusHistogram[] =
"Cryptohome.DownloadsBindMountMigrationStatus";
constexpr char kBackupKeysetCleanupResult[] =
"Cryptohome.BackupKeysetCleanupResult";
constexpr char kFingerprintEnrollSignal[] =
"Cryptohome.Fingerprint.EnrollSignal";
constexpr char kFingerprintAuthSignal[] = "Cryptohome.Fingerprint.AuthSignal";
constexpr char kNumUserHomeDirectories[] =
"Platform.DiskUsage.NumUserHomeDirectories";
// Histogram parameters. This should match the order of 'TimerType'.
// Min and max samples are in milliseconds.
constexpr TimerHistogramParams kTimerHistogramParams[] = {
// A note on the PKCS#11 initialization time:
// Max sample for PKCS#11 initialization time is 100s; we are interested
// in recording the very first PKCS#11 initialization time, which may be a
// lengthy one. Subsequent initializations are fast (under 1s) because they
// just check if PKCS#11 was previously initialized, returning immediately.
// These will all fall into the first histogram bucket.
{kPkcs11InitTimer, "Cryptohome.TimeToInitPkcs11", 1000, 100000, 50},
{kMountExTimer, "Cryptohome.TimeToMountEx", 0, 40000, 150},
{kMountGuestExTimer, "Cryptohome.TimeToMountGuestEx", 0, 4000, 50},
// This is only being reported from the out-of-process helper so it's
// covered by the same 3-second timeout.
{kPerformEphemeralMountTimer, "Cryptohome.TimeToPerformEphemeralMount", 0,
3000, 50},
// Non-ephemeral mounts are currently mounted in-process but it makes sense
// to keep the same scale for them as ephemeral mounts.
{kPerformMountTimer, "Cryptohome.TimeToPerformMount", 0, 3000, 50},
// The time to generate the ECC auth value in TpmEccAuthBlock.
{kGenerateEccAuthValueTimer, "Cryptohome.TimeToGenerateEccAuthValue", 0,
5000, 50},
// The time for AuthSession to add an auth factor with VaultKeyset.
{kAuthSessionAddAuthFactorVKTimer,
"Cryptohome.TimeToAuthSessionAddAuthFactorVK", 0, 6000, 60},
// The time for AuthSession to add an auth factor with USS.
{kAuthSessionAddAuthFactorUSSTimer,
"Cryptohome.TimeToAuthSessionAddAuthFactorUSS", 0, 6000, 60},
// The time for AuthSession to authenticate an auth factor with VaultKeyset.
{kAuthSessionAuthenticateAuthFactorVKTimer,
"Cryptohome.TimeToAuthSessionAuthenticateAuthFactorVK", 0, 6000, 60},
// The time for AuthSession to authenticate an auth factor with USS.
{kAuthSessionAuthenticateAuthFactorUSSTimer,
"Cryptohome.TimeToAuthSessionAuthenticateAuthFactorUSS", 0, 6000, 60},
// TODO(b/236415538, thomascedeno) - Add metric once UpdateAuthFactor is
// implemented.
{kAuthSessionUpdateAuthFactorVKTimer,
"Cryptohome.TimeToAuthSessionUpdateAuthFactorVK", 0, 6000, 60},
{kAuthSessionUpdateAuthFactorUSSTimer,
"Cryptohome.TimeToAuthSessionUpdateAuthFactorUSS", 0, 6000, 60},
// TODO(b/236415640, thomascedeno) - Add metric once RemoveAuthFactor is
// implemented.
{kAuthSessionRemoveAuthFactorVKTimer,
"Cryptohome.TimeToAuthSessionRemoveAuthFactorVK", 0, 6000, 60},
{kAuthSessionRemoveAuthFactorUSSTimer,
"Cryptohome.TimeToAuthSessionRemoveAuthFactorUSS", 0, 6000, 60},
// Time for User Data Auth class to create a persistent user.
{kCreatePersistentUserTimer, "Cryptohome.TimeToCreatePersistentUser", 0,
6000, 60},
// Time for overall AuthSession lifetime, which
// has a default of 5 minutes but can be optionally extended.
{kAuthSessionTotalLifetimeTimer, "Cryptohome.AuthSessionTotalLifetime", 0,
3 * 5 * 60 * 1000, 60},
// Time AuthSession is alive after it is authenticated, does not
// include time AuthSession is initialized but unauthenticated.
{kAuthSessionAuthenticatedLifetimeTimer,
"Cryptohome.AuthSessionAuthenticatedLifetime", 0, 3 * 5 * 60 * 1000, 60},
// The time to Persist a User Secret Stash to system storage.
{kUSSPersistTimer, "Cryptohome.TimeToUSSPersist", 0, 5000, 50},
// The time to Load Persist a User Secret Stash from system storage.
{kUSSLoadPersistedTimer, "Cryptohome.TimeToUSSLoadPersisted", 0, 5000, 50},
// The time to migrate a VaultKeyset to UserSecretStash after authentication
// or update is completed.
{kUSSMigrationTimer, "Cryptohome.TimeToMigrateVaultKeysetToUss", 0, 6000,
60},
// The time take to set up the cryptohome vault for mounting.
{kVaultSetupTimer, "Cryptohome.TimeToSetupVault", 0, 10 * 1000, 50},
// The time taken to relabel the SELinux context of all files inside the
// user cryptohome.
{kSELinuxRelabelTimer, "Cryptohome.TimeToRelabelSELinuxContexts", 0,
60 * 1000, 60},
{kStoreUserPolicyTimer, "Cryptohome.TimeToStoreUserPolicyInFile", 0, 5000,
50},
{kLoadUserPolicyTimer, "Cryptohome.TimeToLoadUserPolicyFromFile", 0, 5000,
50},
// The time for AuthSession to replace an auth factor.
{kAuthSessionReplaceAuthFactorTimer,
"Cryptohome.TimeToAuthSessionReplaceAuthFactor", 0, 6000, 60},
};
static_assert(std::size(kTimerHistogramParams) == kNumTimerTypes,
"kTimerHistogramParams out of sync with enum TimerType");
constexpr bool TestTimerHistogramParams() {
for (int i = 0; i < std::size(kTimerHistogramParams); i++) {
if (static_cast<int>(kTimerHistogramParams[i].timer_type) != i) {
return false;
}
}
return true;
}
static_assert(TestTimerHistogramParams(), "TimerType value mapping mismatch");
// List of strings for a patterned histogram for legacy locations.
const char* kLegacyCodePathLocations[] = {".AddKeyResetSeedGeneration"};
static_assert(
std::size(kLegacyCodePathLocations) ==
static_cast<int>(LegacyCodePathLocation::kMaxValue) + 1,
"kLegacyCodePathLocations out of sync with enum LegacyCodePathLocation");
// Set to true to disable CryptohomeError related reporting, see
// DisableErrorMetricsReporting().
bool g_disable_error_metrics = false;
MetricsLibraryInterface* g_metrics = nullptr;
chromeos_metrics::TimerReporter* g_timers[kNumTimerTypes] = {nullptr};
chromeos_metrics::TimerReporter* GetTimer(TimerType timer_type) {
if (!g_timers[timer_type]) {
g_timers[timer_type] = new chromeos_metrics::TimerReporter(
kTimerHistogramParams[timer_type].metric_name,
kTimerHistogramParams[timer_type].min_sample,
kTimerHistogramParams[timer_type].max_sample,
kTimerHistogramParams[timer_type].num_buckets);
}
return g_timers[timer_type];
}
// These values are persisted to logs.
// Keep in sync with respective variant enum in
// tools/metrics/histograms/metadata/cryptohome/histograms.xml
char const* GetAuthBlockTypeStringVariant(AuthBlockType type) {
switch (type) {
case AuthBlockType::kPinWeaver:
return "PinWeaver";
case AuthBlockType::kChallengeCredential:
return "ChallengeCredential";
case AuthBlockType::kDoubleWrappedCompat:
return "DoubleWrappedCompat";
case AuthBlockType::kTpmBoundToPcr:
return "TpmBoundToPcr";
case AuthBlockType::kTpmNotBoundToPcr:
return "TpmNotBoundToPcr";
case AuthBlockType::kScrypt:
return "Scrypt";
case AuthBlockType::kCryptohomeRecovery:
return "CryptohomeRecovery";
case AuthBlockType::kTpmEcc:
return "TpmEcc";
case AuthBlockType::kFingerprint:
return "Fingerprint";
}
}
} // namespace
void InitializeMetrics() {
g_metrics = new MetricsLibrary();
chromeos_metrics::TimerReporter::set_metrics_lib(g_metrics);
}
void TearDownMetrics() {
if (g_metrics) {
chromeos_metrics::TimerReporter::set_metrics_lib(nullptr);
delete g_metrics;
g_metrics = nullptr;
}
for (auto& g_timer : g_timers) {
if (g_timer) {
delete g_timer;
}
}
}
void OverrideMetricsLibraryForTesting(MetricsLibraryInterface* lib) {
g_metrics = lib;
}
void ClearMetricsLibraryForTesting() {
g_metrics = nullptr;
}
void DisableErrorMetricsReporting() {
g_disable_error_metrics = true;
}
void ReportCryptohomeError(CryptohomeErrorMetric error) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kCryptohomeErrorHistogram, error,
kCryptohomeErrorNumBuckets);
}
void ReportCrosEvent(const char* event) {
if (!g_metrics) {
return;
}
g_metrics->SendCrosEventToUMA(event);
}
void ReportTimerStart(TimerType timer_type) {
if (!g_metrics) {
return;
}
chromeos_metrics::TimerReporter* timer = GetTimer(timer_type);
if (!timer) {
return;
}
timer->Start();
}
void ReportTimerStop(TimerType timer_type) {
if (!g_metrics) {
return;
}
chromeos_metrics::TimerReporter* timer = GetTimer(timer_type);
bool success = (timer && timer->HasStarted() && timer->Stop() &&
timer->ReportMilliseconds());
if (!success) {
LOG(WARNING) << "Timer " << kTimerHistogramParams[timer_type].metric_name
<< " failed to report.";
}
}
void ReportTimerDuration(
const AuthSessionPerformanceTimer* auth_session_performance_timer) {
if (!g_metrics) {
return;
}
// Check that timer_type is a valid timer.
TimerType timer_type = auth_session_performance_timer->type;
CHECK_LT(timer_type, kNumTimerTypes);
// Compute the name, parameterizing by AuthBlockType if needed.
std::string metric_name = kTimerHistogramParams[timer_type].metric_name;
if (auth_session_performance_timer->auth_block_type) {
base::StrAppend(
&metric_name,
{".", GetAuthBlockTypeStringVariant(
*auth_session_performance_timer->auth_block_type)});
}
auto duration =
base::TimeTicks::Now() - auth_session_performance_timer->start_time;
g_metrics->SendToUMA(metric_name, duration.InMilliseconds(),
kTimerHistogramParams[timer_type].min_sample,
kTimerHistogramParams[timer_type].max_sample,
kTimerHistogramParams[timer_type].num_buckets);
}
void ReportTimerDuration(const TimerType& timer_type,
base::TimeTicks start_time,
const std::string& parameter_string) {
if (!g_metrics) {
return;
}
// Check that timer_type is a valid timer.
CHECK_LT(timer_type, kNumTimerTypes);
std::string metric_name = kTimerHistogramParams[timer_type].metric_name;
metric_name.append(parameter_string);
auto duration = base::TimeTicks::Now() - start_time;
g_metrics->SendToUMA(metric_name, duration.InMilliseconds(),
kTimerHistogramParams[timer_type].min_sample,
kTimerHistogramParams[timer_type].max_sample,
kTimerHistogramParams[timer_type].num_buckets);
}
void ReportCredentialRevocationResult(AuthBlockType auth_block_type,
LECredError result) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
base::StringPrintf(kCredentialRevocationResultHistogram,
GetAuthBlockTypeStringVariant(auth_block_type)),
result, LE_CRED_ERROR_MAX);
}
void ReportFreedGCacheDiskSpaceInMb(int mb) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(kCryptohomeGCacheFreedDiskSpaceInMbHistogram, mb,
10 /* 10 MiB minimum */, 1024 * 10 /* 10 GiB maximum */,
50 /* number of buckets */);
}
void ReportFreedDaemonStoreCacheDiskSpaceInMb(int mb) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(kCryptohomeDaemonStoreCacheFreedDiskSpaceInMbHistogram,
mb, 10 /* 10 MiB minimum */,
1024 * 10 /* 10 GiB maximum */,
50 /* number of buckets */);
}
void ReportFreedDaemonStoreCacheMountedUsersDiskSpaceInMb(int mb) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(
kCryptohomeDaemonStoreCacheMountedUsersFreedDiskSpaceInMbHistogram, mb,
10 /* 10 MiB minimum */, 1024 * 10 /* 10 GiB maximum */,
50 /* number of buckets */);
}
void ReportFreedCacheVaultDiskSpaceInMb(int mb) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(kCryptohomeCacheVaultFreedDiskSpaceInMbHistogram, mb,
10 /* 10 MiB minimum */, 1024 * 10 /* 10 GiB maximum */,
50 /* number of buckets */);
}
void ReportDeletedUserProfiles(int user_profile_count) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(kCryptohomeDeletedUserProfilesHistogram,
user_profile_count, 1 /* minimum */, 100 /* maximum */,
20 /* number of buckets */);
}
void ReportFreeDiskSpaceTotalTime(int ms) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(kCryptohomeFreeDiskSpaceTotalTimeHistogram, ms, 1,
60 * 1000, 50);
}
void ReportFreeDiskSpaceTotalFreedInMb(int mb) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 1024 * 10, /* 10 GiB maximum */
kNumBuckets = 50;
g_metrics->SendToUMA(kCryptohomeFreeDiskSpaceTotalFreedInMbHistogram, mb,
kMin, kMax, kNumBuckets);
}
void ReportTimeBetweenFreeDiskSpace(int s) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 86400, /* seconds in a day */
kNumBuckets = 50;
g_metrics->SendToUMA(kCryptohomeTimeBetweenFreeDiskSpaceHistogram, s, kMin,
kMax, kNumBuckets);
}
void ReportLoginDiskCleanupTotalTime(int ms) {
if (!g_metrics) {
return;
}
g_metrics->SendToUMA(kCryptohomeLoginDiskCleanupTotalTime, ms, 1, 60 * 1000,
50);
}
void ReportFreeDiskSpaceDuringLoginTotalFreedInMb(int mb) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 1024 * 10, /* 10 GiB maximum */
kNumBuckets = 50;
g_metrics->SendToUMA(
kCryptohomeFreeDiskSpaceDuringLoginTotalFreedInMbHistogram, mb, kMin,
kMax, kNumBuckets);
}
void ReportDiskCleanupProgress(DiskCleanupProgress progress) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kCryptohomeDiskCleanupProgressHistogram,
static_cast<int>(progress),
static_cast<int>(DiskCleanupProgress::kNumBuckets));
}
void ReportDiskCleanupResult(DiskCleanupResult result) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kCryptohomeDiskCleanupResultHistogram,
static_cast<int>(result),
static_cast<int>(DiskCleanupResult::kNumBuckets));
}
void ReportLoginDiskCleanupProgress(LoginDiskCleanupProgress progress) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kCryptohomeLoginDiskCleanupProgressHistogram, static_cast<int>(progress),
static_cast<int>(LoginDiskCleanupProgress::kNumBuckets));
}
void ReportLoginDiskCleanupResult(DiskCleanupResult result) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kCryptohomeLoginDiskCleanupResultHistogram,
static_cast<int>(result),
static_cast<int>(DiskCleanupResult::kNumBuckets));
}
void ReportLoginDiskCleanupAvailableSpace(int64_t space) {
if (!g_metrics) {
return;
}
constexpr int kMin = 0, kMax = 10000, kNumBuckets = 50;
g_metrics->SendToUMA(kCryptohomeLoginDiskCleanupAvailableSpaceHistogram,
space, kMin, kMax, kNumBuckets);
}
void ReportNumUserHomeDirectories(int num_users) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 50, kNumBuckets = 50;
g_metrics->SendToUMA(kNumUserHomeDirectories, num_users, kMin, kMax,
kNumBuckets);
}
void ReportHomedirEncryptionType(HomedirEncryptionType type) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kHomedirEncryptionTypeHistogram, static_cast<int>(type),
static_cast<int>(
HomedirEncryptionType::kHomedirEncryptionTypeNumBuckets));
}
void ReportLEResult(const char* type, const char* action, LECredError result) {
if (!g_metrics) {
return;
}
std::string hist_str = std::string(kCryptohomeLEResultHistogramPrefix)
.append(type)
.append(action);
g_metrics->SendEnumToUMA(hist_str, result, LE_CRED_ERROR_MAX);
}
void ReportLESyncOutcome(LECredError result) {
if (!g_metrics) {
return;
}
std::string hist_str = std::string(kCryptohomeLEResultHistogramPrefix)
.append(kCryptohomeLESyncOutcomeHistogramSuffix);
g_metrics->SendEnumToUMA(hist_str, result, LE_CRED_ERROR_MAX);
}
void ReportLELogReplayEntryCount(size_t entry_count) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 32, kNumBuckets = 33;
g_metrics->SendToUMA(kCryptohomeLELogReplyEntryCountHistogram,
static_cast<int>(entry_count), kMin, kMax, kNumBuckets);
}
void ReportLEReplayResult(bool is_full_replay, LEReplayError result) {
if (!g_metrics) {
return;
}
const char* replay_type =
is_full_replay ? kLEReplayTypeFull : kLEReplayTypeNormal;
std::string hist_str = std::string(kCryptohomeLEResultHistogramPrefix)
.append(kLEOpReplay)
.append(replay_type);
g_metrics->SendEnumToUMA(hist_str, static_cast<int>(result),
static_cast<int>(LEReplayError::kMaxValue));
}
void ReportOOPMountOperationResult(OOPMountOperationResult result) {
if (!g_metrics) {
return;
}
constexpr auto max_event =
static_cast<int>(OOPMountOperationResult::kMaxValue);
g_metrics->SendEnumToUMA(kOOPMountOperationResultHistogram,
static_cast<int>(result),
static_cast<int>(max_event));
}
void ReportOOPMountCleanupResult(OOPMountCleanupResult result) {
if (!g_metrics) {
return;
}
constexpr auto max_event = static_cast<int>(OOPMountCleanupResult::kMaxValue);
g_metrics->SendEnumToUMA(kOOPMountCleanupResultHistogram,
static_cast<int>(result),
static_cast<int>(max_event));
}
void ReportPrepareForRemovalResult(AuthBlockType auth_block_type,
CryptoError result) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
base::StringPrintf(kRecoveryPrepareForRemovalResultHistogram,
GetAuthBlockTypeStringVariant(auth_block_type)),
static_cast<int>(result), static_cast<int>(CryptoError::CE_MAX_VALUE));
}
void ReportRestoreSELinuxContextResultForHomeDir(bool success) {
if (!g_metrics) {
return;
}
g_metrics->SendBoolToUMA(kRestoreSELinuxContextResultForHome, success);
}
void ReportRestoreSELinuxContextResultForShadowDir(bool success) {
if (!g_metrics) {
return;
}
g_metrics->SendBoolToUMA(kRestoreSELinuxContextResultForShadow, success);
}
void ReportCreateAuthBlock(AuthBlockType type) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kCreateAuthBlockTypeHistogram,
static_cast<int>(type),
static_cast<int>(kAuthBlockTypeMaxValue) + 1);
}
void ReportDeriveAuthBlock(AuthBlockType type) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kDeriveAuthBlockTypeHistogram,
static_cast<int>(type),
static_cast<int>(kAuthBlockTypeMaxValue) + 1);
}
void ReportSelectFactorAuthBlock(AuthBlockType type) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kSelectFactorAuthBlockTypeHistogram,
static_cast<int>(type),
static_cast<int>(kAuthBlockTypeMaxValue) + 1);
}
void ReportUsageOfLegacyCodePath(const LegacyCodePathLocation location,
bool result) {
if (!g_metrics) {
return;
}
std::string hist_str =
std::string(kLegacyCodePathUsageHistogramPrefix)
.append(kLegacyCodePathLocations[static_cast<int>(location)]);
g_metrics->SendBoolToUMA(hist_str, result);
}
void ReportVaultKeysetMetrics(const VaultKeysetMetrics& keyset_metrics) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 99, kNumBuckets = 100;
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".MissingKeyDataCount"),
keyset_metrics.missing_key_data_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".EmptyLabelCount"),
keyset_metrics.empty_label_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".EmptyLabelPINCount"),
keyset_metrics.empty_label_le_cred_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(std::string(kVaultKeysetMetric).append(".PINCount"),
keyset_metrics.le_cred_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".UntypedKeysetCount"),
keyset_metrics.untyped_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".SmartUnlockCount"),
keyset_metrics.smart_unlock_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(std::string(kVaultKeysetMetric).append(".PasswordCount"),
keyset_metrics.password_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".SmartCardCount"),
keyset_metrics.smartcard_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".FingerprintCount"),
keyset_metrics.fingerprint_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(std::string(kVaultKeysetMetric).append(".KioskCount"),
keyset_metrics.kiosk_count, kMin, kMax, kNumBuckets);
g_metrics->SendToUMA(
std::string(kVaultKeysetMetric).append(".UnclassifedKeysetCount"),
keyset_metrics.unclassified_count, kMin, kMax, kNumBuckets);
}
void ReportMaskedDownloadsItems(int num_items) {
if (!g_metrics) {
return;
}
constexpr int kMin = 1, kMax = 1000, kNumBuckets = 20;
g_metrics->SendToUMA(kMaskedDownloadsItems, num_items, kMin, kMax,
kNumBuckets);
}
void ReportDownloadsBindMountMigrationStatus(
DownloadsBindMountMigrationStatus status) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kDownloadsBindMountMigrationStatusHistogram, static_cast<int>(status),
static_cast<int>(DownloadsBindMountMigrationStatus::kMaxValue));
}
void ReportCryptohomeErrorHashedStack(std::string error_bucket_name,
const uint32_t hashed) {
if (!g_metrics || g_disable_error_metrics) {
return;
}
std::string name =
base::JoinString({kCryptohomeErrorPrefix, std::move(error_bucket_name),
kCryptohomeErrorHashedStackSuffix},
".");
g_metrics->SendSparseToUMA(name, static_cast<int>(hashed));
}
void ReportCryptohomeErrorLeafWithTPM(std::string error_bucket_name,
const uint32_t mixed) {
if (!g_metrics || g_disable_error_metrics) {
return;
}
std::string name =
base::JoinString({kCryptohomeErrorPrefix, std::move(error_bucket_name),
kCryptohomeErrorLeafWithTPMSuffix},
".");
g_metrics->SendSparseToUMA(name, static_cast<int>(mixed));
}
void ReportCryptohomeErrorDevCheckUnexpectedState(std::string error_bucket_name,
const uint32_t loc) {
if (!g_metrics || g_disable_error_metrics) {
return;
}
std::string name =
base::JoinString({kCryptohomeErrorPrefix, std::move(error_bucket_name),
kCryptohomeErrorDevCheckUnexpectedStateSuffix},
".");
g_metrics->SendSparseToUMA(name, static_cast<int>(loc));
}
void ReportCryptohomeErrorAllLocations(std::string error_bucket_name,
const uint32_t loc) {
if (!g_metrics || g_disable_error_metrics) {
return;
}
std::string name =
base::JoinString({kCryptohomeErrorPrefix, std::move(error_bucket_name),
kCryptohomeErrorAllLocationsSuffix},
".");
g_metrics->SendSparseToUMA(name, static_cast<int>(loc));
}
void ReportFetchUssExperimentConfigStatus(
FetchUssExperimentConfigStatus status) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kFetchUssExperimentConfigStatus, static_cast<int>(status),
static_cast<int>(FetchUssExperimentConfigStatus::kMaxValue));
}
void ReportFetchUssExperimentConfigRetries(int retries) {
constexpr int kMin = 0, kMax = 9, kNumBuckets = 10;
g_metrics->SendToUMA(kFetchUssExperimentConfigRetries, retries, kMin, kMax,
kNumBuckets);
}
void ReportUssExperimentFlag(UssExperimentFlag flag) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kUssExperimentFlag, static_cast<int>(flag),
static_cast<int>(UssExperimentFlag::kMaxValue));
}
void ReportAuthFactorBackingStoreConfig(AuthFactorBackingStoreConfig config) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kAuthFactorBackingStoreConfig, static_cast<int>(config),
static_cast<int>(AuthFactorBackingStoreConfig::kMaxValue) + 1);
}
void ReportVkToUssMigrationStatus(VkToUssMigrationStatus status) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kVkToUssMigrationStatus, static_cast<int>(status),
static_cast<int>(VkToUssMigrationStatus::kMaxValue) + 1);
}
void ReportBackupKeysetCleanupSucessWithType(AuthFactorType auth_factor_type) {
if (auth_factor_type == AuthFactorType::kPassword) {
ReportBackupKeysetCleanupResult(
BackupKeysetCleanupResult::kRemovedBackupPassword);
return;
}
if (auth_factor_type == AuthFactorType::kPin) {
ReportBackupKeysetCleanupResult(
BackupKeysetCleanupResult::kRemovedBackupPin);
return;
}
ReportBackupKeysetCleanupResult(
BackupKeysetCleanupResult::kRemovedBackupOtherType);
}
void ReportBackupKeysetCleanupFileFailureWithType(
AuthFactorType auth_factor_type) {
if (auth_factor_type == AuthFactorType::kPassword) {
ReportBackupKeysetCleanupResult(
BackupKeysetCleanupResult::kRemoveFileFailedPassword);
return;
}
if (auth_factor_type == AuthFactorType::kPin) {
ReportBackupKeysetCleanupResult(
BackupKeysetCleanupResult::kRemoveFileFailedPin);
return;
}
ReportBackupKeysetCleanupResult(
BackupKeysetCleanupResult::kRemoveFileFailedOtherType);
}
void ReportBackupKeysetCleanupResult(BackupKeysetCleanupResult status) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(
kBackupKeysetCleanupResult, static_cast<int>(status),
static_cast<int>(BackupKeysetCleanupResult::kMaxValue) + 1);
}
void ReportFingerprintEnrollSignal(
user_data_auth::FingerprintScanResult scan_result) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kFingerprintEnrollSignal,
static_cast<int>(scan_result),
user_data_auth::FingerprintScanResult_ARRAYSIZE);
}
void ReportFingerprintAuthSignal(
user_data_auth::FingerprintScanResult scan_result) {
if (!g_metrics) {
return;
}
g_metrics->SendEnumToUMA(kFingerprintAuthSignal,
static_cast<int>(scan_result),
user_data_auth::FingerprintScanResult_ARRAYSIZE);
}
} // namespace cryptohome