Commit c179dd06 authored by siggi's avatar siggi Committed by Commit bot

Allow MetricsProviders to request an initial stability log.

BUG=412384

Review URL: https://codereview.chromium.org/558653002

Cr-Commit-Position: refs/heads/master@{#294182}
parent ca7c6cd6
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
'metrics/metrics_log_uploader.h', 'metrics/metrics_log_uploader.h',
'metrics/metrics_pref_names.cc', 'metrics/metrics_pref_names.cc',
'metrics/metrics_pref_names.h', 'metrics/metrics_pref_names.h',
'metrics/metrics_provider.cc',
'metrics/metrics_provider.h', 'metrics/metrics_provider.h',
'metrics/metrics_reporting_scheduler.cc', 'metrics/metrics_reporting_scheduler.cc',
'metrics/metrics_reporting_scheduler.h', 'metrics/metrics_reporting_scheduler.h',
......
...@@ -24,6 +24,7 @@ source_set("metrics") { ...@@ -24,6 +24,7 @@ source_set("metrics") {
"metrics_log_uploader.h", "metrics_log_uploader.h",
"metrics_pref_names.cc", "metrics_pref_names.cc",
"metrics_pref_names.h", "metrics_pref_names.h",
"metrics_provider.cc",
"metrics_provider.h", "metrics_provider.h",
"metrics_reporting_scheduler.cc", "metrics_reporting_scheduler.cc",
"metrics_reporting_scheduler.h", "metrics_reporting_scheduler.h",
......
// Copyright 2014 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 "components/metrics/metrics_provider.h"
namespace metrics {
MetricsProvider::MetricsProvider() {
}
MetricsProvider::~MetricsProvider() {
}
void MetricsProvider::OnDidCreateMetricsLog() {
}
void MetricsProvider::OnRecordingEnabled() {
}
void MetricsProvider::OnRecordingDisabled() {
}
void MetricsProvider::ProvideSystemProfileMetrics(
SystemProfileProto* system_profile_proto) {
}
bool MetricsProvider::HasStabilityMetrics() {
return false;
}
void MetricsProvider::ProvideStabilityMetrics(
SystemProfileProto* system_profile_proto) {
}
void MetricsProvider::ProvideGeneralMetrics(
ChromeUserMetricsExtension* uma_proto) {
}
} // namespace metrics
...@@ -17,32 +17,36 @@ class SystemProfileProto_Stability; ...@@ -17,32 +17,36 @@ class SystemProfileProto_Stability;
// be filled out by different classes. // be filled out by different classes.
class MetricsProvider { class MetricsProvider {
public: public:
MetricsProvider() {} MetricsProvider();
virtual ~MetricsProvider() {} virtual ~MetricsProvider();
// Called when a new MetricsLog is created. // Called when a new MetricsLog is created.
virtual void OnDidCreateMetricsLog() {} virtual void OnDidCreateMetricsLog();
// Called when metrics recording has been enabled. // Called when metrics recording has been enabled.
virtual void OnRecordingEnabled() {} virtual void OnRecordingEnabled();
// Called when metrics recording has been disabled. // Called when metrics recording has been disabled.
virtual void OnRecordingDisabled() {} virtual void OnRecordingDisabled();
// Provides additional metrics into the system profile. // Provides additional metrics into the system profile.
virtual void ProvideSystemProfileMetrics( virtual void ProvideSystemProfileMetrics(
SystemProfileProto* system_profile_proto) {} SystemProfileProto* system_profile_proto);
// Called once at startup to see whether this provider has stability events
// to share. Default implementation always returns false.
virtual bool HasStabilityMetrics();
// Provides additional stability metrics. Stability metrics can be provided // Provides additional stability metrics. Stability metrics can be provided
// directly into |stability_proto| fields or by logging stability histograms // directly into |stability_proto| fields or by logging stability histograms
// via the UMA_STABILITY_HISTOGRAM_ENUMERATION() macro. // via the UMA_STABILITY_HISTOGRAM_ENUMERATION() macro.
virtual void ProvideStabilityMetrics( virtual void ProvideStabilityMetrics(
SystemProfileProto* system_profile_proto) {} SystemProfileProto* system_profile_proto);
// Provides general metrics that are neither system profile nor stability // Provides general metrics that are neither system profile nor stability
// metrics. // metrics.
virtual void ProvideGeneralMetrics( virtual void ProvideGeneralMetrics(
ChromeUserMetricsExtension* uma_proto) {} ChromeUserMetricsExtension* uma_proto);
private: private:
DISALLOW_COPY_AND_ASSIGN(MetricsProvider); DISALLOW_COPY_AND_ASSIGN(MetricsProvider);
......
...@@ -564,13 +564,16 @@ void MetricsService::InitializeMetricsState() { ...@@ -564,13 +564,16 @@ void MetricsService::InitializeMetricsState() {
log_manager_.LoadPersistedUnsentLogs(); log_manager_.LoadPersistedUnsentLogs();
session_id_ = local_state_->GetInteger(metrics::prefs::kMetricsSessionID); session_id_ = local_state_->GetInteger(metrics::prefs::kMetricsSessionID);
bool exited_cleanly = true;
if (!local_state_->GetBoolean(metrics::prefs::kStabilityExitedCleanly)) { if (!local_state_->GetBoolean(metrics::prefs::kStabilityExitedCleanly)) {
IncrementPrefValue(metrics::prefs::kStabilityCrashCount); IncrementPrefValue(metrics::prefs::kStabilityCrashCount);
// Reset flag, and wait until we call LogNeedForCleanShutdown() before // Reset flag, and wait until we call LogNeedForCleanShutdown() before
// monitoring. // monitoring.
local_state_->SetBoolean(metrics::prefs::kStabilityExitedCleanly, true); local_state_->SetBoolean(metrics::prefs::kStabilityExitedCleanly, true);
exited_cleanly = false;
}
if (!exited_cleanly || ProvidersHaveStabilityMetrics()) {
// TODO(rtenneti): On windows, consider saving/getting execution_phase from // TODO(rtenneti): On windows, consider saving/getting execution_phase from
// the registry. // the registry.
int execution_phase = int execution_phase =
...@@ -578,8 +581,9 @@ void MetricsService::InitializeMetricsState() { ...@@ -578,8 +581,9 @@ void MetricsService::InitializeMetricsState() {
UMA_HISTOGRAM_SPARSE_SLOWLY("Chrome.Browser.CrashedExecutionPhase", UMA_HISTOGRAM_SPARSE_SLOWLY("Chrome.Browser.CrashedExecutionPhase",
execution_phase); execution_phase);
// If the previous session didn't exit cleanly, then prepare an initial // If the previous session didn't exit cleanly, or if any provider
// stability log if UMA is enabled. // explicitly requests it, prepare an initial stability log -
// provided UMA is enabled.
if (state_manager_->IsMetricsReportingEnabled()) if (state_manager_->IsMetricsReportingEnabled())
PrepareInitialStabilityLog(); PrepareInitialStabilityLog();
} }
...@@ -896,9 +900,18 @@ void MetricsService::StageNewLog() { ...@@ -896,9 +900,18 @@ void MetricsService::StageNewLog() {
DCHECK(log_manager_.has_staged_log()); 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() { void MetricsService::PrepareInitialStabilityLog() {
DCHECK_EQ(INITIALIZED, state_); DCHECK_EQ(INITIALIZED, state_);
DCHECK_NE(0, local_state_->GetInteger(metrics::prefs::kStabilityCrashCount));
scoped_ptr<MetricsLog> initial_stability_log( scoped_ptr<MetricsLog> initial_stability_log(
CreateLog(MetricsLog::INITIAL_STABILITY_LOG)); CreateLog(MetricsLog::INITIAL_STABILITY_LOG));
......
...@@ -315,6 +315,10 @@ class MetricsService : public base::HistogramFlattener { ...@@ -315,6 +315,10 @@ class MetricsService : public base::HistogramFlattener {
// (depending on |state_|), and stages it for upload. // (depending on |state_|), and stages it for upload.
void StageNewLog(); void StageNewLog();
// Returns true if any of the registered metrics providers have stability
// metrics to report.
bool ProvidersHaveStabilityMetrics();
// Prepares the initial stability log, which is only logged when the previous // Prepares the initial stability log, which is only logged when the previous
// run of Chrome crashed. This log contains any stability metrics left over // run of Chrome crashed. This log contains any stability metrics left over
// from that previous run, and only these stability metrics. It uses the // from that previous run, and only these stability metrics. It uses the
......
...@@ -31,6 +31,30 @@ scoped_ptr<ClientInfo> ReturnNoBackup() { ...@@ -31,6 +31,30 @@ scoped_ptr<ClientInfo> ReturnNoBackup() {
return scoped_ptr<ClientInfo>(); return scoped_ptr<ClientInfo>();
} }
class TestMetricsProvider : public metrics::MetricsProvider {
public:
explicit TestMetricsProvider(bool has_stability_metrics) :
has_stability_metrics_(has_stability_metrics),
provide_stability_metrics_called_(false) {
}
virtual bool HasStabilityMetrics() OVERRIDE { return has_stability_metrics_; }
virtual void ProvideStabilityMetrics(
SystemProfileProto* system_profile_proto) OVERRIDE {
provide_stability_metrics_called_ = true;
}
bool provide_stability_metrics_called() const {
return provide_stability_metrics_called_;
}
private:
bool has_stability_metrics_;
bool provide_stability_metrics_called_;
DISALLOW_COPY_AND_ASSIGN(TestMetricsProvider);
};
class TestMetricsService : public MetricsService { class TestMetricsService : public MetricsService {
public: public:
TestMetricsService(MetricsStateManager* state_manager, TestMetricsService(MetricsStateManager* state_manager,
...@@ -138,10 +162,83 @@ TEST_F(MetricsServiceTest, InitialStabilityLogAfterCleanShutDown) { ...@@ -138,10 +162,83 @@ TEST_F(MetricsServiceTest, InitialStabilityLogAfterCleanShutDown) {
TestMetricsServiceClient client; TestMetricsServiceClient client;
TestMetricsService service( TestMetricsService service(
GetMetricsStateManager(), &client, GetLocalState()); GetMetricsStateManager(), &client, GetLocalState());
TestMetricsProvider* test_provider = new TestMetricsProvider(false);
service.RegisterMetricsProvider(
scoped_ptr<metrics::MetricsProvider>(test_provider));
service.InitializeMetricsRecordingState(); service.InitializeMetricsRecordingState();
// No initial stability log should be generated. // No initial stability log should be generated.
EXPECT_FALSE(service.log_manager()->has_unsent_logs()); EXPECT_FALSE(service.log_manager()->has_unsent_logs());
EXPECT_FALSE(service.log_manager()->has_staged_log()); EXPECT_FALSE(service.log_manager()->has_staged_log());
// The test provider should not have been called upon to provide stability
// metrics.
EXPECT_FALSE(test_provider->provide_stability_metrics_called());
}
TEST_F(MetricsServiceTest, InitialStabilityLogAtProviderRequest) {
EnableMetricsReporting();
// Save an existing system profile to prefs, to correspond to what would be
// saved from a previous session.
TestMetricsServiceClient client;
TestMetricsLog log("client", 1, &client, GetLocalState());
log.RecordEnvironment(std::vector<metrics::MetricsProvider*>(),
std::vector<variations::ActiveGroupId>(),
0);
// Record stability build time and version from previous session, so that
// stability metrics (including exited cleanly flag) won't be cleared.
GetLocalState()->SetInt64(prefs::kStabilityStatsBuildTime,
MetricsLog::GetBuildTime());
GetLocalState()->SetString(prefs::kStabilityStatsVersion,
client.GetVersionString());
// Set the clean exit flag, as that will otherwise cause a stabilty
// log to be produced, irrespective provider requests.
GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true);
TestMetricsService service(
GetMetricsStateManager(), &client, GetLocalState());
// Add a metrics provider that requests a stability log.
TestMetricsProvider* test_provider = new TestMetricsProvider(true);
service.RegisterMetricsProvider(
scoped_ptr<MetricsProvider>(test_provider));
service.InitializeMetricsRecordingState();
// The initial stability log should be generated and persisted in unsent logs.
MetricsLogManager* log_manager = service.log_manager();
EXPECT_TRUE(log_manager->has_unsent_logs());
EXPECT_FALSE(log_manager->has_staged_log());
// The test provider should have been called upon to provide stability
// metrics.
EXPECT_TRUE(test_provider->provide_stability_metrics_called());
// Stage the log and retrieve it.
log_manager->StageNextLogForUpload();
EXPECT_TRUE(log_manager->has_staged_log());
std::string uncompressed_log;
EXPECT_TRUE(GzipUncompress(log_manager->staged_log(),
&uncompressed_log));
ChromeUserMetricsExtension uma_log;
EXPECT_TRUE(uma_log.ParseFromString(uncompressed_log));
EXPECT_TRUE(uma_log.has_client_id());
EXPECT_TRUE(uma_log.has_session_id());
EXPECT_TRUE(uma_log.has_system_profile());
EXPECT_EQ(0, uma_log.user_action_event_size());
EXPECT_EQ(0, uma_log.omnibox_event_size());
EXPECT_EQ(0, uma_log.histogram_event_size());
EXPECT_EQ(0, uma_log.profiler_event_size());
EXPECT_EQ(0, uma_log.perf_data_size());
// As there wasn't an unclean shutdown, this log has zero crash count.
EXPECT_EQ(0, uma_log.system_profile().stability().crash_count());
} }
TEST_F(MetricsServiceTest, InitialStabilityLogAfterCrash) { TEST_F(MetricsServiceTest, InitialStabilityLogAfterCrash) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment