• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 // StatisticsRecorder holds all Histograms and BucketRanges that are used by
6 // Histograms in the system. It provides a general place for
7 // Histograms/BucketRanges to register, and supports a global API for accessing
8 // (i.e., dumping, or graphing) the data.
9 
10 #ifndef BASE_METRICS_STATISTICS_RECORDER_H_
11 #define BASE_METRICS_STATISTICS_RECORDER_H_
12 
13 #include <stdint.h>
14 
15 #include <list>
16 #include <map>
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 #include "base/base_export.h"
22 #include "base/callback.h"
23 #include "base/gtest_prod_util.h"
24 #include "base/lazy_instance.h"
25 #include "base/macros.h"
26 #include "base/metrics/histogram_base.h"
27 #include "base/strings/string_piece.h"
28 
29 class SubprocessMetricsProviderTest;
30 
31 namespace base {
32 
33 class BucketRanges;
34 class Lock;
35 
36 class BASE_EXPORT StatisticsRecorder {
37  public:
38   // A class used as a key for the histogram map below. It always references
39   // a string owned outside of this class, likely in the value of the map.
40   class StringKey : public StringPiece {
41    public:
42     // Constructs the StringKey using various sources. The source must live
43     // at least as long as the created object.
StringKey(const std::string & str)44     StringKey(const std::string& str) : StringPiece(str) {}
StringKey(StringPiece str)45     StringKey(StringPiece str) : StringPiece(str) {}
46 
47     // Though StringPiece is better passed by value than by reference, in
48     // this case it's being passed many times and likely already been stored
49     // in memory (not just registers) so the benefit of pass-by-value is
50     // negated.
51     bool operator<(const StringKey& rhs) const {
52       // Since order is unimportant in the map and string comparisons can be
53       // slow, use the length as the primary sort value.
54       if (length() < rhs.length())
55         return true;
56       if (length() > rhs.length())
57         return false;
58 
59       // Fall back to an actual string comparison. The lengths are the same
60       // so a simple memory-compare is sufficient. This is slightly more
61       // efficient than calling operator<() for StringPiece which would
62       // again have to check lengths before calling wordmemcmp().
63       return wordmemcmp(data(), rhs.data(), length()) < 0;
64     }
65   };
66 
67   typedef std::map<StringKey, HistogramBase*> HistogramMap;
68   typedef std::vector<HistogramBase*> Histograms;
69 
70   // A class for iterating over the histograms held within this global resource.
71   class BASE_EXPORT HistogramIterator {
72    public:
73     HistogramIterator(const HistogramMap::iterator& iter,
74                       bool include_persistent);
75     HistogramIterator(const HistogramIterator& rhs);  // Must be copyable.
76     ~HistogramIterator();
77 
78     HistogramIterator& operator++();
79     HistogramIterator operator++(int) {
80       HistogramIterator tmp(*this);
81       operator++();
82       return tmp;
83     }
84 
85     bool operator==(const HistogramIterator& rhs) const {
86       return iter_ == rhs.iter_;
87     }
88     bool operator!=(const HistogramIterator& rhs) const {
89       return iter_ != rhs.iter_;
90     }
91     HistogramBase* operator*() { return iter_->second; }
92 
93    private:
94     HistogramMap::iterator iter_;
95     const bool include_persistent_;
96   };
97 
98   ~StatisticsRecorder();
99 
100   // Initializes the StatisticsRecorder system. Safe to call multiple times.
101   static void Initialize();
102 
103   // Find out if histograms can now be registered into our list.
104   static bool IsActive();
105 
106   // Register, or add a new histogram to the collection of statistics. If an
107   // identically named histogram is already registered, then the argument
108   // |histogram| will deleted.  The returned value is always the registered
109   // histogram (either the argument, or the pre-existing registered histogram).
110   static HistogramBase* RegisterOrDeleteDuplicate(HistogramBase* histogram);
111 
112   // Register, or add a new BucketRanges. If an identically BucketRanges is
113   // already registered, then the argument |ranges| will deleted. The returned
114   // value is always the registered BucketRanges (either the argument, or the
115   // pre-existing one).
116   static const BucketRanges* RegisterOrDeleteDuplicateRanges(
117       const BucketRanges* ranges);
118 
119   // Methods for appending histogram data to a string.  Only histograms which
120   // have |query| as a substring are written to |output| (an empty string will
121   // process all registered histograms).
122   static void WriteHTMLGraph(const std::string& query, std::string* output);
123   static void WriteGraph(const std::string& query, std::string* output);
124 
125   // Returns the histograms with |query| as a substring as JSON text (an empty
126   // |query| will process all registered histograms).
127   static std::string ToJSON(const std::string& query);
128 
129   // Method for extracting histograms which were marked for use by UMA.
130   static void GetHistograms(Histograms* output);
131 
132   // Method for extracting BucketRanges used by all histograms registered.
133   static void GetBucketRanges(std::vector<const BucketRanges*>* output);
134 
135   // Find a histogram by name. It matches the exact name. This method is thread
136   // safe.  It returns NULL if a matching histogram is not found.
137   static HistogramBase* FindHistogram(base::StringPiece name);
138 
139   // Support for iterating over known histograms.
140   static HistogramIterator begin(bool include_persistent);
141   static HistogramIterator end();
142 
143   // GetSnapshot copies some of the pointers to registered histograms into the
144   // caller supplied vector (Histograms). Only histograms which have |query| as
145   // a substring are copied (an empty string will process all registered
146   // histograms).
147   static void GetSnapshot(const std::string& query, Histograms* snapshot);
148 
149   typedef base::Callback<void(HistogramBase::Sample)> OnSampleCallback;
150 
151   // SetCallback sets the callback to notify when a new sample is recorded on
152   // the histogram referred to by |histogram_name|. The call to this method can
153   // be be done before or after the histogram is created. This method is thread
154   // safe. The return value is whether or not the callback was successfully set.
155   static bool SetCallback(const std::string& histogram_name,
156                           const OnSampleCallback& callback);
157 
158   // ClearCallback clears any callback set on the histogram referred to by
159   // |histogram_name|. This method is thread safe.
160   static void ClearCallback(const std::string& histogram_name);
161 
162   // FindCallback retrieves the callback for the histogram referred to by
163   // |histogram_name|, or a null callback if no callback exists for this
164   // histogram. This method is thread safe.
165   static OnSampleCallback FindCallback(const std::string& histogram_name);
166 
167   // Returns the number of known histograms.
168   static size_t GetHistogramCount();
169 
170   // Initializes logging histograms with --v=1. Safe to call multiple times.
171   // Is called from ctor but for browser it seems that it is more useful to
172   // start logging after statistics recorder, so we need to init log-on-shutdown
173   // later.
174   static void InitLogOnShutdown();
175 
176   // Removes a histogram from the internal set of known ones. This can be
177   // necessary during testing persistent histograms where the underlying
178   // memory is being released.
179   static void ForgetHistogramForTesting(base::StringPiece name);
180 
181   // Creates a local StatisticsRecorder object for testing purposes. All new
182   // histograms will be registered in it until it is destructed or pushed
183   // aside for the lifetime of yet another SR object. The destruction of the
184   // returned object will re-activate the previous one. Always release SR
185   // objects in the opposite order to which they're created.
186   static std::unique_ptr<StatisticsRecorder> CreateTemporaryForTesting()
187       WARN_UNUSED_RESULT;
188 
189   // Resets any global instance of the statistics-recorder that was created
190   // by a call to Initialize().
191   static void UninitializeForTesting();
192 
193  private:
194   // We keep a map of callbacks to histograms, so that as histograms are
195   // created, we can set the callback properly.
196   typedef std::map<std::string, OnSampleCallback> CallbackMap;
197 
198   // We keep all |bucket_ranges_| in a map, from checksum to a list of
199   // |bucket_ranges_|.  Checksum is calculated from the |ranges_| in
200   // |bucket_ranges_|.
201   typedef std::map<uint32_t, std::list<const BucketRanges*>*> RangesMap;
202 
203   friend struct DefaultLazyInstanceTraits<StatisticsRecorder>;
204   friend class StatisticsRecorderTest;
205 
206   // Imports histograms from global persistent memory. The global lock must
207   // not be held during this call.
208   static void ImportGlobalPersistentHistograms();
209 
210   // The constructor just initializes static members. Usually client code should
211   // use Initialize to do this. But in test code, you can friend this class and
212   // call the constructor to get a clean StatisticsRecorder.
213   StatisticsRecorder();
214 
215   // Initialize implementation but without lock. Caller should guard
216   // StatisticsRecorder by itself if needed (it isn't in unit tests).
217   void InitLogOnShutdownWithoutLock();
218 
219   // These are copies of everything that existed when the (test) Statistics-
220   // Recorder was created. The global ones have to be moved aside to create a
221   // clean environment.
222   std::unique_ptr<HistogramMap> existing_histograms_;
223   std::unique_ptr<CallbackMap> existing_callbacks_;
224   std::unique_ptr<RangesMap> existing_ranges_;
225 
226   bool vlog_initialized_ = false;
227 
228   static void Reset();
229   static void DumpHistogramsToVlog(void* instance);
230 
231   static HistogramMap* histograms_;
232   static CallbackMap* callbacks_;
233   static RangesMap* ranges_;
234 
235   // Lock protects access to above maps.
236   static base::Lock* lock_;
237 
238   DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
239 };
240 
241 }  // namespace base
242 
243 #endif  // BASE_METRICS_STATISTICS_RECORDER_H_
244