#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
#include "base/tracked_objects.h"
#include "base/values.h"
#include "components/metrics/metrics_log.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/variations/entropy_provider.h"
-using base::Time;
-using metrics::MetricsLogManager;
+namespace metrics {
namespace {
}
}
-void MarkAppCleanShutdownAndCommit(PrefService* local_state) {
- local_state->SetBoolean(metrics::prefs::kStabilityExitedCleanly, true);
- local_state->SetInteger(metrics::prefs::kStabilityExecutionPhase,
+bool NewInitialMetricsTimingEnabled() {
+ return base::FieldTrialList::FindFullName("UMAInitialMetricsTiming") ==
+ "Enabled";
+}
+
+void MarkAppCleanShutdownAndCommit(CleanExitBeacon* clean_exit_beacon,
+ PrefService* local_state) {
+ clean_exit_beacon->WriteBeaconValue(true);
+ local_state->SetInteger(prefs::kStabilityExecutionPhase,
MetricsService::SHUTDOWN_COMPLETE);
// Start writing right away (write happens on a different thread).
local_state->CommitPendingWrite();
// static
void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
DCHECK(IsSingleThreaded());
- metrics::MetricsStateManager::RegisterPrefs(registry);
+ MetricsStateManager::RegisterPrefs(registry);
MetricsLog::RegisterPrefs(registry);
- registry->RegisterInt64Pref(metrics::prefs::kStabilityLaunchTimeSec, 0);
- registry->RegisterInt64Pref(metrics::prefs::kStabilityLastTimestampSec, 0);
- registry->RegisterStringPref(metrics::prefs::kStabilityStatsVersion,
- std::string());
- registry->RegisterInt64Pref(metrics::prefs::kStabilityStatsBuildTime, 0);
- registry->RegisterBooleanPref(metrics::prefs::kStabilityExitedCleanly, true);
- registry->RegisterIntegerPref(metrics::prefs::kStabilityExecutionPhase,
+ registry->RegisterInt64Pref(prefs::kInstallDate, 0);
+
+ registry->RegisterInt64Pref(prefs::kStabilityLaunchTimeSec, 0);
+ registry->RegisterInt64Pref(prefs::kStabilityLastTimestampSec, 0);
+ registry->RegisterStringPref(prefs::kStabilityStatsVersion, std::string());
+ registry->RegisterInt64Pref(prefs::kStabilityStatsBuildTime, 0);
+ registry->RegisterBooleanPref(prefs::kStabilityExitedCleanly, true);
+ registry->RegisterIntegerPref(prefs::kStabilityExecutionPhase,
UNINITIALIZED_PHASE);
- registry->RegisterBooleanPref(metrics::prefs::kStabilitySessionEndCompleted,
- true);
- registry->RegisterIntegerPref(metrics::prefs::kMetricsSessionID, -1);
+ registry->RegisterBooleanPref(prefs::kStabilitySessionEndCompleted, true);
+ registry->RegisterIntegerPref(prefs::kMetricsSessionID, -1);
- registry->RegisterListPref(metrics::prefs::kMetricsInitialLogs);
- registry->RegisterListPref(metrics::prefs::kMetricsOngoingLogs);
- registry->RegisterListPref(metrics::prefs::kMetricsInitialLogsOld);
- registry->RegisterListPref(metrics::prefs::kMetricsOngoingLogsOld);
+ registry->RegisterListPref(prefs::kMetricsInitialLogs);
+ registry->RegisterListPref(prefs::kMetricsOngoingLogs);
- registry->RegisterInt64Pref(metrics::prefs::kUninstallLaunchCount, 0);
- registry->RegisterInt64Pref(metrics::prefs::kUninstallMetricsUptimeSec, 0);
+ registry->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0);
+ registry->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0);
}
-MetricsService::MetricsService(metrics::MetricsStateManager* state_manager,
- metrics::MetricsServiceClient* client,
+MetricsService::MetricsService(MetricsStateManager* state_manager,
+ MetricsServiceClient* client,
PrefService* local_state)
: log_manager_(local_state, kUploadLogAvoidRetransmitSize),
histogram_snapshot_manager_(this),
state_manager_(state_manager),
client_(client),
local_state_(local_state),
+ clean_exit_beacon_(client->GetRegistryBackupKey(), local_state),
recording_active_(false),
reporting_active_(false),
test_mode_active_(false),
DCHECK(state_manager_);
DCHECK(client_);
DCHECK(local_state_);
+
+ // Set the install date if this is our first run.
+ int64 install_date = local_state_->GetInt64(prefs::kInstallDate);
+ if (install_date == 0)
+ local_state_->SetInt64(prefs::kInstallDate, base::Time::Now().ToTimeT());
}
MetricsService::~MetricsService() {
return state_manager_->client_id();
}
+int64 MetricsService::GetInstallDate() {
+ return local_state_->GetInt64(prefs::kInstallDate);
+}
+
scoped_ptr<const base::FieldTrial::EntropyProvider>
MetricsService::CreateEntropyProvider() {
// TODO(asvitkine): Refactor the code so that MetricsService does not expose
recording_active_ = true;
state_manager_->ForceClientIdCreation();
- client_->SetClientID(state_manager_->client_id());
+ client_->SetMetricsClientId(state_manager_->client_id());
if (!log_manager_.current_log())
OpenNewLog();
metrics_providers_[i]->OnRecordingDisabled();
PushPendingLogsToPersistentStorage();
- DCHECK(!log_manager_.has_staged_log());
}
bool MetricsService::recording_active() const {
void MetricsService::RecordStartOfSessionEnd() {
LogCleanShutdown();
- RecordBooleanPrefValue(metrics::prefs::kStabilitySessionEndCompleted, false);
+ RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false);
}
void MetricsService::RecordCompletedSessionEnd() {
LogCleanShutdown();
- RecordBooleanPrefValue(metrics::prefs::kStabilitySessionEndCompleted, true);
+ RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true);
}
#if defined(OS_ANDROID) || defined(OS_IOS)
void MetricsService::OnAppEnterBackground() {
scheduler_->Stop();
- MarkAppCleanShutdownAndCommit(local_state_);
+ MarkAppCleanShutdownAndCommit(&clean_exit_beacon_, local_state_);
// At this point, there's no way of knowing when the process will be
// killed, so this has to be treated similar to a shutdown, closing and
}
void MetricsService::OnAppEnterForeground() {
- local_state_->SetBoolean(metrics::prefs::kStabilityExitedCleanly, false);
+ clean_exit_beacon_.WriteBeaconValue(false);
StartSchedulerIfNecessary();
}
#else
-void MetricsService::LogNeedForCleanShutdown(PrefService* local_state) {
- local_state->SetBoolean(metrics::prefs::kStabilityExitedCleanly, false);
+void MetricsService::LogNeedForCleanShutdown() {
+ clean_exit_beacon_.WriteBeaconValue(false);
// Redundant setting to be sure we call for a clean shutdown.
clean_shutdown_status_ = NEED_TO_SHUTDOWN;
}
void MetricsService::SetExecutionPhase(ExecutionPhase execution_phase,
PrefService* local_state) {
execution_phase_ = execution_phase;
- local_state->SetInteger(metrics::prefs::kStabilityExecutionPhase,
- execution_phase_);
+ local_state->SetInteger(prefs::kStabilityExecutionPhase, execution_phase_);
}
void MetricsService::RecordBreakpadRegistration(bool success) {
if (!success)
- IncrementPrefValue(metrics::prefs::kStabilityBreakpadRegistrationFail);
+ IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail);
else
- IncrementPrefValue(metrics::prefs::kStabilityBreakpadRegistrationSuccess);
+ IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess);
}
void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) {
if (!has_debugger)
- IncrementPrefValue(metrics::prefs::kStabilityDebuggerNotPresent);
+ IncrementPrefValue(prefs::kStabilityDebuggerNotPresent);
else
- IncrementPrefValue(metrics::prefs::kStabilityDebuggerPresent);
+ IncrementPrefValue(prefs::kStabilityDebuggerPresent);
+}
+
+void MetricsService::ClearSavedStabilityMetrics() {
+ for (size_t i = 0; i < metrics_providers_.size(); ++i)
+ metrics_providers_[i]->ClearSavedStabilityMetrics();
+
+ // Reset the prefs that are managed by MetricsService/MetricsLog directly.
+ local_state_->SetInteger(prefs::kStabilityCrashCount, 0);
+ local_state_->SetInteger(prefs::kStabilityExecutionPhase,
+ UNINITIALIZED_PHASE);
+ local_state_->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0);
+ local_state_->SetInteger(prefs::kStabilityLaunchCount, 0);
+ local_state_->SetBoolean(prefs::kStabilitySessionEndCompleted, true);
}
//------------------------------------------------------------------------------
// Initialization methods
void MetricsService::InitializeMetricsState() {
- local_state_->SetString(metrics::prefs::kStabilityStatsVersion,
- client_->GetVersionString());
- local_state_->SetInt64(metrics::prefs::kStabilityStatsBuildTime,
- MetricsLog::GetBuildTime());
+ const int64 buildtime = MetricsLog::GetBuildTime();
+ const std::string version = client_->GetVersionString();
+ bool version_changed = false;
+ if (local_state_->GetInt64(prefs::kStabilityStatsBuildTime) != buildtime ||
+ local_state_->GetString(prefs::kStabilityStatsVersion) != version) {
+ local_state_->SetString(prefs::kStabilityStatsVersion, version);
+ local_state_->SetInt64(prefs::kStabilityStatsBuildTime, buildtime);
+ version_changed = true;
+ }
- session_id_ = local_state_->GetInteger(metrics::prefs::kMetricsSessionID);
+ log_manager_.LoadPersistedUnsentLogs();
- if (!local_state_->GetBoolean(metrics::prefs::kStabilityExitedCleanly)) {
- IncrementPrefValue(metrics::prefs::kStabilityCrashCount);
+ session_id_ = local_state_->GetInteger(prefs::kMetricsSessionID);
+
+ if (!clean_exit_beacon_.exited_cleanly()) {
+ IncrementPrefValue(prefs::kStabilityCrashCount);
// Reset flag, and wait until we call LogNeedForCleanShutdown() before
// monitoring.
- local_state_->SetBoolean(metrics::prefs::kStabilityExitedCleanly, true);
+ clean_exit_beacon_.WriteBeaconValue(true);
+ }
+ if (!clean_exit_beacon_.exited_cleanly() || ProvidersHaveStabilityMetrics()) {
// TODO(rtenneti): On windows, consider saving/getting execution_phase from
// the registry.
int execution_phase =
- local_state_->GetInteger(metrics::prefs::kStabilityExecutionPhase);
+ local_state_->GetInteger(prefs::kStabilityExecutionPhase);
UMA_HISTOGRAM_SPARSE_SLOWLY("Chrome.Browser.CrashedExecutionPhase",
execution_phase);
- // If the previous session didn't exit cleanly, then prepare an initial
- // stability log if UMA is enabled.
+ // If the previous session didn't exit cleanly, or if any provider
+ // explicitly requests it, prepare an initial stability log -
+ // provided UMA is enabled.
if (state_manager_->IsMetricsReportingEnabled())
PrepareInitialStabilityLog();
}
+ // If no initial stability log was generated and there was a version upgrade,
+ // clear the stability stats from the previous version (so that they don't get
+ // attributed to the current version). This could otherwise happen due to a
+ // number of different edge cases, such as if the last version crashed before
+ // it could save off a system profile or if UMA reporting is disabled (which
+ // normally results in stats being accumulated).
+ if (!has_initial_stability_log_ && version_changed)
+ ClearSavedStabilityMetrics();
+
// Update session ID.
++session_id_;
- local_state_->SetInteger(metrics::prefs::kMetricsSessionID, session_id_);
+ local_state_->SetInteger(prefs::kMetricsSessionID, session_id_);
// Stability bookkeeping
- IncrementPrefValue(metrics::prefs::kStabilityLaunchCount);
+ IncrementPrefValue(prefs::kStabilityLaunchCount);
DCHECK_EQ(UNINITIALIZED_PHASE, execution_phase_);
SetExecutionPhase(START_METRICS_RECORDING, local_state_);
- if (!local_state_->GetBoolean(
- metrics::prefs::kStabilitySessionEndCompleted)) {
- IncrementPrefValue(metrics::prefs::kStabilityIncompleteSessionEndCount);
+ if (!local_state_->GetBoolean(prefs::kStabilitySessionEndCompleted)) {
+ IncrementPrefValue(prefs::kStabilityIncompleteSessionEndCount);
// This is marked false when we get a WM_ENDSESSION.
- local_state_->SetBoolean(metrics::prefs::kStabilitySessionEndCompleted,
- true);
+ local_state_->SetBoolean(prefs::kStabilitySessionEndCompleted, true);
}
// Call GetUptimes() for the first time, thus allowing all later calls
GetUptimes(local_state_, &startup_uptime, &ignored_uptime_parameter);
DCHECK_EQ(0, startup_uptime.InMicroseconds());
// For backwards compatibility, leave this intact in case Omaha is checking
- // them. metrics::prefs::kStabilityLastTimestampSec may also be useless now.
+ // them. prefs::kStabilityLastTimestampSec may also be useless now.
// TODO(jar): Delete these if they have no uses.
- local_state_->SetInt64(metrics::prefs::kStabilityLaunchTimeSec,
- Time::Now().ToTimeT());
+ local_state_->SetInt64(prefs::kStabilityLaunchTimeSec,
+ base::Time::Now().ToTimeT());
// Bookkeeping for the uninstall metrics.
- IncrementLongPrefsValue(metrics::prefs::kUninstallLaunchCount);
+ IncrementLongPrefsValue(prefs::kUninstallLaunchCount);
// Kick off the process of saving the state (so the uptime numbers keep
// getting updated) every n minutes.
const int64 incremental_time_secs = incremental_uptime->InSeconds();
if (incremental_time_secs > 0) {
- int64 metrics_uptime =
- pref->GetInt64(metrics::prefs::kUninstallMetricsUptimeSec);
+ int64 metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec);
metrics_uptime += incremental_time_secs;
- pref->SetInt64(metrics::prefs::kUninstallMetricsUptimeSec, metrics_uptime);
+ pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime);
}
}
-void MetricsService::AddObserver(MetricsServiceObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.AddObserver(observer);
-}
-
-void MetricsService::RemoveObserver(MetricsServiceObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.RemoveObserver(observer);
-}
-
void MetricsService::NotifyOnDidCreateMetricsLog() {
- DCHECK(thread_checker_.CalledOnValidThread());
- FOR_EACH_OBSERVER(
- MetricsServiceObserver, observers_, OnDidCreateMetricsLog());
+ DCHECK(IsSingleThreaded());
for (size_t i = 0; i < metrics_providers_.size(); ++i)
metrics_providers_[i]->OnDidCreateMetricsLog();
}
// end of all log transmissions (initial log handles this separately).
// RecordIncrementalStabilityElements only exists on the derived
// MetricsLog class.
- MetricsLog* current_log =
- static_cast<MetricsLog*>(log_manager_.current_log());
+ MetricsLog* current_log = log_manager_.current_log();
DCHECK(current_log);
- std::vector<variations::ActiveGroupId> synthetic_trials;
- GetCurrentSyntheticFieldTrials(&synthetic_trials);
- current_log->RecordEnvironment(metrics_providers_.get(), synthetic_trials);
+ RecordCurrentEnvironment(current_log);
base::TimeDelta incremental_uptime;
base::TimeDelta uptime;
GetUptimes(local_state_, &incremental_uptime, &uptime);
current_log->RecordStabilityMetrics(metrics_providers_.get(),
incremental_uptime, uptime);
- RecordCurrentHistograms();
current_log->RecordGeneralMetrics(metrics_providers_.get());
+ RecordCurrentHistograms();
log_manager_.FinishCurrentLog();
}
if (state_ < SENDING_INITIAL_STABILITY_LOG)
return; // We didn't and still don't have time to get plugin list etc.
- if (log_manager_.has_staged_log()) {
- // We may race here, and send second copy of the log later.
- metrics::PersistedLogs::StoreType store_type;
- if (log_upload_in_progress_)
- store_type = metrics::PersistedLogs::PROVISIONAL_STORE;
- else
- store_type = metrics::PersistedLogs::NORMAL_STORE;
- log_manager_.StoreStagedLogAsUnsent(store_type);
- }
- DCHECK(!log_manager_.has_staged_log());
CloseCurrentLog();
log_manager_.PersistUnsentLogs();
return;
case INIT_TASK_DONE:
- if (has_initial_stability_log_) {
- // There's an initial stability log, ready to send.
+ if (NewInitialMetricsTimingEnabled()) {
+ PrepareInitialMetricsLog();
+ // Stage the first log, which could be a stability log (either one
+ // for created in this session or from a previous session) or the
+ // initial metrics log that was just created.
log_manager_.StageNextLogForUpload();
- has_initial_stability_log_ = false;
- // Note: No need to call LoadPersistedUnsentLogs() here because unsent
- // logs have already been loaded by PrepareInitialStabilityLog().
- state_ = SENDING_INITIAL_STABILITY_LOG;
+ if (has_initial_stability_log_) {
+ // The initial stability log was just staged.
+ has_initial_stability_log_ = false;
+ state_ = SENDING_INITIAL_STABILITY_LOG;
+ } else {
+ state_ = SENDING_INITIAL_METRICS_LOG;
+ }
} else {
- PrepareInitialMetricsLog();
- // Load unsent logs (if any) from local state.
- log_manager_.LoadPersistedUnsentLogs();
- state_ = SENDING_INITIAL_METRICS_LOG;
+ if (has_initial_stability_log_) {
+ // There's an initial stability log, ready to send.
+ log_manager_.StageNextLogForUpload();
+ has_initial_stability_log_ = false;
+ state_ = SENDING_INITIAL_STABILITY_LOG;
+ } else {
+ PrepareInitialMetricsLog();
+ log_manager_.StageNextLogForUpload();
+ state_ = SENDING_INITIAL_METRICS_LOG;
+ }
}
break;
DCHECK(log_manager_.has_staged_log());
}
+bool MetricsService::ProvidersHaveStabilityMetrics() {
+ // Check whether any metrics provider has stability metrics.
+ for (size_t i = 0; i < metrics_providers_.size(); ++i) {
+ if (metrics_providers_[i]->HasStabilityMetrics())
+ return true;
+ }
+
+ return false;
+}
+
void MetricsService::PrepareInitialStabilityLog() {
DCHECK_EQ(INITIALIZED, state_);
- DCHECK_NE(0, local_state_->GetInteger(metrics::prefs::kStabilityCrashCount));
scoped_ptr<MetricsLog> initial_stability_log(
CreateLog(MetricsLog::INITIAL_STABILITY_LOG));
if (!initial_stability_log->LoadSavedEnvironmentFromPrefs())
return;
- log_manager_.LoadPersistedUnsentLogs();
-
log_manager_.PauseCurrentLog();
log_manager_.BeginLoggingWithLog(initial_stability_log.Pass());
void MetricsService::PrepareInitialMetricsLog() {
DCHECK(state_ == INIT_TASK_DONE || state_ == SENDING_INITIAL_STABILITY_LOG);
- std::vector<variations::ActiveGroupId> synthetic_trials;
- GetCurrentSyntheticFieldTrials(&synthetic_trials);
- initial_metrics_log_->RecordEnvironment(metrics_providers_.get(),
- synthetic_trials);
+ RecordCurrentEnvironment(initial_metrics_log_.get());
base::TimeDelta incremental_uptime;
base::TimeDelta uptime;
GetUptimes(local_state_, &incremental_uptime, &uptime);
// Note: Some stability providers may record stability stats via histograms,
// so this call has to be after BeginLoggingWithLog().
- MetricsLog* current_log =
- static_cast<MetricsLog*>(log_manager_.current_log());
+ MetricsLog* current_log = log_manager_.current_log();
current_log->RecordStabilityMetrics(metrics_providers_.get(),
base::TimeDelta(), base::TimeDelta());
- RecordCurrentHistograms();
-
current_log->RecordGeneralMetrics(metrics_providers_.get());
+ RecordCurrentHistograms();
log_manager_.FinishCurrentLog();
log_manager_.ResumePausedLog();
- DCHECK(!log_manager_.has_staged_log());
- log_manager_.StageNextLogForUpload();
+ // Store unsent logs, including the initial log that was just saved, so
+ // that they're not lost in case of a crash before upload time.
+ log_manager_.PersistUnsentLogs();
}
void MetricsService::SendStagedLog() {
ResponseCodeToStatus(response_code),
NUM_RESPONSE_STATUSES);
- // If the upload was provisionally stored, drop it now that the upload is
- // known to have gone through.
- log_manager_.DiscardLastProvisionalStore();
-
bool upload_succeeded = response_code == 200;
// Provide boolean for error recovery (allow us to ignore response_code).
bool discard_log = false;
const size_t log_size = log_manager_.staged_log().length();
- if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) {
+ if (upload_succeeded) {
+ UMA_HISTOGRAM_COUNTS_10000("UMA.LogSize.OnSuccess", log_size / 1024);
+ } else if (log_size > kUploadLogAvoidRetransmitSize) {
UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded",
static_cast<int>(log_size));
discard_log = true;
discard_log = true;
}
- if (upload_succeeded || discard_log)
+ if (upload_succeeded || discard_log) {
log_manager_.DiscardStagedLog();
+ // Store the updated list to disk now that the removed log is uploaded.
+ log_manager_.PersistUnsentLogs();
+ }
if (!log_manager_.has_staged_log()) {
switch (state_) {
case SENDING_INITIAL_STABILITY_LOG:
- // Store the updated list to disk now that the removed log is uploaded.
- log_manager_.PersistUnsentLogs();
- PrepareInitialMetricsLog();
- SendStagedLog();
- state_ = SENDING_INITIAL_METRICS_LOG;
+ if (NewInitialMetricsTimingEnabled()) {
+ // The initial metrics log is already in the queue of unsent logs.
+ state_ = SENDING_OLD_LOGS;
+ } else {
+ PrepareInitialMetricsLog();
+ log_manager_.StageNextLogForUpload();
+ SendStagedLog();
+ state_ = SENDING_INITIAL_METRICS_LOG;
+ }
break;
case SENDING_INITIAL_METRICS_LOG:
- // The initial metrics log never gets persisted to local state, so it's
- // not necessary to call log_manager_.PersistUnsentLogs() here.
- // TODO(asvitkine): It should be persisted like the initial stability
- // log and old unsent logs. http://crbug.com/328417
state_ = log_manager_.has_unsent_logs() ? SENDING_OLD_LOGS
: SENDING_CURRENT_LOGS;
break;
case SENDING_OLD_LOGS:
- // Store the updated list to disk now that the removed log is uploaded.
- log_manager_.PersistUnsentLogs();
if (!log_manager_.has_unsent_logs())
state_ = SENDING_CURRENT_LOGS;
break;
return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
}
+void MetricsService::AddSyntheticTrialObserver(
+ SyntheticTrialObserver* observer) {
+ synthetic_trial_observer_list_.AddObserver(observer);
+ if (!synthetic_trial_groups_.empty())
+ observer->OnSyntheticTrialsChanged(synthetic_trial_groups_);
+}
+
+void MetricsService::RemoveSyntheticTrialObserver(
+ SyntheticTrialObserver* observer) {
+ synthetic_trial_observer_list_.RemoveObserver(observer);
+}
+
void MetricsService::RegisterSyntheticFieldTrial(
const SyntheticTrialGroup& trial) {
for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) {
if (synthetic_trial_groups_[i].id.group != trial.id.group) {
synthetic_trial_groups_[i].id.group = trial.id.group;
synthetic_trial_groups_[i].start_time = base::TimeTicks::Now();
+ NotifySyntheticTrialObservers();
}
return;
}
SyntheticTrialGroup trial_group = trial;
trial_group.start_time = base::TimeTicks::Now();
synthetic_trial_groups_.push_back(trial_group);
+ NotifySyntheticTrialObservers();
}
void MetricsService::RegisterMetricsProvider(
- scoped_ptr<metrics::MetricsProvider> provider) {
+ scoped_ptr<MetricsProvider> provider) {
DCHECK_EQ(INITIALIZED, state_);
metrics_providers_.push_back(provider.release());
}
state_manager_->CheckForClonedInstall(task_runner);
}
+void MetricsService::NotifySyntheticTrialObservers() {
+ FOR_EACH_OBSERVER(SyntheticTrialObserver, synthetic_trial_observer_list_,
+ OnSyntheticTrialsChanged(synthetic_trial_groups_));
+}
+
void MetricsService::GetCurrentSyntheticFieldTrials(
std::vector<variations::ActiveGroupId>* synthetic_trials) {
DCHECK(synthetic_trials);
synthetic_trials->clear();
- const MetricsLog* current_log =
- static_cast<const MetricsLog*>(log_manager_.current_log());
+ const MetricsLog* current_log = log_manager_.current_log();
for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) {
if (synthetic_trial_groups_[i].start_time <= current_log->creation_time())
synthetic_trials->push_back(synthetic_trial_groups_[i].id);
local_state_));
}
+void MetricsService::RecordCurrentEnvironment(MetricsLog* log) {
+ std::vector<variations::ActiveGroupId> synthetic_trials;
+ GetCurrentSyntheticFieldTrials(&synthetic_trials);
+ log->RecordEnvironment(metrics_providers_.get(), synthetic_trials,
+ GetInstallDate());
+ UMA_HISTOGRAM_COUNTS_100("UMA.SyntheticTrials.Count",
+ synthetic_trials.size());
+}
+
void MetricsService::RecordCurrentHistograms() {
DCHECK(log_manager_.current_log());
histogram_snapshot_manager_.PrepareDeltas(
void MetricsService::LogCleanShutdown() {
// Redundant hack to write pref ASAP.
- MarkAppCleanShutdownAndCommit(local_state_);
+ MarkAppCleanShutdownAndCommit(&clean_exit_beacon_, local_state_);
// Redundant setting to assure that we always reset this value at shutdown
// (and that we don't use some alternate path, and not call LogCleanShutdown).
clean_shutdown_status_ = CLEANLY_SHUTDOWN;
- RecordBooleanPrefValue(metrics::prefs::kStabilityExitedCleanly, true);
- local_state_->SetInteger(metrics::prefs::kStabilityExecutionPhase,
+ clean_exit_beacon_.WriteBeaconValue(true);
+ RecordCurrentState(local_state_);
+ local_state_->SetInteger(prefs::kStabilityExecutionPhase,
MetricsService::SHUTDOWN_COMPLETE);
}
}
void MetricsService::RecordCurrentState(PrefService* pref) {
- pref->SetInt64(metrics::prefs::kStabilityLastTimestampSec,
- Time::Now().ToTimeT());
-
- for (size_t i = 0; i < metrics_providers_.size(); ++i)
- metrics_providers_[i]->RecordCurrentState();
+ pref->SetInt64(prefs::kStabilityLastTimestampSec,
+ base::Time::Now().ToTimeT());
}
+
+} // namespace metrics