// Copyright 2017 Google Inc. All Rights Reserved. // // This file contains the declarations for the Metric class and related // types. #ifndef WVCDM_METRICS_COUNTER_METRIC_H_ #define WVCDM_METRICS_COUNTER_METRIC_H_ #include #include #include #include #include #include "field_tuples.h" #include "lock.h" #include "metric_serialization.h" namespace wvcdm { namespace metrics { class CounterMetricTest; // This base class provides the common defintion used by all templated // instances of CounterMetric. class BaseCounterMetric : public MetricSerializable { public: // Send metric values to the MetricSerializer. |serializer| must // not be null and is owned by the caller. virtual void Serialize(MetricSerializer* serializer); protected: // Instantiates a BaseCounterMetric. BaseCounterMetric(const std::string& metric_name) : metric_name_(metric_name) {} virtual ~BaseCounterMetric() {} // Increment will look for an existing instance of the field names and // add the new value to the existing value. If the instance does not exist, // this method will create it. void Increment(const std::string& field_names_values, int64_t value); private: friend class CounterMetricTest; const std::string metric_name_; // value_map_ contains a mapping from the field name/value pairs to the // counter(int64_t) instance. std::map value_map_; /* * This locks the internal state of the counter metric to ensure safety across * multiple threads preventing the caller from worrying about locking. */ Lock internal_lock_; }; // The CounterMetric class is used to track a counter such as the number of // times a method is called. It can also track a delta that could be positive // or negative. // // The CounterMetric class supports the ability to keep track of multiple // variations of the count based on certain "field" values. E.g. keep track of // the counts of success and failure counts for a method call. Or keep track of // number of times the method was called with a particular parameter. // Fields define what variations to track. Each Field is a separate dimension. // The count for each combination of field values is tracked independently. // // Example usage: // // CounterMetric my_metric("multiple/fields/metric", // "request_type", // Field name. // "error_code"); // Field name. // // my_metric.Increment(1, 7, 23); // (counter value, request type, error code). // // The CounterMetric supports serialization. A call to Serialize will serialize // all values to the provided MetricsSerializer instance. // // example: // // class MyMetricSerializer : public MetricSerializer { // // Add implementation here. // } // // MyMetricSerializer serializer; // my_metric.Serialize(&serializer); template class CounterMetric : public BaseCounterMetric { public: // Create a CounterMetric instance with the name |metric_name|. CounterMetric(const std::string& metric_name); // Overloaded constructors with variable field name arguments. The number // of |field_name| arguments must match the number of used Field type // arguments. CounterMetric(const std::string& metric_name, const char* field_name); CounterMetric(const std::string& metric_name, const char* field_name1, const char* field_name2); CounterMetric(const std::string& metric_name, const char* field_name1, const char* field_name2, const char* field_name3); CounterMetric(const std::string& metric_name, const char* field_name1, const char* field_name2, const char* field_name3, const char* field_name4); // Increment will update the counter value associated with the provided // field values. void Increment(F1 field1 = util::Unused(), F2 field2 = util::Unused(), F3 field3 = util::Unused(), F4 field4 = util::Unused()); // Increment will add the value to the counter associated with the provided // field values. void Increment(int64_t value, F1 field1 = util::Unused(), F2 field2 = util::Unused(), F3 field3 = util::Unused(), F4 field4 = util::Unused()); private: friend class CounterMetricTest; std::vector field_names_; }; // Overloaded template constructor implementations for CounterMetric. template CounterMetric::CounterMetric( const std::string& metric_name) : BaseCounterMetric(metric_name) { ASSERT_METRIC_UNUSED_START_FROM(1); } template CounterMetric::CounterMetric( const std::string& metric_name, const char* field_name) : BaseCounterMetric(metric_name) { ASSERT_METRIC_UNUSED_START_FROM(2); util::AppendFieldNames(&field_names_, util::FirstUnusedType::value - 1, field_name); } template CounterMetric::CounterMetric( const std::string& metric_name, const char* field_name1, const char* field_name2) : BaseCounterMetric(metric_name) { ASSERT_METRIC_UNUSED_START_FROM(3); util::AppendFieldNames(&field_names_, util::FirstUnusedType::value - 1, field_name1, field_name2); } template CounterMetric::CounterMetric( const std::string& metric_name, const char* field_name1, const char* field_name2, const char* field_name3) : BaseCounterMetric(metric_name) { ASSERT_METRIC_UNUSED_START_FROM(4); util::AppendFieldNames(&field_names_, util::FirstUnusedType::value - 1, field_name1, field_name2, field_name3); } template CounterMetric::CounterMetric( const std::string& metric_name, const char* field_name1, const char* field_name2, const char* field_name3, const char* field_name4) : BaseCounterMetric(metric_name) { ASSERT_METRIC_UNUSED_START_FROM(5); util::AppendFieldNames(&field_names_, util::FirstUnusedType::value - 1, field_name1, field_name2, field_name3, field_name4); } template void CounterMetric::Increment( F1 field1, F2 field2, F3 field3, F4 field4) { std::string field_name_values = util::MakeFieldNameString(field_names_, field1, field2, field3, field4); BaseCounterMetric::Increment(field_name_values, 1); } template void CounterMetric::Increment( int64_t value, F1 field1, F2 field2, F3 field3, F4 field4) { std::string field_name_values = util::MakeFieldNameString(field_names_, field1, field2, field3, field4); BaseCounterMetric::Increment(field_name_values, value); } } // namespace metrics } // namespace wvcdm #endif // WVCDM_METRICS_COUNTER_METRIC_H_