|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // StatisticsRecorder holds all Histograms and BucketRanges that are used by | 
|  | // Histograms in the system. It provides a general place for | 
|  | // Histograms/BucketRanges to register, and supports a global API for accessing | 
|  | // (i.e., dumping, or graphing) the data. | 
|  |  | 
|  | #ifndef BASE_METRICS_STATISTICS_RECORDER_H_ | 
|  | #define BASE_METRICS_STATISTICS_RECORDER_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <unordered_map> | 
|  | #include <unordered_set> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/base_export.h" | 
|  | #include "base/callback.h" | 
|  | #include "base/gtest_prod_util.h" | 
|  | #include "base/lazy_instance.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/metrics/histogram_base.h" | 
|  | #include "base/metrics/record_histogram_checker.h" | 
|  | #include "base/strings/string_piece.h" | 
|  | #include "base/synchronization/lock.h" | 
|  | #include "starboard/types.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | class BucketRanges; | 
|  | class HistogramSnapshotManager; | 
|  |  | 
|  | // In-memory recorder of usage statistics (aka metrics, aka histograms). | 
|  | // | 
|  | // All the public methods are static and act on a global recorder. This global | 
|  | // recorder is internally synchronized and all the static methods are thread | 
|  | // safe. | 
|  | // | 
|  | // StatisticsRecorder doesn't have any public constructor. For testing purpose, | 
|  | // you can create a temporary recorder using the factory method | 
|  | // CreateTemporaryForTesting(). This temporary recorder becomes the global one | 
|  | // until deleted. When this temporary recorder is deleted, it restores the | 
|  | // previous global one. | 
|  | class BASE_EXPORT StatisticsRecorder { | 
|  | public: | 
|  | // An interface class that allows the StatisticsRecorder to forcibly merge | 
|  | // histograms from providers when necessary. | 
|  | class HistogramProvider { | 
|  | public: | 
|  | // Merges all histogram information into the global versions. | 
|  | virtual void MergeHistogramDeltas() = 0; | 
|  | }; | 
|  |  | 
|  | typedef std::vector<HistogramBase*> Histograms; | 
|  |  | 
|  | // Restores the previous global recorder. | 
|  | // | 
|  | // When several temporary recorders are created using | 
|  | // CreateTemporaryForTesting(), these recorders must be deleted in reverse | 
|  | // order of creation. | 
|  | // | 
|  | // This method is thread safe. | 
|  | // | 
|  | // Precondition: The recorder being deleted is the current global recorder. | 
|  | ~StatisticsRecorder(); | 
|  |  | 
|  | // Registers a provider of histograms that can be called to merge those into | 
|  | // the global recorder. Calls to ImportProvidedHistograms() will fetch from | 
|  | // registered providers. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static void RegisterHistogramProvider( | 
|  | const WeakPtr<HistogramProvider>& provider); | 
|  |  | 
|  | // Registers or adds a new histogram to the collection of statistics. If an | 
|  | // identically named histogram is already registered, then the argument | 
|  | // |histogram| will be deleted. The returned value is always the registered | 
|  | // histogram (either the argument, or the pre-existing registered histogram). | 
|  | // | 
|  | // This method is thread safe. | 
|  | static HistogramBase* RegisterOrDeleteDuplicate(HistogramBase* histogram); | 
|  |  | 
|  | // Registers or adds a new BucketRanges. If an equivalent BucketRanges is | 
|  | // already registered, then the argument |ranges| will be deleted. The | 
|  | // returned value is always the registered BucketRanges (either the argument, | 
|  | // or the pre-existing one). | 
|  | // | 
|  | // This method is thread safe. | 
|  | static const BucketRanges* RegisterOrDeleteDuplicateRanges( | 
|  | const BucketRanges* ranges); | 
|  |  | 
|  | // Methods for appending histogram data to a string.  Only histograms which | 
|  | // have |query| as a substring are written to |output| (an empty string will | 
|  | // process all registered histograms). | 
|  | // | 
|  | // These methods are thread safe. | 
|  | static void WriteHTMLGraph(const std::string& query, std::string* output); | 
|  | static void WriteGraph(const std::string& query, std::string* output); | 
|  |  | 
|  | // Returns the histograms with |verbosity_level| as the serialization | 
|  | // verbosity. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static std::string ToJSON(JSONVerbosityLevel verbosity_level); | 
|  |  | 
|  | // Gets existing histograms. | 
|  | // | 
|  | // The order of returned histograms is not guaranteed. | 
|  | // | 
|  | // Ownership of the individual histograms remains with the StatisticsRecorder. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static Histograms GetHistograms(); | 
|  |  | 
|  | // Gets BucketRanges used by all histograms registered. The order of returned | 
|  | // BucketRanges is not guaranteed. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static std::vector<const BucketRanges*> GetBucketRanges(); | 
|  |  | 
|  | // Finds a histogram by name. Matches the exact name. Returns a null pointer | 
|  | // if a matching histogram is not found. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static HistogramBase* FindHistogram(base::StringPiece name); | 
|  |  | 
|  | // Imports histograms from providers. | 
|  | // | 
|  | // This method must be called on the UI thread. | 
|  | static void ImportProvidedHistograms(); | 
|  |  | 
|  | // Snapshots all histograms via |snapshot_manager|. |flags_to_set| is used to | 
|  | // set flags for each histogram. |required_flags| is used to select | 
|  | // histograms to be recorded. Only histograms that have all the flags | 
|  | // specified by the argument will be chosen. If all histograms should be | 
|  | // recorded, set it to |Histogram::kNoFlags|. | 
|  | static void PrepareDeltas(bool include_persistent, | 
|  | HistogramBase::Flags flags_to_set, | 
|  | HistogramBase::Flags required_flags, | 
|  | HistogramSnapshotManager* snapshot_manager); | 
|  |  | 
|  | typedef base::Callback<void(HistogramBase::Sample)> OnSampleCallback; | 
|  |  | 
|  | // Sets the callback to notify when a new sample is recorded on the histogram | 
|  | // referred to by |histogram_name|. Can be called before or after the | 
|  | // histogram is created. Returns whether the callback was successfully set. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static bool SetCallback(const std::string& histogram_name, | 
|  | const OnSampleCallback& callback); | 
|  |  | 
|  | // Clears any callback set on the histogram referred to by |histogram_name|. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static void ClearCallback(const std::string& histogram_name); | 
|  |  | 
|  | // Retrieves the callback for the histogram referred to by |histogram_name|, | 
|  | // or a null callback if no callback exists for this histogram. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static OnSampleCallback FindCallback(const std::string& histogram_name); | 
|  |  | 
|  | // Returns the number of known histograms. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static size_t GetHistogramCount(); | 
|  |  | 
|  | // Initializes logging histograms with --v=1. Safe to call multiple times. | 
|  | // Is called from ctor but for browser it seems that it is more useful to | 
|  | // start logging after statistics recorder, so we need to init log-on-shutdown | 
|  | // later. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static void InitLogOnShutdown(); | 
|  |  | 
|  | // Removes a histogram from the internal set of known ones. This can be | 
|  | // necessary during testing persistent histograms where the underlying | 
|  | // memory is being released. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static void ForgetHistogramForTesting(base::StringPiece name); | 
|  |  | 
|  | // Creates a temporary StatisticsRecorder object for testing purposes. All new | 
|  | // histograms will be registered in it until it is destructed or pushed aside | 
|  | // for the lifetime of yet another StatisticsRecorder object. The destruction | 
|  | // of the returned object will re-activate the previous one. | 
|  | // StatisticsRecorder objects must be deleted in the opposite order to which | 
|  | // they're created. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static std::unique_ptr<StatisticsRecorder> CreateTemporaryForTesting() | 
|  | WARN_UNUSED_RESULT; | 
|  |  | 
|  | // Sets the record checker for determining if a histogram should be recorded. | 
|  | // Record checker doesn't affect any already recorded histograms, so this | 
|  | // method must be called very early, before any threads have started. | 
|  | // Record checker methods can be called on any thread, so they shouldn't | 
|  | // mutate any state. | 
|  | static void SetRecordChecker( | 
|  | std::unique_ptr<RecordHistogramChecker> record_checker); | 
|  |  | 
|  | // Checks if the given histogram should be recorded based on the | 
|  | // ShouldRecord() method of the record checker. If the record checker is not | 
|  | // set, returns true. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static bool ShouldRecordHistogram(uint64_t histogram_hash); | 
|  |  | 
|  | // Sorts histograms by name. | 
|  | static Histograms Sort(Histograms histograms); | 
|  |  | 
|  | // Filters histograms by name. Only histograms which have |query| as a | 
|  | // substring in their name are kept. An empty query keeps all histograms. | 
|  | static Histograms WithName(Histograms histograms, const std::string& query); | 
|  |  | 
|  | // Filters histograms by persistency. Only non-persistent histograms are kept. | 
|  | static Histograms NonPersistent(Histograms histograms); | 
|  |  | 
|  | private: | 
|  | typedef std::vector<WeakPtr<HistogramProvider>> HistogramProviders; | 
|  |  | 
|  | typedef std::unordered_map<StringPiece, HistogramBase*, StringPieceHash> | 
|  | HistogramMap; | 
|  |  | 
|  | // We keep a map of callbacks to histograms, so that as histograms are | 
|  | // created, we can set the callback properly. | 
|  | typedef std::unordered_map<std::string, OnSampleCallback> CallbackMap; | 
|  |  | 
|  | struct BucketRangesHash { | 
|  | size_t operator()(const BucketRanges* a) const; | 
|  | }; | 
|  |  | 
|  | struct BucketRangesEqual { | 
|  | bool operator()(const BucketRanges* a, const BucketRanges* b) const; | 
|  | }; | 
|  |  | 
|  | typedef std:: | 
|  | unordered_set<const BucketRanges*, BucketRangesHash, BucketRangesEqual> | 
|  | RangesMap; | 
|  |  | 
|  | friend class StatisticsRecorderTest; | 
|  | FRIEND_TEST_ALL_PREFIXES(StatisticsRecorderTest, IterationTest); | 
|  |  | 
|  | // Initializes the global recorder if it doesn't already exist. Safe to call | 
|  | // multiple times. | 
|  | // | 
|  | // Precondition: The global lock is already acquired. | 
|  | static void EnsureGlobalRecorderWhileLocked(); | 
|  |  | 
|  | // Gets histogram providers. | 
|  | // | 
|  | // This method is thread safe. | 
|  | static HistogramProviders GetHistogramProviders(); | 
|  |  | 
|  | // Imports histograms from global persistent memory. | 
|  | // | 
|  | // Precondition: The global lock must not be held during this call. | 
|  | static void ImportGlobalPersistentHistograms(); | 
|  |  | 
|  | // Constructs a new StatisticsRecorder and sets it as the current global | 
|  | // recorder. | 
|  | // | 
|  | // Precondition: The global lock is already acquired. | 
|  | StatisticsRecorder(); | 
|  |  | 
|  | // Initialize implementation but without lock. Caller should guard | 
|  | // StatisticsRecorder by itself if needed (it isn't in unit tests). | 
|  | // | 
|  | // Precondition: The global lock is already acquired. | 
|  | static void InitLogOnShutdownWhileLocked(); | 
|  |  | 
|  | HistogramMap histograms_; | 
|  | CallbackMap callbacks_; | 
|  | RangesMap ranges_; | 
|  | HistogramProviders providers_; | 
|  | std::unique_ptr<RecordHistogramChecker> record_checker_; | 
|  |  | 
|  | // Previous global recorder that existed when this one was created. | 
|  | StatisticsRecorder* previous_ = nullptr; | 
|  |  | 
|  | // Global lock for internal synchronization. | 
|  | static LazyInstance<Lock>::Leaky lock_; | 
|  |  | 
|  | // Current global recorder. This recorder is used by static methods. When a | 
|  | // new global recorder is created by CreateTemporaryForTesting(), then the | 
|  | // previous global recorder is referenced by top_->previous_. | 
|  | static StatisticsRecorder* top_; | 
|  |  | 
|  | // Tracks whether InitLogOnShutdownWhileLocked() has registered a logging | 
|  | // function that will be called when the program finishes. | 
|  | static bool is_vlog_initialized_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); | 
|  | }; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_METRICS_STATISTICS_RECORDER_H_ |