LogCabin
|
00001 /* Copyright (c) 2015 Diego Ongaro 00002 * 00003 * Permission to use, copy, modify, and distribute this software for any 00004 * purpose with or without fee is hereby granted, provided that the above 00005 * copyright notice and this permission notice appear in all copies. 00006 * 00007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00008 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00009 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00010 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00011 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00012 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00013 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00014 */ 00015 00016 #ifndef LOGCABIN_CORE_ROLLINGSTAT_H 00017 #define LOGCABIN_CORE_ROLLINGSTAT_H 00018 00019 #include <cinttypes> 00020 #include <iostream> 00021 #include <deque> 00022 00023 #include "Core/Time.h" 00024 00025 namespace LogCabin { 00026 00027 // forward declaration 00028 namespace Protocol { 00029 class RollingStat; 00030 } 00031 00032 namespace Core { 00033 00034 /** 00035 * This class gathers statistics about a given metric over time, like its 00036 * average, standard deviation, and exponentially weighted moving average. This 00037 * class also keeps track of the last 5 "exceptional" values, typically those 00038 * that are above some pre-defined threshold. 00039 * 00040 * This currently assumes your metric is a uint64_t. It could probably be 00041 * abstracted out in some way, but most metrics in LogCabin seem to fit this 00042 * category. 00043 */ 00044 class RollingStat { 00045 public: 00046 /** 00047 * Clock used for exceptional values. 00048 */ 00049 typedef Core::Time::SteadyClock Clock; 00050 /** 00051 * Time point used for exceptional values. 00052 */ 00053 typedef Clock::time_point TimePoint; 00054 00055 /** 00056 * Constructor. 00057 */ 00058 RollingStat(); 00059 00060 /** 00061 * Destructor. 00062 */ 00063 ~RollingStat(); 00064 00065 /** 00066 * Return mean, or 0 if no values reported. 00067 */ 00068 double getAverage() const; 00069 /** 00070 * Return number of values reported. 00071 */ 00072 uint64_t getCount() const; 00073 /** 00074 * Return exponentially weighted moving average with alpha of 0.5, 00075 * or 0 if no values reported. 00076 */ 00077 double getEWMA2() const; 00078 /** 00079 * Return exponentially weighted moving average with alpha of 0.25, 00080 * or 0 if no values reported. 00081 */ 00082 double getEWMA4() const; 00083 /** 00084 * Return total number of exceptional values reported. 00085 */ 00086 uint64_t getExceptionalCount() const; 00087 /** 00088 * Return last value reported, or 0 if no values reported. 00089 */ 00090 uint64_t getLast() const; 00091 /** 00092 * Return up to the last 5 exceptional values reported, newest first. 00093 */ 00094 std::vector<std::pair<TimePoint, uint64_t>> getLastExceptional() const; 00095 /** 00096 * Return the smallest value reported, or 0 if no values reported. 00097 */ 00098 uint64_t getMin() const; 00099 /** 00100 * Return the largest value reported, or 0 if no values reported. 00101 */ 00102 uint64_t getMax() const; 00103 /** 00104 * Return the cumulative total of all values reported, or 0 if no values 00105 * reported. 00106 */ 00107 uint64_t getSum() const; 00108 /** 00109 * Return the standard deviation of all values reported, or 0 if no values 00110 * reported. 00111 */ 00112 double getStdDev() const; 00113 00114 /** 00115 * Report an exceptional value. Note that this does not include a 'push'; 00116 * you may want to do that separately. 00117 * \param when 00118 * The time the exceptional situation occurred (by convention, this is 00119 * usually its start time). 00120 * \param value 00121 * The exceptional value. 00122 */ 00123 void noteExceptional(TimePoint when, uint64_t value); 00124 00125 /** 00126 * Report a value. 00127 */ 00128 void push(uint64_t value); 00129 00130 /** 00131 * Serialize all the stats into the given empty ProtoBuf message. 00132 */ 00133 void updateProtoBuf(Protocol::RollingStat& message) const; 00134 00135 /** 00136 * Print all the stats. 00137 */ 00138 friend std::ostream& operator<<(std::ostream& os, 00139 const RollingStat& stat); 00140 00141 private: 00142 // See getters above for most of these. 00143 uint64_t count; 00144 double ewma2; 00145 double ewma4; 00146 uint64_t exceptionalCount; 00147 uint64_t last; 00148 std::deque<std::pair<TimePoint, uint64_t>> lastExceptional; 00149 uint64_t max; 00150 uint64_t min; 00151 uint64_t sum; 00152 /** 00153 * Used to calculate standard deviation. sum of x times x over all values. 00154 */ 00155 uint64_t sumSquares; 00156 00157 }; 00158 00159 } // namespace LogCabin::Core 00160 } // namespace LogCabin 00161 00162 #endif /* LOGCABIN_CORE_ROLLINGSTAT_H */