statistics_recorder.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // StatisticsRecorder holds all Histograms and BucketRanges that are used by
  5. // Histograms in the system. It provides a general place for
  6. // Histograms/BucketRanges to register, and supports a global API for accessing
  7. // (i.e., dumping, or graphing) the data.
  8. #ifndef BASE_METRICS_STATISTICS_RECORDER_H_
  9. #define BASE_METRICS_STATISTICS_RECORDER_H_
  10. #include <stdint.h>
  11. #include <atomic>
  12. #include <memory>
  13. #include <string>
  14. #include <unordered_map>
  15. #include <unordered_set>
  16. #include <vector>
  17. #include "base/base_export.h"
  18. #include "base/callback.h"
  19. #include "base/gtest_prod_util.h"
  20. #include "base/lazy_instance.h"
  21. #include "base/memory/raw_ptr.h"
  22. #include "base/memory/weak_ptr.h"
  23. #include "base/metrics/histogram_base.h"
  24. #include "base/metrics/ranges_manager.h"
  25. #include "base/metrics/record_histogram_checker.h"
  26. #include "base/observer_list_threadsafe.h"
  27. #include "base/strings/string_piece.h"
  28. #include "base/synchronization/lock.h"
  29. #include "base/types/pass_key.h"
  30. namespace base {
  31. class BucketRanges;
  32. class HistogramSnapshotManager;
  33. // In-memory recorder of usage statistics (aka metrics, aka histograms).
  34. //
  35. // All the public methods are static and act on a global recorder. This global
  36. // recorder is internally synchronized and all the static methods are thread
  37. // safe. This is intended to only be run/used in the browser process.
  38. //
  39. // StatisticsRecorder doesn't have any public constructor. For testing purpose,
  40. // you can create a temporary recorder using the factory method
  41. // CreateTemporaryForTesting(). This temporary recorder becomes the global one
  42. // until deleted. When this temporary recorder is deleted, it restores the
  43. // previous global one.
  44. class BASE_EXPORT StatisticsRecorder {
  45. public:
  46. // An interface class that allows the StatisticsRecorder to forcibly merge
  47. // histograms from providers when necessary.
  48. class HistogramProvider {
  49. public:
  50. // Merges all histogram information into the global versions.
  51. virtual void MergeHistogramDeltas() = 0;
  52. };
  53. // OnSampleCallback is a convenient callback type that provides information
  54. // about a histogram sample. This is used in conjunction with
  55. // ScopedHistogramSampleObserver to get notified when a sample is collected.
  56. using OnSampleCallback =
  57. base::RepeatingCallback<void(const char* /*=histogram_name*/,
  58. uint64_t /*=name_hash*/,
  59. HistogramBase::Sample)>;
  60. // An observer that gets notified whenever a new sample is recorded for a
  61. // particular histogram. Clients only need to construct it with the histogram
  62. // name and the callback to be invoked. The class starts observing on
  63. // construction and removes itself from the observer list on destruction. The
  64. // clients are always notified on the same sequence in which they were
  65. // registered.
  66. class BASE_EXPORT ScopedHistogramSampleObserver {
  67. public:
  68. // Constructor. Called with the desired histogram name and the callback to
  69. // be invoked when a sample is recorded.
  70. explicit ScopedHistogramSampleObserver(const std::string& histogram_name,
  71. OnSampleCallback callback);
  72. ~ScopedHistogramSampleObserver();
  73. private:
  74. friend class StatisticsRecorder;
  75. // Runs the callback.
  76. void RunCallback(const char* histogram_name,
  77. uint64_t name_hash,
  78. HistogramBase::Sample sample);
  79. // The name of the histogram to observe.
  80. const std::string histogram_name_;
  81. // The client supplied callback that is invoked when the histogram sample is
  82. // collected.
  83. const OnSampleCallback callback_;
  84. };
  85. typedef std::vector<HistogramBase*> Histograms;
  86. StatisticsRecorder(const StatisticsRecorder&) = delete;
  87. StatisticsRecorder& operator=(const StatisticsRecorder&) = delete;
  88. // Restores the previous global recorder.
  89. //
  90. // When several temporary recorders are created using
  91. // CreateTemporaryForTesting(), these recorders must be deleted in reverse
  92. // order of creation.
  93. //
  94. // This method is thread safe.
  95. //
  96. // Precondition: The recorder being deleted is the current global recorder.
  97. ~StatisticsRecorder();
  98. // Registers a provider of histograms that can be called to merge those into
  99. // the global recorder. Calls to ImportProvidedHistograms() will fetch from
  100. // registered providers.
  101. //
  102. // This method is thread safe.
  103. static void RegisterHistogramProvider(
  104. const WeakPtr<HistogramProvider>& provider);
  105. // Registers or adds a new histogram to the collection of statistics. If an
  106. // identically named histogram is already registered, then the argument
  107. // |histogram| will be deleted. The returned value is always the registered
  108. // histogram (either the argument, or the pre-existing registered histogram).
  109. //
  110. // This method is thread safe.
  111. static HistogramBase* RegisterOrDeleteDuplicate(HistogramBase* histogram);
  112. // Registers or adds a new BucketRanges. If an equivalent BucketRanges is
  113. // already registered, then the argument |ranges| will be deleted. The
  114. // returned value is always the registered BucketRanges (either the argument,
  115. // or the pre-existing one).
  116. //
  117. // This method is thread safe.
  118. static const BucketRanges* RegisterOrDeleteDuplicateRanges(
  119. const BucketRanges* ranges);
  120. // A method for appending histogram data to a string. Only histograms which
  121. // have |query| as a substring are written to |output| (an empty string will
  122. // process all registered histograms).
  123. //
  124. // This method is thread safe.
  125. static void WriteGraph(const std::string& query, std::string* output);
  126. // Returns the histograms with |verbosity_level| as the serialization
  127. // verbosity.
  128. //
  129. // This method is thread safe.
  130. static std::string ToJSON(JSONVerbosityLevel verbosity_level);
  131. // Gets existing histograms.
  132. //
  133. // The order of returned histograms is not guaranteed.
  134. //
  135. // Ownership of the individual histograms remains with the StatisticsRecorder.
  136. //
  137. // This method is thread safe.
  138. static Histograms GetHistograms();
  139. // Gets BucketRanges used by all histograms registered. The order of returned
  140. // BucketRanges is not guaranteed.
  141. //
  142. // This method is thread safe.
  143. static std::vector<const BucketRanges*> GetBucketRanges();
  144. // Finds a histogram by name. Matches the exact name. Returns a null pointer
  145. // if a matching histogram is not found.
  146. //
  147. // This method is thread safe.
  148. static HistogramBase* FindHistogram(base::StringPiece name);
  149. // Imports histograms from providers.
  150. //
  151. // This method must be called on the UI thread.
  152. static void ImportProvidedHistograms();
  153. // Snapshots all histograms via |snapshot_manager|. |include_persistent|
  154. // determines whether histograms held in persistent storage are
  155. // snapshotted. |flags_to_set| is used to set flags for each histogram.
  156. // |required_flags| is used to select which histograms to record. Only
  157. // histograms with all required flags are selected. If all histograms should
  158. // be recorded, use |Histogram::kNoFlags| as the required flag.
  159. static void PrepareDeltas(bool include_persistent,
  160. HistogramBase::Flags flags_to_set,
  161. HistogramBase::Flags required_flags,
  162. HistogramSnapshotManager* snapshot_manager);
  163. // Retrieves and runs the list of callbacks for the histogram referred to by
  164. // |histogram_name|, if any.
  165. //
  166. // This method is thread safe.
  167. static void FindAndRunHistogramCallbacks(base::PassKey<HistogramBase>,
  168. const char* histogram_name,
  169. uint64_t name_hash,
  170. HistogramBase::Sample sample);
  171. // Returns the number of known histograms.
  172. //
  173. // This method is thread safe.
  174. static size_t GetHistogramCount();
  175. // Initializes logging histograms with --v=1. Safe to call multiple times.
  176. // Is called from ctor but for browser it seems that it is more useful to
  177. // start logging after statistics recorder, so we need to init log-on-shutdown
  178. // later.
  179. //
  180. // This method is thread safe.
  181. static void InitLogOnShutdown();
  182. // Removes a histogram from the internal set of known ones. This can be
  183. // necessary during testing persistent histograms where the underlying
  184. // memory is being released.
  185. //
  186. // This method is thread safe.
  187. static void ForgetHistogramForTesting(base::StringPiece name);
  188. // Creates a temporary StatisticsRecorder object for testing purposes. All new
  189. // histograms will be registered in it until it is destructed or pushed aside
  190. // for the lifetime of yet another StatisticsRecorder object. The destruction
  191. // of the returned object will re-activate the previous one.
  192. // StatisticsRecorder objects must be deleted in the opposite order to which
  193. // they're created.
  194. //
  195. // This method is thread safe.
  196. [[nodiscard]] static std::unique_ptr<StatisticsRecorder>
  197. CreateTemporaryForTesting();
  198. // Sets the record checker for determining if a histogram should be recorded.
  199. // Record checker doesn't affect any already recorded histograms, so this
  200. // method must be called very early, before any threads have started.
  201. // Record checker methods can be called on any thread, so they shouldn't
  202. // mutate any state.
  203. static void SetRecordChecker(
  204. std::unique_ptr<RecordHistogramChecker> record_checker);
  205. // Checks if the given histogram should be recorded based on the
  206. // ShouldRecord() method of the record checker. If the record checker is not
  207. // set, returns true.
  208. // |histogram_hash| corresponds to the result of HashMetricNameAs32Bits().
  209. //
  210. // This method is thread safe.
  211. static bool ShouldRecordHistogram(uint32_t histogram_hash);
  212. // Sorts histograms by name.
  213. static Histograms Sort(Histograms histograms);
  214. // Filters histograms by name. Only histograms which have |query| as a
  215. // substring in their name are kept. An empty query keeps all histograms.
  216. static Histograms WithName(Histograms histograms, const std::string& query);
  217. // Filters histograms by persistency. Only non-persistent histograms are kept.
  218. static Histograms NonPersistent(Histograms histograms);
  219. using GlobalSampleCallback = void (*)(const char* /*=histogram_name*/,
  220. uint64_t /*=name_hash*/,
  221. HistogramBase::Sample);
  222. // Installs a global callback which will be called for every added
  223. // histogram sample. The given callback is a raw function pointer in order
  224. // to be accessed lock-free and can be called on any thread.
  225. static void SetGlobalSampleCallback(
  226. const GlobalSampleCallback& global_sample_callback);
  227. // Returns the global callback, if any, that should be called every time a
  228. // histogram sample is added.
  229. static GlobalSampleCallback global_sample_callback() {
  230. return global_sample_callback_.load(std::memory_order_relaxed);
  231. }
  232. // Returns whether there's either a global histogram callback set,
  233. // or if any individual histograms have callbacks set. Used for early return
  234. // when histogram samples are added.
  235. static bool have_active_callbacks() {
  236. return have_active_callbacks_.load(std::memory_order_relaxed);
  237. }
  238. private:
  239. // Adds an observer to be notified when a new sample is recorded on the
  240. // histogram referred to by |histogram_name|. Can be called before or after
  241. // the histogram is created.
  242. //
  243. // This method is thread safe.
  244. static void AddHistogramSampleObserver(
  245. const std::string& histogram_name,
  246. ScopedHistogramSampleObserver* observer);
  247. // Clears the given |observer| set on the histogram referred to by
  248. // |histogram_name|.
  249. //
  250. // This method is thread safe.
  251. static void RemoveHistogramSampleObserver(
  252. const std::string& histogram_name,
  253. ScopedHistogramSampleObserver* observer);
  254. typedef std::vector<WeakPtr<HistogramProvider>> HistogramProviders;
  255. typedef std::unordered_map<StringPiece, HistogramBase*, StringPieceHash>
  256. HistogramMap;
  257. // A map of histogram name to registered observers. If the histogram isn't
  258. // created yet, the observers will be added after creation.
  259. using HistogramSampleObserverList =
  260. base::ObserverListThreadSafe<ScopedHistogramSampleObserver>;
  261. typedef std::unordered_map<std::string,
  262. scoped_refptr<HistogramSampleObserverList>>
  263. ObserverMap;
  264. friend class StatisticsRecorderTest;
  265. FRIEND_TEST_ALL_PREFIXES(StatisticsRecorderTest, IterationTest);
  266. // Initializes the global recorder if it doesn't already exist. Safe to call
  267. // multiple times.
  268. //
  269. // Precondition: The global lock is already acquired.
  270. static void EnsureGlobalRecorderWhileLocked();
  271. // Gets histogram providers.
  272. //
  273. // This method is thread safe.
  274. static HistogramProviders GetHistogramProviders();
  275. // Imports histograms from global persistent memory.
  276. //
  277. // Precondition: The global lock must not be held during this call.
  278. static void ImportGlobalPersistentHistograms();
  279. // Constructs a new StatisticsRecorder and sets it as the current global
  280. // recorder.
  281. //
  282. // This singleton instance should be started during the single-threaded
  283. // portion of startup and hence it is not thread safe. It initializes globals
  284. // to provide support for all future calls.
  285. //
  286. // Precondition: The global lock is already acquired.
  287. StatisticsRecorder();
  288. // Initialize implementation but without lock. Caller should guard
  289. // StatisticsRecorder by itself if needed (it isn't in unit tests).
  290. //
  291. // Precondition: The global lock is already acquired.
  292. static void InitLogOnShutdownWhileLocked();
  293. HistogramMap histograms_;
  294. ObserverMap observers_;
  295. HistogramProviders providers_;
  296. RangesManager ranges_manager_;
  297. std::unique_ptr<RecordHistogramChecker> record_checker_;
  298. // Previous global recorder that existed when this one was created.
  299. raw_ptr<StatisticsRecorder> previous_ = nullptr;
  300. // Global lock for internal synchronization.
  301. static LazyInstance<Lock>::Leaky lock_;
  302. // Current global recorder. This recorder is used by static methods. When a
  303. // new global recorder is created by CreateTemporaryForTesting(), then the
  304. // previous global recorder is referenced by top_->previous_.
  305. static StatisticsRecorder* top_;
  306. // Tracks whether InitLogOnShutdownWhileLocked() has registered a logging
  307. // function that will be called when the program finishes.
  308. static bool is_vlog_initialized_;
  309. // Track whether there are active histogram callbacks present.
  310. static std::atomic<bool> have_active_callbacks_;
  311. // Stores a raw callback which should be called on any every histogram sample
  312. // which gets added.
  313. static std::atomic<GlobalSampleCallback> global_sample_callback_;
  314. };
  315. } // namespace base
  316. #endif // BASE_METRICS_STATISTICS_RECORDER_H_