1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_METRICS_CONTENT_SUBPROCESS_METRICS_PROVIDER_H_
#define COMPONENTS_METRICS_CONTENT_SUBPROCESS_METRICS_PROVIDER_H_
#include <map>
#include <memory>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/statistics_recorder.h"
#include "base/scoped_multi_source_observation.h"
#include "base/task/task_runner.h"
#include "base/threading/thread_checker.h"
#include "components/metrics/metrics_provider.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_creation_observer.h"
#include "content/public/browser/render_process_host_observer.h"
namespace base {
class PersistentHistogramAllocator;
}
namespace metrics {
// SubprocessMetricsProvider gathers and merges histograms stored in shared
// memory segments between processes. Merging occurs when a process exits,
// when metrics are being collected for upload, or when something else needs
// combined metrics (such as the chrome://histograms page).
// TODO(crbug.com/40213327): Do not inherit MetricsProvider.
class SubprocessMetricsProvider
: public MetricsProvider,
public base::StatisticsRecorder::HistogramProvider,
public content::BrowserChildProcessObserver,
public content::RenderProcessHostCreationObserver,
public content::RenderProcessHostObserver {
public:
SubprocessMetricsProvider(const SubprocessMetricsProvider&) = delete;
SubprocessMetricsProvider& operator=(const SubprocessMetricsProvider&) =
delete;
// Creates the global instance. Returns false if the instance already exists.
static bool CreateInstance();
// Returns the global instance.
static SubprocessMetricsProvider* GetInstance();
// Merge histograms for all subprocesses. This is used by tests that don't
// have access to the internal instance of this class.
static void MergeHistogramDeltasForTesting(
bool async = false,
base::OnceClosure done_callback = base::DoNothing());
// Indicates subprocess to be monitored with unique id for later reference.
// Metrics reporting will read histograms from it and upload them to UMA.
void RegisterSubprocessAllocator(
int id,
std::unique_ptr<base::PersistentHistogramAllocator> allocator);
// Indicates that a subprocess has exited and is thus finished with the
// allocator it was using.
void DeregisterSubprocessAllocator(int id);
private:
friend class SubprocessMetricsProviderTest;
// Wrapper to add reference counting to an allocator so that it is only
// released it when all tasks have finished with it. Note that this is
// RefCounted and not RefCountedThreadSafe, meaning that references should
// only be created/destroyed on the same sequence (the implementation has
// DCHECKs to enforce this).
class RefCountedAllocator : public base::RefCounted<RefCountedAllocator> {
public:
explicit RefCountedAllocator(
std::unique_ptr<base::PersistentHistogramAllocator> allocator);
RefCountedAllocator(const RefCountedAllocator& other) = delete;
RefCountedAllocator& operator=(const RefCountedAllocator& other) = delete;
base::PersistentHistogramAllocator* allocator() { return allocator_.get(); }
private:
friend class base::RefCounted<RefCountedAllocator>;
~RefCountedAllocator();
std::unique_ptr<base::PersistentHistogramAllocator> allocator_;
};
// The global instance should be accessed through Get().
SubprocessMetricsProvider();
// This should never be deleted, as it handles subprocess metrics for the
// whole lifetime of the browser process.
~SubprocessMetricsProvider() override;
// base::StatisticsRecorder::HistogramProvider:
void MergeHistogramDeltas(bool async,
base::OnceClosure done_callback) override;
// content::BrowserChildProcessObserver:
void BrowserChildProcessLaunchedAndConnected(
const content::ChildProcessData& data) override;
void BrowserChildProcessHostDisconnected(
const content::ChildProcessData& data) override;
void BrowserChildProcessCrashed(
const content::ChildProcessData& data,
const content::ChildProcessTerminationInfo& info) override;
void BrowserChildProcessKilled(
const content::ChildProcessData& data,
const content::ChildProcessTerminationInfo& info) override;
// content::RenderProcessHostCreationObserver:
void OnRenderProcessHostCreated(content::RenderProcessHost* host) override;
// content::RenderProcessHostObserver:
void RenderProcessReady(content::RenderProcessHost* host) override;
void RenderProcessExited(
content::RenderProcessHost* host,
const content::ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
// Re-creates |sequenced_task_runner_|. Used for testing.
void RecreateTaskRunnerForTesting();
// Merges all histograms of |allocator| to the global StatisticsRecorder. This
// is called periodically during UMA metrics collection (if enabled) and
// possibly on-demand for other purposes. May be called on a background
// thread.
static void MergeHistogramDeltasFromAllocator(int id,
RefCountedAllocator* allocator);
// Merges all histograms of the |allocators| to the global StatisticsRecorder.
// Does not have any form of ownership on the allocators. May be called on a
// background thread.
using AllocatorByIdMap = std::map<int, scoped_refptr<RefCountedAllocator>>;
static void MergeHistogramDeltasFromAllocators(AllocatorByIdMap* allocators);
// Callback for when MergeHistogramDeltasFromAllocator() is called in a
// background thread.
static void OnMergeHistogramDeltasFromAllocator(
scoped_refptr<RefCountedAllocator> allocator);
// Callback for when MergeHistogramDeltasFromAllocators() is called in a
// background thread.
static void OnMergeHistogramDeltasFromAllocators(
std::unique_ptr<AllocatorByIdMap> allocators,
base::OnceClosure done_callback);
THREAD_CHECKER(thread_checker_);
// All of the shared-persistent-allocators for known sub-processes.
AllocatorByIdMap allocators_by_id_;
// Track all observed render processes to un-observe them on exit.
// TODO(crbug.com/40213327): Since this class should be leaky, it is not
// semantically correct to have a "scoped" member field here. Replace this
// with something like a set.
base::ScopedMultiSourceObservation<content::RenderProcessHost,
content::RenderProcessHostObserver>
scoped_observations_{this};
// Used to asynchronously merge metrics from subprocesses that have exited.
scoped_refptr<base::TaskRunner> task_runner_;
base::WeakPtrFactory<SubprocessMetricsProvider> weak_ptr_factory_{this};
};
} // namespace metrics
#endif // COMPONENTS_METRICS_CONTENT_SUBPROCESS_METRICS_PROVIDER_H_
|