// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/metrics/cast_stability_metrics_provider.h"
#include <vector>
#include "base/check.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "chromecast/base/pref_names.h"
#include "chromecast/metrics/cast_metrics_service_client.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/stability_metrics_helper.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_process_host.h"
namespace chromecast {
namespace metrics {
namespace {
enum RendererType {
RENDERER_TYPE_RENDERER = 1,
RENDERER_TYPE_EXTENSION, // Not used, but needed for correct histogram count.
// NOTE: Add new action types only immediately above this line. Also,
// make sure the enum list in tools/metrics/histograms/histograms.xml is
// updated with any change in here.
RENDERER_TYPE_COUNT
};
// Converts an exit code into something that can be inserted into our
// histograms (which expect non-negative numbers less than MAX_INT).
int MapCrashExitCodeForHistogram(int exit_code) {
return std::abs(exit_code);
}
} // namespace
CastStabilityMetricsProvider::CastStabilityMetricsProvider(
::metrics::MetricsService* metrics_service,
PrefService* pref_service)
: metrics_service_(metrics_service), pref_service_(pref_service) {
DCHECK(pref_service_);
}
CastStabilityMetricsProvider::~CastStabilityMetricsProvider() {}
void CastStabilityMetricsProvider::OnRecordingEnabled() {
logging_enabled_ = true;
}
void CastStabilityMetricsProvider::OnRecordingDisabled() {
logging_enabled_ = false;
}
void CastStabilityMetricsProvider::LogExternalCrash(
const std::string& crash_type) {
if (crash_type == "user")
IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
else if (crash_type == "kernel")
IncrementPrefValue(prefs::kStabilityKernelCrashCount);
else if (crash_type == "uncleanshutdown")
IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
else
NOTREACHED_IN_MIGRATION() << "Unexpected crash type " << crash_type;
// Wake up metrics logs sending if necessary now that new
// log data is available.
metrics_service_->OnApplicationNotIdle();
}
void CastStabilityMetricsProvider::OnRenderProcessHostCreated(
content::RenderProcessHost* host) {
if (!scoped_observations_.IsObservingSource(host))
scoped_observations_.AddObservation(host);
}
void CastStabilityMetricsProvider::RenderProcessExited(
content::RenderProcessHost* host,
const content::ChildProcessTerminationInfo& info) {
LogRendererCrash(host, info.status, info.exit_code);
}
void CastStabilityMetricsProvider::RenderProcessHostDestroyed(
content::RenderProcessHost* host) {
scoped_observations_.RemoveObservation(host);
}
void CastStabilityMetricsProvider::LogRendererCrash(
content::RenderProcessHost* host,
base::TerminationStatus status,
int exit_code) {
if (!logging_enabled_)
return;
if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
::metrics::StabilityMetricsHelper::RecordStabilityEvent(
::metrics::StabilityEventType::kRendererCrash);
base::UmaHistogramSparse("CrashExitCodes.Renderer",
MapCrashExitCodeForHistogram(exit_code));
UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildCrashes",
RENDERER_TYPE_RENDERER, RENDERER_TYPE_COUNT);
} else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills",
RENDERER_TYPE_RENDERER, RENDERER_TYPE_COUNT);
} else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.DisconnectedAlive",
RENDERER_TYPE_RENDERER, RENDERER_TYPE_COUNT);
} else if (status == base::TERMINATION_STATUS_LAUNCH_FAILED) {
::metrics::StabilityMetricsHelper::RecordStabilityEvent(
::metrics::StabilityEventType::kRendererFailedLaunch);
}
}
void CastStabilityMetricsProvider::IncrementPrefValue(const char* path) {
int value = pref_service_->GetInteger(path);
pref_service_->SetInteger(path, value + 1);
}
} // namespace metrics
} // namespace chromecast