| Index: statsreport/metrics.h
|
| diff --git a/statsreport/metrics.h b/statsreport/metrics.h
|
| deleted file mode 100644
|
| index 360370512e3c67500189f89d2cd96a37c1419b60..0000000000000000000000000000000000000000
|
| --- a/statsreport/metrics.h
|
| +++ /dev/null
|
| @@ -1,539 +0,0 @@
|
| -// Copyright 2006-2009 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -//
|
| -// Declares the interface to in-memory metrics capture
|
| -#ifndef OMAHA_STATSREPORT_METRICS_H__
|
| -#define OMAHA_STATSREPORT_METRICS_H__
|
| -
|
| -#include <iterator>
|
| -#include "base/basictypes.h"
|
| -#include "omaha/base/highres_timer-win32.h"
|
| -#include "omaha/base/logging/logging.h"
|
| -
|
| -/// Macros to declare & define named & typed metrics.
|
| -/// Put declarations in headers or in cpp files, where you need access
|
| -/// to the metrics. For each declared metric, there must be precisely
|
| -/// one definition in a compilation unit someplace.
|
| -
|
| -/// A count metric should be used to report anything that monotonically
|
| -/// increases.
|
| -/// Examples:
|
| -/// # event count
|
| -/// how often does this condition hit, this function get called
|
| -/// # aggregate sums
|
| -/// how many bytes are written
|
| -#define DECLARE_METRIC_count(name) DECLARE_METRIC(CountMetric, name)
|
| -#define DEFINE_METRIC_count(name) DEFINE_METRIC(CountMetric, name)
|
| -
|
| -/// Use timing metrics to report on the performance of important things.
|
| -/// A timing metric will report the count of occurrences, as well as the
|
| -/// average, min and max times.
|
| -/// Samples are measured in milliseconds if you use the TIME_SCOPE macro
|
| -/// or the HighResTimer class to collect samples.
|
| -#define DECLARE_METRIC_timing(name) DECLARE_METRIC(TimingMetric, name)
|
| -#define DEFINE_METRIC_timing(name) DEFINE_METRIC(TimingMetric, name)
|
| -
|
| -/// Collects a sample from here to the end of the current scope, and
|
| -/// adds the sample to the timing metric supplied
|
| -#define TIME_SCOPE(timing) \
|
| - stats_report::TimingSample __xxsample__(timing)
|
| -
|
| -/// Use integer metrics to report runtime values that fluctuate.
|
| -/// Examples:
|
| -/// # object count
|
| -/// How many objects of some type exist
|
| -/// # disk space or memory
|
| -/// How much disk space or memory is in use
|
| -#define DECLARE_METRIC_integer(name) DECLARE_METRIC(IntegerMetric, name)
|
| -#define DEFINE_METRIC_integer(name) DEFINE_METRIC(IntegerMetric, name)
|
| -
|
| -
|
| -/// Use boolean metrics to report the occurrence of important but rare events
|
| -/// or conditions. Note that a boolean metric is tri-state, so you typically
|
| -/// want to set it only in one direction, and typically to true.
|
| -/// Setting a boolean metric one way or another on a trigger event will report
|
| -/// the setting of the boolean immediately prior to reporting, which is
|
| -/// typically not what you want.
|
| -#define DECLARE_METRIC_bool(name) DECLARE_METRIC(BoolMetric, name)
|
| -#define DEFINE_METRIC_bool(name) DEFINE_METRIC(BoolMetric, name)
|
| -
|
| -
|
| -/// Implementation macros
|
| -#define DECLARE_METRIC(type, name) \
|
| - namespace omaha_client_statsreport { \
|
| - extern stats_report::type metric_##name; \
|
| - } \
|
| - using omaha_client_statsreport::metric_##name
|
| -
|
| -#define DEFINE_METRIC(type, name) \
|
| - namespace omaha_client_statsreport { \
|
| - stats_report::type metric_##name(#name, \
|
| - &stats_report::g_global_metric_storage); \
|
| - } \
|
| - using omaha_client_statsreport::metric_##name
|
| -
|
| -
|
| -namespace stats_report {
|
| -
|
| -enum MetricType {
|
| - // use zero for invalid, because global storage defaults to zero
|
| - kInvalidType = 0,
|
| - kCountType,
|
| - kTimingType,
|
| - kIntegerType,
|
| - kBoolType
|
| -};
|
| -
|
| -// fwd.
|
| -struct MetricCollectionBase;
|
| -class MetricCollection;
|
| -class MetricBase;
|
| -class IntegerMetricBase;
|
| -class CountMetric;
|
| -class TimingMetric;
|
| -class IntegerMetric;
|
| -class BoolMetric;
|
| -
|
| -/// Base class for all stats instances.
|
| -/// Stats instances are chained together against a MetricCollection to
|
| -/// allow enumerating stats.
|
| -///
|
| -/// MetricCollection is factored into a class to make it easier to unittest
|
| -/// the implementation.
|
| -class MetricBase {
|
| -public:
|
| - /// @name Downcasts
|
| - /// @{
|
| - CountMetric &AsCount();
|
| - TimingMetric &AsTiming();
|
| - IntegerMetric &AsInteger();
|
| - BoolMetric &AsBool();
|
| -
|
| - const CountMetric &AsCount() const;
|
| - const TimingMetric &AsTiming() const;
|
| - const IntegerMetric &AsInteger() const;
|
| - const BoolMetric &AsBool() const;
|
| - /// @}
|
| -
|
| - /// @name Accessors
|
| - /// @{
|
| - MetricType type() const { return type_; }
|
| - MetricBase *next() const { return next_; }
|
| - const char *name() const { return name_; }
|
| - /// @}
|
| -
|
| - // TODO(omaha): does this need to be virtual?
|
| - virtual ~MetricBase() = 0;
|
| -
|
| -protected:
|
| - class ObjectLock;
|
| - void Lock() const;
|
| - void Unlock() const;
|
| -
|
| - /// Constructs a MetricBase and adds to the provided MetricCollection.
|
| - /// @note Metrics can only be constructed up to the point where the
|
| - /// MetricCollection is initialized, and there's no locking performed.
|
| - /// The assumption is that outside unit tests, Metrics will we declared
|
| - /// as static/global variables, and initialized at static initialization
|
| - /// time - and static initialization is single-threaded.
|
| - MetricBase(const char *name, MetricType type, MetricCollectionBase *coll);
|
| -
|
| - /// Constructs a named typed MetricBase
|
| - MetricBase(const char *name, MetricType type);
|
| -
|
| - /// Our name
|
| - char const *const name_;
|
| -
|
| - /// type of this metric
|
| - MetricType const type_;
|
| -
|
| - /// chains to next stat instance
|
| - MetricBase *const next_;
|
| -
|
| - /// The collection we're created against
|
| - MetricCollectionBase *const coll_;
|
| -
|
| -private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(MetricBase);
|
| -};
|
| -
|
| -/// Must be a POD
|
| -struct MetricCollectionBase {
|
| - bool initialized_;
|
| - MetricBase *first_;
|
| -};
|
| -
|
| -/// Inherit from base, which is a POD and can be initialized at link time.
|
| -///
|
| -/// The global MetricCollection is aliased to a link-time initialized
|
| -/// instance of MetricCollectionBase, and must not extend the size of its
|
| -/// base class.
|
| -class MetricCollection: public MetricCollectionBase {
|
| -public:
|
| - MetricCollection() {
|
| - initialized_ = false;
|
| - first_ = NULL;
|
| - }
|
| - ~MetricCollection() {
|
| - DCHECK(NULL == first_);
|
| - }
|
| -
|
| - /// Initialize must be called after all metrics have been added to the
|
| - /// collection, but before enumerating it for e.g. aggregation or reporting.
|
| - /// The intent is that outside unit tests, there will only be the global
|
| - /// metrics collection, which will accrue all metrics defined with the
|
| - /// DEFINE_METRIC_* macros.
|
| - /// Typically you'd call Initialize very early in your main function, and
|
| - /// Uninitialize towards the end of main.
|
| - /// It is an error to Initialize() when the collection is initialized().
|
| - void Initialize();
|
| -
|
| - /// Uninitialize must be called before removing (deleting or deconstructing)
|
| - /// metrics from the collection.
|
| - /// It is an error to Uninitialize() when the collection is !initialized().
|
| - void Uninitialize();
|
| -
|
| - MetricBase *first() const { return first_; }
|
| - bool initialized() const { return initialized_; }
|
| -
|
| -private:
|
| - using MetricCollectionBase::initialized_;
|
| - using MetricCollectionBase::first_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(MetricCollection);
|
| -
|
| - /// MetricBase is intimate with us
|
| - friend class MetricBase;
|
| -};
|
| -
|
| -/// Implements a forward_iterator for MetricCollection.
|
| -class MetricIterator: public std::iterator<std::forward_iterator_tag,
|
| - MetricBase *> {
|
| -public:
|
| - MetricIterator() : curr_(NULL) {
|
| - }
|
| - MetricIterator(const MetricIterator &other) : curr_(other.curr_) {
|
| - }
|
| - MetricIterator(const MetricCollection &coll) : curr_(coll.first()) {
|
| - DCHECK(coll.initialized());
|
| - }
|
| -
|
| - MetricBase *operator*() const {
|
| - return curr_;
|
| - }
|
| - MetricBase *operator->() const {
|
| - return curr_;
|
| - }
|
| - MetricIterator operator++() { // preincrement
|
| - if (curr_)
|
| - curr_ = curr_->next();
|
| -
|
| - return (*this);
|
| - }
|
| - MetricIterator operator++(int) {// postincrement
|
| - MetricIterator ret = *this;
|
| - ++*this;
|
| - return (ret);
|
| - }
|
| -
|
| -private:
|
| - MetricBase *curr_;
|
| -};
|
| -
|
| -inline bool operator == (const MetricIterator &a, const MetricIterator &b) {
|
| - return *a == *b;
|
| -}
|
| -inline bool operator != (const MetricIterator &a, const MetricIterator &b) {
|
| - return !operator == (a, b);
|
| -}
|
| -
|
| -/// Globally defined counters are registered here
|
| -extern MetricCollectionBase g_global_metric_storage;
|
| -
|
| -/// And more conveniently accessed through here
|
| -extern MetricCollection &g_global_metrics;
|
| -
|
| -/// Base class for integer metrics
|
| -class IntegerMetricBase: public MetricBase {
|
| -public:
|
| - /// Sets the current value
|
| - void Set(int64 value);
|
| -
|
| - /// Retrieves the current value
|
| - int64 value() const;
|
| -
|
| - void operator ++ () { Increment(); }
|
| - void operator ++ (int) { Increment(); }
|
| - void operator += (int64 addend) { Add(addend); }
|
| -
|
| -protected:
|
| - IntegerMetricBase(const char *name,
|
| - MetricType type,
|
| - MetricCollectionBase *coll)
|
| - : MetricBase(name, type, coll), value_(0) {
|
| - }
|
| - IntegerMetricBase(const char *name, MetricType type, int64 value)
|
| - : MetricBase(name, type), value_(value) {
|
| - }
|
| -
|
| - void Increment();
|
| - void Decrement();
|
| - void Add(int64 value);
|
| - void Subtract(int64 value);
|
| -
|
| - int64 value_;
|
| -
|
| -private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(IntegerMetricBase);
|
| -};
|
| -
|
| -/// A count metric is a cumulative counter of events.
|
| -class CountMetric: public IntegerMetricBase {
|
| -public:
|
| - CountMetric(const char *name, MetricCollectionBase *coll)
|
| - : IntegerMetricBase(name, kCountType, coll) {
|
| - }
|
| -
|
| - CountMetric(const char *name, int64 value)
|
| - : IntegerMetricBase(name, kCountType, value) {
|
| - }
|
| -
|
| - /// Nulls the metric and returns the current values.
|
| - int64 Reset();
|
| -
|
| -private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(CountMetric);
|
| -};
|
| -
|
| -class TimingMetric: public MetricBase {
|
| -public:
|
| - struct TimingData {
|
| - uint32 count;
|
| - uint32 align; // allow access to the alignment gap between count and sum,
|
| - // makes it esier to unittest.
|
| - int64 sum; // ms
|
| - int64 minimum; // ms
|
| - int64 maximum; // ms
|
| - };
|
| -
|
| - TimingMetric(const char *name, MetricCollectionBase *coll)
|
| - : MetricBase(name, kTimingType, coll) {
|
| - Clear();
|
| - }
|
| -
|
| - TimingMetric(const char *name, const TimingData &value)
|
| - : MetricBase(name, kTimingType), data_(value) {
|
| - }
|
| -
|
| - uint32 count() const;
|
| - int64 sum() const;
|
| - int64 minimum() const;
|
| - int64 maximum() const;
|
| - int64 average() const;
|
| -
|
| - /// Adds a single sample to the metric
|
| - /// @param time_ms time (in milliseconds) for this sample
|
| - void AddSample(int64 time_ms);
|
| -
|
| - /// Adds count samples to the metric
|
| - /// @note use this when capturing time over a variable number of items to
|
| - /// normalize e.g. download time per byte or KB. This records one sample
|
| - /// over count items, which is numerically more stable for the average
|
| - /// than dividing the captured time by the item count. As a side benefit
|
| - /// the timer will also record the item count.
|
| - /// @note if count == 0, no sample will be recorded
|
| - /// @param count number of samples to add
|
| - /// @param total_time_ms the total time consumed by all the "count" samples
|
| - void AddSamples(int64 count, int64 total_time_ms);
|
| -
|
| - /// Nulls the metric and returns the current values.
|
| - TimingData Reset();
|
| -
|
| -private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(TimingMetric);
|
| -
|
| - void Clear();
|
| -
|
| - TimingData data_;
|
| -};
|
| -
|
| -/// A convenience class to sample the time from construction to destruction
|
| -/// against a given timing metric.
|
| -class TimingSample {
|
| -public:
|
| - /// @param timing the metric the sample is to be tallied against
|
| - explicit TimingSample(TimingMetric &timing) : timing_(timing), count_(1) {
|
| - }
|
| -
|
| - /// @param timing the metric the sample is to be tallied against
|
| - /// @param item_count count of items processed, used to divide the sampled
|
| - /// time so as to capture time per item, which is often a better measure
|
| - /// than the total time over a varying number of items.
|
| - TimingSample(TimingMetric &timing, uint32 item_count) : timing_(timing),
|
| - count_(item_count) {
|
| - }
|
| -
|
| - ~TimingSample() {
|
| - // We discard samples with a zero count
|
| - if(count_ == 1)
|
| - timing_.AddSample(timer_.GetElapsedMs());
|
| - else
|
| - timing_.AddSamples(count_, timer_.GetElapsedMs());
|
| - }
|
| -
|
| - /// @name Accessors
|
| - /// @{
|
| - uint32 count() const { return count_; }
|
| - void set_count(uint32 count) { count_ = count; }
|
| - /// @}
|
| -
|
| -private:
|
| - /// Collects the sample for us.
|
| - omaha::HighresTimer timer_;
|
| -
|
| - /// The metric we tally against.
|
| - TimingMetric &timing_;
|
| -
|
| - /// The item count we divide the captured time by
|
| - uint32 count_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(TimingSample);
|
| -};
|
| -
|
| -/// An integer metric is used to sample values that vary over time.
|
| -/// On aggregation the instantaneous value of the integer metric is captured.
|
| -class IntegerMetric: public IntegerMetricBase {
|
| -public:
|
| - IntegerMetric(const char *name, MetricCollectionBase *coll)
|
| - : IntegerMetricBase(name, kIntegerType, coll) {
|
| - }
|
| -
|
| - IntegerMetric(const char *name, int64 value)
|
| - : IntegerMetricBase(name, kIntegerType, value) {
|
| - }
|
| -
|
| - void operator = (int64 value) { Set(value); }
|
| -
|
| - void operator -- () { Decrement(); }
|
| - void operator -- (int) { Decrement(); }
|
| - void operator -= (int64 sub) { Subtract(sub); }
|
| -
|
| -private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(IntegerMetric);
|
| -};
|
| -
|
| -/// A bool metric is tri-state, and can be:
|
| -/// - unset,
|
| -/// - true or
|
| -/// - false
|
| -/// to match other metrics, which are implicitly unset if they've not changed
|
| -/// from their initial value.
|
| -class BoolMetric: public MetricBase {
|
| -public:
|
| - /// Values we can take
|
| - enum TristateBoolValue {
|
| - kBoolUnset = -1,
|
| - kBoolFalse,
|
| - kBoolTrue,
|
| - };
|
| -
|
| - BoolMetric(const char *name, MetricCollectionBase *coll)
|
| - : MetricBase(name, kBoolType, coll), value_(kBoolUnset) {
|
| - }
|
| -
|
| - BoolMetric(const char *name, uint32 value)
|
| - : MetricBase(name, kBoolType) {
|
| - switch (value) {
|
| - case kBoolFalse:
|
| - case kBoolTrue:
|
| - value_ = static_cast<TristateBoolValue>(value);
|
| - break;
|
| -
|
| - default:
|
| - DCHECK(false && "Unexpected tristate bool value on construction");
|
| - value_ = kBoolUnset;
|
| - }
|
| - }
|
| -
|
| - /// Sets the flag to the provided value.
|
| - void Set(bool value);
|
| -
|
| - void operator = (bool value) {
|
| - Set(value);
|
| - }
|
| -
|
| - /// Nulls the metric and returns the current values.
|
| - TristateBoolValue Reset();
|
| -
|
| - /// Returns the current value - not threadsafe
|
| - TristateBoolValue value() const { return value_; };
|
| -
|
| -private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(BoolMetric);
|
| -
|
| - TristateBoolValue value_;
|
| -};
|
| -
|
| -inline CountMetric &MetricBase::AsCount() {
|
| - DCHECK_EQ(kCountType, type());
|
| -
|
| - return static_cast<CountMetric&>(*this);
|
| -}
|
| -
|
| -inline TimingMetric &MetricBase::AsTiming() {
|
| - DCHECK_EQ(kTimingType, type());
|
| -
|
| - return static_cast<TimingMetric&>(*this);
|
| -}
|
| -
|
| -inline IntegerMetric &MetricBase::AsInteger() {
|
| - DCHECK_EQ(kIntegerType, type());
|
| -
|
| - return static_cast<IntegerMetric&>(*this);
|
| -}
|
| -
|
| -inline BoolMetric &MetricBase::AsBool() {
|
| - DCHECK_EQ(kBoolType, type());
|
| -
|
| - return static_cast<BoolMetric&>(*this);
|
| -}
|
| -
|
| -inline const CountMetric &MetricBase::AsCount() const {
|
| - DCHECK_EQ(kCountType, type());
|
| -
|
| - return static_cast<const CountMetric&>(*this);
|
| -}
|
| -
|
| -inline const TimingMetric &MetricBase::AsTiming() const {
|
| - DCHECK_EQ(kTimingType, type());
|
| -
|
| - return static_cast<const TimingMetric&>(*this);
|
| -}
|
| -
|
| -inline const IntegerMetric &MetricBase::AsInteger() const {
|
| - DCHECK_EQ(kIntegerType, type());
|
| -
|
| - return static_cast<const IntegerMetric&>(*this);
|
| -}
|
| -
|
| -inline const BoolMetric &MetricBase::AsBool() const {
|
| - DCHECK_EQ(kBoolType, type());
|
| -
|
| - return static_cast<const BoolMetric&>(*this);
|
| -}
|
| -
|
| -} // namespace stats_report
|
| -
|
| -#endif // OMAHA_STATSREPORT_METRICS_H__
|
|
|