mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 22:36:09 +03:00
303 lines
11 KiB
C
303 lines
11 KiB
C
|
// 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 <stdint.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"
|
||
|
|
||
|
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_
|