File: subprocess_metrics_provider.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (174 lines) | stat: -rw-r--r-- 7,203 bytes parent folder | download | duplicates (9)
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_