statistics_recorder.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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/macros.h"
  22. #include "base/memory/weak_ptr.h"
  23. #include "base/metrics/histogram_base.h"
  24. #include "base/metrics/record_histogram_checker.h"
  25. #include "base/strings/string_piece.h"
  26. #include "base/synchronization/lock.h"
  27. namespace base {
  28. class BucketRanges;
  29. class HistogramSnapshotManager;
  30. // In-memory recorder of usage statistics (aka metrics, aka histograms).
  31. //
  32. // All the public methods are static and act on a global recorder. This global
  33. // recorder is internally synchronized and all the static methods are thread
  34. // safe.
  35. //
  36. // StatisticsRecorder doesn't have any public constructor. For testing purpose,
  37. // you can create a temporary recorder using the factory method
  38. // CreateTemporaryForTesting(). This temporary recorder becomes the global one
  39. // until deleted. When this temporary recorder is deleted, it restores the
  40. // previous global one.
  41. class BASE_EXPORT StatisticsRecorder {
  42. public:
  43. // An interface class that allows the StatisticsRecorder to forcibly merge
  44. // histograms from providers when necessary.
  45. class HistogramProvider {
  46. public:
  47. // Merges all histogram information into the global versions.
  48. virtual void MergeHistogramDeltas() = 0;
  49. };
  50. typedef std::vector<HistogramBase*> Histograms;
  51. // Restores the previous global recorder.
  52. //
  53. // When several temporary recorders are created using
  54. // CreateTemporaryForTesting(), these recorders must be deleted in reverse
  55. // order of creation.
  56. //
  57. // This method is thread safe.
  58. //
  59. // Precondition: The recorder being deleted is the current global recorder.
  60. ~StatisticsRecorder();
  61. // Registers a provider of histograms that can be called to merge those into
  62. // the global recorder. Calls to ImportProvidedHistograms() will fetch from
  63. // registered providers.
  64. //
  65. // This method is thread safe.
  66. static void RegisterHistogramProvider(
  67. const WeakPtr<HistogramProvider>& provider);
  68. // Registers or adds a new histogram to the collection of statistics. If an
  69. // identically named histogram is already registered, then the argument
  70. // |histogram| will be deleted. The returned value is always the registered
  71. // histogram (either the argument, or the pre-existing registered histogram).
  72. //
  73. // This method is thread safe.
  74. static HistogramBase* RegisterOrDeleteDuplicate(HistogramBase* histogram);
  75. // Registers or adds a new BucketRanges. If an equivalent BucketRanges is
  76. // already registered, then the argument |ranges| will be deleted. The
  77. // returned value is always the registered BucketRanges (either the argument,
  78. // or the pre-existing one).
  79. //
  80. // This method is thread safe.
  81. static const BucketRanges* RegisterOrDeleteDuplicateRanges(
  82. const BucketRanges* ranges);
  83. // A method for appending histogram data to a string. Only histograms which
  84. // have |query| as a substring are written to |output| (an empty string will
  85. // process all registered histograms).
  86. //
  87. // This method is thread safe.
  88. static void WriteGraph(const std::string& query, std::string* output);
  89. // Returns the histograms with |verbosity_level| as the serialization
  90. // verbosity.
  91. //
  92. // This method is thread safe.
  93. static std::string ToJSON(JSONVerbosityLevel verbosity_level);
  94. // Gets existing histograms.
  95. //
  96. // The order of returned histograms is not guaranteed.
  97. //
  98. // Ownership of the individual histograms remains with the StatisticsRecorder.
  99. //
  100. // This method is thread safe.
  101. static Histograms GetHistograms();
  102. // Gets BucketRanges used by all histograms registered. The order of returned
  103. // BucketRanges is not guaranteed.
  104. //
  105. // This method is thread safe.
  106. static std::vector<const BucketRanges*> GetBucketRanges();
  107. // Finds a histogram by name. Matches the exact name. Returns a null pointer
  108. // if a matching histogram is not found.
  109. //
  110. // This method is thread safe.
  111. static HistogramBase* FindHistogram(base::StringPiece name);
  112. // Imports histograms from providers.
  113. //
  114. // This method must be called on the UI thread.
  115. static void ImportProvidedHistograms();
  116. // Snapshots all histograms via |snapshot_manager|. |flags_to_set| is used to
  117. // set flags for each histogram. |required_flags| is used to select
  118. // histograms to be recorded. Only histograms that have all the flags
  119. // specified by the argument will be chosen. If all histograms should be
  120. // recorded, set it to |Histogram::kNoFlags|.
  121. static void PrepareDeltas(bool include_persistent,
  122. HistogramBase::Flags flags_to_set,
  123. HistogramBase::Flags required_flags,
  124. HistogramSnapshotManager* snapshot_manager);
  125. using OnSampleCallback =
  126. base::RepeatingCallback<void(const char* /*=histogram_name*/,
  127. uint64_t /*=name_hash*/,
  128. HistogramBase::Sample)>;
  129. // Sets the callback to notify when a new sample is recorded on the histogram
  130. // referred to by |histogram_name|. Can be called before or after the
  131. // histogram is created. Returns whether the callback was successfully set.
  132. //
  133. // This method is thread safe.
  134. static bool SetCallback(const std::string& histogram_name,
  135. OnSampleCallback callback);
  136. // Clears any callback set on the histogram referred to by |histogram_name|.
  137. //
  138. // This method is thread safe.
  139. static void ClearCallback(const std::string& histogram_name);
  140. // Retrieves the callback for the histogram referred to by |histogram_name|,
  141. // or a null callback if no callback exists for this histogram.
  142. //
  143. // This method is thread safe.
  144. static OnSampleCallback FindCallback(const std::string& histogram_name);
  145. // Returns the number of known histograms.
  146. //
  147. // This method is thread safe.
  148. static size_t GetHistogramCount();
  149. // Initializes logging histograms with --v=1. Safe to call multiple times.
  150. // Is called from ctor but for browser it seems that it is more useful to
  151. // start logging after statistics recorder, so we need to init log-on-shutdown
  152. // later.
  153. //
  154. // This method is thread safe.
  155. static void InitLogOnShutdown();
  156. // Removes a histogram from the internal set of known ones. This can be
  157. // necessary during testing persistent histograms where the underlying
  158. // memory is being released.
  159. //
  160. // This method is thread safe.
  161. static void ForgetHistogramForTesting(base::StringPiece name);
  162. // Creates a temporary StatisticsRecorder object for testing purposes. All new
  163. // histograms will be registered in it until it is destructed or pushed aside
  164. // for the lifetime of yet another StatisticsRecorder object. The destruction
  165. // of the returned object will re-activate the previous one.
  166. // StatisticsRecorder objects must be deleted in the opposite order to which
  167. // they're created.
  168. //
  169. // This method is thread safe.
  170. static std::unique_ptr<StatisticsRecorder> CreateTemporaryForTesting()
  171. WARN_UNUSED_RESULT;
  172. // Sets the record checker for determining if a histogram should be recorded.
  173. // Record checker doesn't affect any already recorded histograms, so this
  174. // method must be called very early, before any threads have started.
  175. // Record checker methods can be called on any thread, so they shouldn't
  176. // mutate any state.
  177. static void SetRecordChecker(
  178. std::unique_ptr<RecordHistogramChecker> record_checker);
  179. // Checks if the given histogram should be recorded based on the
  180. // ShouldRecord() method of the record checker. If the record checker is not
  181. // set, returns true.
  182. //
  183. // This method is thread safe.
  184. static bool ShouldRecordHistogram(uint64_t histogram_hash);
  185. // Sorts histograms by name.
  186. static Histograms Sort(Histograms histograms);
  187. // Filters histograms by name. Only histograms which have |query| as a
  188. // substring in their name are kept. An empty query keeps all histograms.
  189. static Histograms WithName(Histograms histograms, const std::string& query);
  190. // Filters histograms by persistency. Only non-persistent histograms are kept.
  191. static Histograms NonPersistent(Histograms histograms);
  192. using GlobalSampleCallback = void (*)(const char* /*=histogram_name*/,
  193. uint64_t /*=name_hash*/,
  194. HistogramBase::Sample);
  195. // Installs a global callback which will be called for every added
  196. // histogram sample. The given callback is a raw function pointer in order
  197. // to be accessed lock-free and can be called on any thread.
  198. static void SetGlobalSampleCallback(
  199. const GlobalSampleCallback& global_sample_callback);
  200. // Returns the global callback, if any, that should be called every time a
  201. // histogram sample is added.
  202. static GlobalSampleCallback global_sample_callback() {
  203. return global_sample_callback_.load(std::memory_order_relaxed);
  204. }
  205. // Returns whether there's either a global histogram callback set,
  206. // or if any individual histograms have callbacks set. Used for early return
  207. // when histogram samples are added.
  208. static bool have_active_callbacks() {
  209. return have_active_callbacks_.load(std::memory_order_relaxed);
  210. }
  211. private:
  212. typedef std::vector<WeakPtr<HistogramProvider>> HistogramProviders;
  213. typedef std::unordered_map<StringPiece, HistogramBase*, StringPieceHash>
  214. HistogramMap;
  215. // We keep a map of callbacks to histograms, so that as histograms are
  216. // created, we can set the callback properly.
  217. typedef std::unordered_map<std::string, OnSampleCallback> CallbackMap;
  218. struct BucketRangesHash {
  219. size_t operator()(const BucketRanges* a) const;
  220. };
  221. struct BucketRangesEqual {
  222. bool operator()(const BucketRanges* a, const BucketRanges* b) const;
  223. };
  224. typedef std::
  225. unordered_set<const BucketRanges*, BucketRangesHash, BucketRangesEqual>
  226. RangesMap;
  227. friend class StatisticsRecorderTest;
  228. FRIEND_TEST_ALL_PREFIXES(StatisticsRecorderTest, IterationTest);
  229. // Initializes the global recorder if it doesn't already exist. Safe to call
  230. // multiple times.
  231. //
  232. // Precondition: The global lock is already acquired.
  233. static void EnsureGlobalRecorderWhileLocked();
  234. // Gets histogram providers.
  235. //
  236. // This method is thread safe.
  237. static HistogramProviders GetHistogramProviders();
  238. // Imports histograms from global persistent memory.
  239. //
  240. // Precondition: The global lock must not be held during this call.
  241. static void ImportGlobalPersistentHistograms();
  242. // Constructs a new StatisticsRecorder and sets it as the current global
  243. // recorder.
  244. //
  245. // Precondition: The global lock is already acquired.
  246. StatisticsRecorder();
  247. // Initialize implementation but without lock. Caller should guard
  248. // StatisticsRecorder by itself if needed (it isn't in unit tests).
  249. //
  250. // Precondition: The global lock is already acquired.
  251. static void InitLogOnShutdownWhileLocked();
  252. HistogramMap histograms_;
  253. CallbackMap callbacks_;
  254. RangesMap ranges_;
  255. HistogramProviders providers_;
  256. std::unique_ptr<RecordHistogramChecker> record_checker_;
  257. // Previous global recorder that existed when this one was created.
  258. StatisticsRecorder* previous_ = nullptr;
  259. // Global lock for internal synchronization.
  260. static LazyInstance<Lock>::Leaky lock_;
  261. // Current global recorder. This recorder is used by static methods. When a
  262. // new global recorder is created by CreateTemporaryForTesting(), then the
  263. // previous global recorder is referenced by top_->previous_.
  264. static StatisticsRecorder* top_;
  265. // Tracks whether InitLogOnShutdownWhileLocked() has registered a logging
  266. // function that will be called when the program finishes.
  267. static bool is_vlog_initialized_;
  268. // Track whether there are active histogram callbacks present.
  269. static std::atomic<bool> have_active_callbacks_;
  270. // Stores a raw callback which should be called on any every histogram sample
  271. // which gets added.
  272. static std::atomic<GlobalSampleCallback> global_sample_callback_;
  273. DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
  274. };
  275. } // namespace base
  276. #endif // BASE_METRICS_STATISTICS_RECORDER_H_