#include "components/metrics/metrics_service.h"
#include <stddef.h>
#include <algorithm>
#include <memory>
#include <string_view>
#include <utility>
#include "base/callback_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_flattener.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/histogram_macros_local.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/persistent_histogram_allocator.h"
#include "base/metrics/statistics_recorder.h"
#include "base/metrics/user_metrics.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/environment_recorder.h"
#include "components/metrics/field_trials_provider.h"
#include "components/metrics/metrics_features.h"
#include "components/metrics/metrics_log.h"
#include "components/metrics/metrics_log_uploader.h"
#include "components/metrics/metrics_logs_event_manager.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_rotation_scheduler.h"
#include "components/metrics/metrics_service_client.h"
#include "components/metrics/metrics_service_observer.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/metrics/metrics_switches.h"
#include "components/metrics/persistent_system_profile.h"
#include "components/metrics/stability_metrics_provider.h"
#include "components/metrics/url_constants.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/variations/entropy_provider.h"
#if !BUILDFLAG(IS_ANDROID)
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#endif
namespace metrics {
namespace {
class IndependentFlattener : public base::HistogramFlattener { … };
class DiscardingFlattener : public base::HistogramFlattener { … };
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
class ScopedTerminationChecker {
public:
enum class Status {
kStarted = 0,
kFinished = 1,
kMaxValue = kFinished,
};
explicit ScopedTerminationChecker(std::string_view histogram_name) {
if (!base::GlobalHistogramAllocator::Get()) {
return;
}
active_ = true;
histogram_name_ = histogram_name;
base::UmaHistogramEnumeration(histogram_name_, Status::kStarted);
}
ScopedTerminationChecker(const ScopedTerminationChecker& other) = delete;
ScopedTerminationChecker& operator=(const ScopedTerminationChecker& other) =
delete;
~ScopedTerminationChecker() {
if (!active_) {
return;
}
base::UmaHistogramEnumeration(histogram_name_, Status::kFinished);
}
private:
std::string histogram_name_;
bool active_ = false;
};
#endif
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
const int kInitializationDelaySeconds = 5;
#else
const int kInitializationDelaySeconds = …;
#endif
const int kUpdateAliveTimestampSeconds = …;
#if BUILDFLAG(IS_CHROMEOS_ASH)
enum UserLogStoreState {
kSetPostSendLogsState = 0,
kSetPreSendLogsState = 1,
kUnsetPostSendLogsState = 2,
kUnsetPreSendLogsState = 3,
kMaxValue = kUnsetPreSendLogsState,
};
void RecordUserLogStoreState(UserLogStoreState state) {
base::UmaHistogramEnumeration("UMA.CrosPerUser.UserLogStoreState", state);
}
#endif
}
void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) { … }
MetricsService::MetricsService(MetricsStateManager* state_manager,
MetricsServiceClient* client,
PrefService* local_state)
: … { … }
MetricsService::~MetricsService() { … }
void MetricsService::InitializeMetricsRecordingState() { … }
void MetricsService::Start() { … }
void MetricsService::StartRecordingForTests() { … }
void MetricsService::StartUpdatingLastLiveTimestamp() { … }
void MetricsService::Stop() { … }
void MetricsService::EnableReporting() { … }
void MetricsService::DisableReporting() { … }
std::string MetricsService::GetClientId() const { … }
int MetricsService::GetLowEntropySource() { … }
int MetricsService::GetOldLowEntropySource() { … }
int MetricsService::GetPseudoLowEntropySource() { … }
void MetricsService::SetExternalClientId(const std::string& id) { … }
bool MetricsService::WasLastShutdownClean() const { … }
void MetricsService::EnableRecording() { … }
void MetricsService::DisableRecording() { … }
bool MetricsService::recording_active() const { … }
bool MetricsService::reporting_active() const { … }
bool MetricsService::has_unsent_logs() const { … }
bool MetricsService::IsMetricsReportingEnabled() const { … }
void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { … }
void MetricsService::OnApplicationNotIdle() { … }
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
is_in_foreground_ = false;
reporting_service_.SetIsInForegound(false);
if (!keep_recording_in_background) {
rotation_scheduler_->Stop();
reporting_service_.Stop();
}
state_manager_->LogHasSessionShutdownCleanly(true);
local_state_->CommitPendingWrite();
delegating_provider_.OnAppEnterBackground();
if (recording_active() && !IsTooEarlyToCloseLog()) {
base::UmaHistogramBoolean(
"UMA.MetricsService.PendingOngoingLogOnBackgrounded",
pending_ongoing_log_);
#if BUILDFLAG(IS_ANDROID)
client_->MergeSubprocessHistograms();
#endif
{
ScopedTerminationChecker scoped_termination_checker(
"UMA.MetricsService.OnBackgroundedScopedTerminationChecker");
PushPendingLogsToPersistentStorage(
MetricsLogsEventManager::CreateReason::kBackgrounded);
}
OpenNewLog();
}
}
void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
is_in_foreground_ = true;
reporting_service_.SetIsInForegound(true);
state_manager_->LogHasSessionShutdownCleanly(false);
StartSchedulerIfNecessary();
if (force_open_new_log && recording_active() && !IsTooEarlyToCloseLog()) {
base::UmaHistogramBoolean(
"UMA.MetricsService.PendingOngoingLogOnForegrounded",
pending_ongoing_log_);
#if BUILDFLAG(IS_ANDROID)
client_->MergeSubprocessHistograms();
#endif
PushPendingLogsToPersistentStorage(
MetricsLogsEventManager::CreateReason::kForegrounded);
OpenNewLog();
}
}
#endif
void MetricsService::OnPageLoadStarted() { … }
void MetricsService::LogCleanShutdown() { … }
void MetricsService::ClearSavedStabilityMetrics() { … }
void MetricsService::MarkCurrentHistogramsAsReported() { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void MetricsService::SetUserLogStore(
std::unique_ptr<UnsentLogStore> user_log_store) {
if (log_store()->has_alternate_ongoing_log_store())
return;
if (state_ >= SENDING_LOGS) {
PushPendingLogsToPersistentStorage(
MetricsLogsEventManager::CreateReason::kAlternateOngoingLogStoreSet);
log_store()->SetAlternateOngoingLogStore(std::move(user_log_store));
OpenNewLog();
RecordUserLogStoreState(kSetPostSendLogsState);
} else {
log_store()->SetAlternateOngoingLogStore(std::move(user_log_store));
RecordUserLogStoreState(kSetPreSendLogsState);
}
}
void MetricsService::UnsetUserLogStore() {
if (!log_store()->has_alternate_ongoing_log_store()) {
return;
}
if (state_ >= SENDING_LOGS) {
PushPendingLogsToPersistentStorage(
MetricsLogsEventManager::CreateReason::kAlternateOngoingLogStoreUnset);
log_store()->UnsetAlternateOngoingLogStore();
OpenNewLog();
RecordUserLogStoreState(kUnsetPostSendLogsState);
return;
}
DiscardingFlattener flattener;
base::HistogramSnapshotManager histogram_snapshot_manager(&flattener);
delegating_provider_.RecordHistogramSnapshots(&histogram_snapshot_manager);
base::StatisticsRecorder::PrepareDeltas(
true, base::Histogram::kNoFlags,
base::Histogram::kUmaTargetedHistogramFlag,
&histogram_snapshot_manager);
CHECK(current_log_);
current_log_.reset();
DisableRecording();
log_store()->UnsetAlternateOngoingLogStore();
RecordUserLogStoreState(kUnsetPreSendLogsState);
}
bool MetricsService::HasUserLogStore() {
return log_store()->has_alternate_ongoing_log_store();
}
void MetricsService::InitPerUserMetrics() {
client_->InitPerUserMetrics();
}
std::optional<bool> MetricsService::GetCurrentUserMetricsConsent() const {
return client_->GetCurrentUserMetricsConsent();
}
std::optional<std::string> MetricsService::GetCurrentUserId() const {
return client_->GetCurrentUserId();
}
void MetricsService::UpdateCurrentUserMetricsConsent(
bool user_metrics_consent) {
client_->UpdateCurrentUserMetricsConsent(user_metrics_consent);
}
#endif
#if BUILDFLAG(IS_CHROMEOS)
void MetricsService::ResetClientId() {
local_state_->ClearPref(prefs::kMetricsClientID);
local_state_->ClearPref(prefs::kMetricsLogFinalizedRecordId);
local_state_->ClearPref(prefs::kMetricsLogRecordId);
state_manager_->ForceClientIdCreation();
client_->SetMetricsClientId(state_manager_->client_id());
}
#endif
variations::SyntheticTrialRegistry*
MetricsService::GetSyntheticTrialRegistry() { … }
base::TimeDelta MetricsService::GetInitializationDelay() { … }
base::TimeDelta MetricsService::GetUpdateLastAliveTimestampDelay() { … }
bool MetricsService::StageCurrentLogForTest() { … }
void MetricsService::InitializeMetricsState() { … }
void MetricsService::OnUserAction(const std::string& action,
base::TimeTicks action_time) { … }
void MetricsService::FinishedInitTask() { … }
void MetricsService::GetUptimes(PrefService* pref,
base::TimeDelta* incremental_uptime,
base::TimeDelta* uptime) { … }
void MetricsService::OpenNewLog(bool call_providers) { … }
MetricsService::FinalizedLog::FinalizedLog() = default;
MetricsService::FinalizedLog::~FinalizedLog() = default;
MetricsService::FinalizedLog::FinalizedLog(FinalizedLog&& other) = default;
MetricsService::FinalizedLog& MetricsService::FinalizedLog::operator=(
FinalizedLog&& other) = default;
MetricsService::MetricsLogHistogramWriter::MetricsLogHistogramWriter(
MetricsLog* log)
: … { … }
MetricsService::MetricsLogHistogramWriter::MetricsLogHistogramWriter(
MetricsLog* log,
base::HistogramBase::Flags required_flags)
: … { … }
MetricsService::MetricsLogHistogramWriter::~MetricsLogHistogramWriter() =
default;
void MetricsService::MetricsLogHistogramWriter::
SnapshotStatisticsRecorderDeltas() { … }
void MetricsService::MetricsLogHistogramWriter::
SnapshotStatisticsRecorderUnloggedSamples() { … }
void MetricsService::MetricsLogHistogramWriter::NotifyLogBeingFinalized() { … }
MetricsService::IndependentMetricsLoader::IndependentMetricsLoader(
std::unique_ptr<MetricsLog> log,
std::string app_version,
std::string signing_key)
: … { … }
MetricsService::IndependentMetricsLoader::~IndependentMetricsLoader() = default;
void MetricsService::IndependentMetricsLoader::Run(
base::OnceCallback<void(bool)> done_callback,
MetricsProvider* metrics_provider) { … }
void MetricsService::IndependentMetricsLoader::FinalizeLog() { … }
bool MetricsService::IndependentMetricsLoader::HasFinalizedLog() { … }
MetricsService::FinalizedLog
MetricsService::IndependentMetricsLoader::ReleaseFinalizedLog() { … }
void MetricsService::StartInitTask() { … }
void MetricsService::CloseCurrentLog(
bool async,
MetricsLogsEventManager::CreateReason reason,
base::OnceClosure log_stored_callback) { … }
void MetricsService::StoreFinalizedLog(
MetricsLog::LogType log_type,
MetricsLogsEventManager::CreateReason reason,
base::OnceClosure done_callback,
FinalizedLog finalized_log) { … }
void MetricsService::MaybeCleanUpAndStoreFinalizedLog(
std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
MetricsLog::LogType log_type,
MetricsLogsEventManager::CreateReason reason,
base::OnceClosure done_callback,
FinalizedLog finalized_log) { … }
void MetricsService::PushPendingLogsToPersistentStorage(
MetricsLogsEventManager::CreateReason reason) { … }
void MetricsService::StartSchedulerIfNecessary() { … }
void MetricsService::StartScheduledUpload() { … }
void MetricsService::OnFinalLogInfoCollectionDone() { … }
void MetricsService::OnAsyncPeriodicOngoingLogStored() { … }
bool MetricsService::PrepareInitialStabilityLog(
const std::string& prefs_previous_version) { … }
void MetricsService::RegisterMetricsProvider(
std::unique_ptr<MetricsProvider> provider) { … }
void MetricsService::CheckForClonedInstall() { … }
bool MetricsService::ShouldResetClientIdsOnClonedInstall() { … }
std::unique_ptr<MetricsLog> MetricsService::CreateLog(
MetricsLog::LogType log_type) { … }
void MetricsService::AddLogsObserver(
MetricsLogsEventManager::Observer* observer) { … }
void MetricsService::RemoveLogsObserver(
MetricsLogsEventManager::Observer* observer) { … }
base::CallbackListSubscription MetricsService::AddEnablementObserver(
const base::RepeatingCallback<void(bool)>& observer) { … }
void MetricsService::SetPersistentSystemProfile(
const std::string& serialized_proto,
bool complete) { … }
std::string MetricsService::RecordCurrentEnvironmentHelper(
MetricsLog* log,
PrefService* local_state,
DelegatingProvider* delegating_provider) { … }
void MetricsService::RecordCurrentEnvironment(MetricsLog* log, bool complete) { … }
void MetricsService::PrepareProviderMetricsLogDone(
std::unique_ptr<IndependentMetricsLoader> loader,
bool success) { … }
bool MetricsService::PrepareProviderMetricsLog() { … }
void MetricsService::PrepareProviderMetricsTask() { … }
void MetricsService::UpdateLastLiveTimestampTask() { … }
bool MetricsService::IsTooEarlyToCloseLog() { … }
void MetricsService::OnClonedInstallDetected() { … }
MetricsService::FinalizedLog MetricsService::SnapshotDeltasAndFinalizeLog(
std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
std::unique_ptr<MetricsLog> log,
bool truncate_events,
std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
std::string&& current_app_version,
std::string&& signing_key) { … }
MetricsService::FinalizedLog
MetricsService::SnapshotUnloggedSamplesAndFinalizeLog(
MetricsLogHistogramWriter* log_histogram_writer,
std::unique_ptr<MetricsLog> log,
bool truncate_events,
std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
std::string&& current_app_version,
std::string&& signing_key) { … }
MetricsService::FinalizedLog MetricsService::FinalizeLog(
std::unique_ptr<MetricsLog> log,
bool truncate_events,
std::optional<ChromeUserMetricsExtension::RealLocalTime> close_time,
const std::string& current_app_version,
const std::string& signing_key) { … }
}