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