blob: e77aa482a90201a9d091d88b8294bfbad98478c6 [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/metrics/renderer_uptime_tracker.h"
#include "base/metrics/histogram_macros.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/buildflags/buildflags.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/process_map.h"
#endif
namespace metrics {
namespace {
RendererUptimeTracker* g_renderer_uptime_tracker_instance = nullptr;
} // namespace
// static
void RendererUptimeTracker::Initialize() {
DCHECK(!g_renderer_uptime_tracker_instance);
g_renderer_uptime_tracker_instance = new RendererUptimeTracker;
}
// static
RendererUptimeTracker* RendererUptimeTracker::SetMockRendererUptimeTracker(
RendererUptimeTracker* tracker) {
RendererUptimeTracker* old_tracker = g_renderer_uptime_tracker_instance;
g_renderer_uptime_tracker_instance = tracker;
return old_tracker;
}
// static
RendererUptimeTracker* RendererUptimeTracker::Get() {
DCHECK(g_renderer_uptime_tracker_instance);
return g_renderer_uptime_tracker_instance;
}
RendererUptimeTracker::RendererUptimeTracker() {
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
}
RendererUptimeTracker::~RendererUptimeTracker() {}
void RendererUptimeTracker::OnRendererStarted(int pid) {
info_map_[pid] = RendererInfo{base::TimeTicks::Now(), 0};
}
base::TimeDelta RendererUptimeTracker::GetProcessUptime(int pid) {
auto it = info_map_.find(pid);
// The pid may not exist when process fails to start up or when process is
// terminated without reuse.
if (it == info_map_.end())
return base::TimeDelta();
return base::TimeTicks::Now() - it->second.launched_at_;
}
void RendererUptimeTracker::OnRendererTerminated(int pid) {
auto it = info_map_.find(pid);
// The pid may not exist when process fails to start up or when process is
// terminated without reuse.
if (it != info_map_.end()) {
auto uptime = base::TimeTicks::Now() - it->second.launched_at_;
UMA_HISTOGRAM_CUSTOM_TIMES("Memory.Experimental.Renderer.Uptime", uptime,
base::TimeDelta::FromHours(1),
base::TimeDelta::FromDays(7), 50);
UMA_HISTOGRAM_COUNTS_10000(
"Memory.Experimental.Renderer.LoadsInMainFrameDuringUptime",
it->second.num_loads_in_main_frame_);
info_map_.erase(it);
}
}
void RendererUptimeTracker::OnLoadInMainFrame(int pid) {
auto it = info_map_.find(pid);
// The pid may not exist in an in-process browser test.
if (it != info_map_.end()) {
it->second.num_loads_in_main_frame_++;
}
}
void RendererUptimeTracker::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
content::RenderProcessHost* host =
content::Source<content::RenderProcessHost>(source).ptr();
#if BUILDFLAG(ENABLE_EXTENSIONS)
if (extensions::ProcessMap::Get(host->GetBrowserContext())
->Contains(host->GetID())) {
break;
}
#endif
OnRendererStarted(host->GetID());
break;
}
case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
content::RenderProcessHost* host =
content::Source<content::RenderProcessHost>(source).ptr();
OnRendererTerminated(host->GetID());
break;
}
case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
content::RenderProcessHost* host =
content::Source<content::RenderProcessHost>(source).ptr();
OnRendererTerminated(host->GetID());
break;
}
default:
NOTREACHED();
break;
}
}
} // namespace metrics