00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __METRIC_INTERFACE__
00009 #define __METRIC_INTERFACE__
00010
00011 #include <string>
00012 #include <cstdint>
00013 #include <chrono>
00014 #include <unordered_map>
00015 #include "fhiclcpp/ParameterSet.h"
00016
00017 namespace artdaq
00018 {
00019 class MetricPlugin
00020 {
00021 public:
00022 MetricPlugin(fhicl::ParameterSet const& ps) : pset(ps)
00023 , inhibit_(false)
00024 {
00025 runLevel_ = pset.get<int>("level", 0);
00026 accumulationTime_ = pset.get<double>("reporting_interval", 15.0);
00027 }
00028
00029 virtual ~MetricPlugin() = default;
00030
00032
00033
00034
00036 public:
00037 virtual std::string getLibName() const { return "ERROR"; }
00038 protected:
00039
00040
00041 virtual void sendMetric_(const std::string& name, const std::string& value, const std::string& unit) = 0;
00042
00043 virtual void sendMetric_(const std::string& name, const int& value, const std::string& unit) = 0;
00044
00045 virtual void sendMetric_(const std::string& name, const double& value, const std::string& unit) = 0;
00046
00047 virtual void sendMetric_(const std::string& name, const float& value, const std::string& unit) = 0;
00048
00049 virtual void sendMetric_(const std::string& name, const long unsigned int& value, const std::string& unit) = 0;
00050
00051
00052 virtual void startMetrics_() = 0;
00053
00054 virtual void stopMetrics_() = 0;
00055
00057
00058
00059
00061 public:
00062
00063 virtual void sendMetric(const std::string& name, const std::string& value, const std::string& unit, bool accumulate = true)
00064 {
00065 if (accumulate)
00066 {
00067
00068 sendMetric_(name, value, unit);
00069 }
00070 else
00071 {
00072 sendMetric_(name, value, unit);
00073 }
00074 }
00075
00076 virtual void sendMetric(const std::string& name, const int& value, const std::string& unit, bool accumulate = true)
00077 {
00078
00079
00080
00081 intAccumulator_[name].push_back(value);
00082
00083 if (!accumulate)
00084 {
00085 sendMetric_(name, value, unit);
00086 intAccumulator_[name].clear();
00087 lastSendTime_[name] = std::chrono::steady_clock::now();
00088 return;
00089 }
00090
00091 if (readyToSend_(name))
00092 {
00093 double sendValue = 0;
00094 for (auto val : intAccumulator_[name])
00095 {
00096 sendValue += val / (double)intAccumulator_[name].size();
00097 }
00098
00099 sendMetric_(name, sendValue, unit);
00100
00101 intAccumulator_[name].clear();
00102 }
00103 }
00104
00105 virtual void sendMetric(const std::string& name, const double& value, const std::string& unit, bool accumulate = true)
00106 {
00107
00108
00109
00110 doubleAccumulator_[name].push_back(value);
00111
00112 if (!accumulate)
00113 {
00114 sendMetric_(name, value, unit);
00115 doubleAccumulator_[name].clear();
00116 lastSendTime_[name] = std::chrono::steady_clock::now();
00117 return;
00118 }
00119
00120 if (readyToSend_(name))
00121 {
00122 double sendValue = 0;
00123 for (auto val : doubleAccumulator_[name])
00124 {
00125 sendValue += val / doubleAccumulator_[name].size();
00126 }
00127
00128 sendMetric_(name, sendValue, unit);
00129
00130 doubleAccumulator_[name].clear();
00131 }
00132 }
00133
00134 virtual void sendMetric(const std::string& name, const float& value, const std::string& unit, bool accumulate = true)
00135 {
00136
00137
00138
00139 floatAccumulator_[name].push_back(value);
00140
00141 if (!accumulate)
00142 {
00143 sendMetric_(name, value, unit);
00144 floatAccumulator_[name].clear();
00145 lastSendTime_[name] = std::chrono::steady_clock::now();
00146 return;
00147 }
00148
00149 if (readyToSend_(name))
00150 {
00151 float sendValue = 0;
00152 for (auto val : floatAccumulator_[name])
00153 {
00154 sendValue += val / floatAccumulator_[name].size();
00155 }
00156
00157 sendMetric_(name, sendValue, unit);
00158
00159 floatAccumulator_[name].clear();
00160 }
00161 }
00162
00163 virtual void sendMetric(const std::string& name, const long unsigned int& value, const std::string& unit, bool accumulate = true)
00164 {
00165
00166
00167
00168 uint32_t uvalue = static_cast<uint32_t>(value);
00169 uintAccumulator_[name].push_back(uvalue);
00170
00171 if (!accumulate)
00172 {
00173 sendMetric_(name, value, unit);
00174 uintAccumulator_[name].clear();
00175 lastSendTime_[name] = std::chrono::steady_clock::now();
00176 return;
00177 }
00178
00179 if (readyToSend_(name))
00180 {
00181 double sendValue = 0;
00182 for (auto val : uintAccumulator_[name])
00183 {
00184 sendValue += val / (double)uintAccumulator_[name].size();
00185 }
00186
00187 sendMetric_(name, sendValue, unit);
00188
00189 uintAccumulator_[name].clear();
00190 }
00191 }
00192
00193
00194
00195 virtual void startMetrics() { startMetrics_(); }
00196
00197 virtual void stopMetrics()
00198 {
00199 inhibit_ = true;
00200 for (auto dv : doubleAccumulator_)
00201 {
00202 static_cast<std::vector<double>>(dv.second).clear();
00203
00204 sendMetric(dv.first, (double)0.0, "", false);
00205 }
00206 for (auto iv : intAccumulator_)
00207 {
00208 static_cast<std::vector<int>>(iv.second).clear();
00209
00210 sendMetric(iv.first, (int)0, "", false);
00211 }
00212 for (auto fv : floatAccumulator_)
00213 {
00214 static_cast<std::vector<float>>(fv.second).clear();
00215
00216 sendMetric(fv.first, (float)0.0, "", false);
00217 }
00218 for (auto uv : uintAccumulator_)
00219 {
00220 static_cast<std::vector<uint32_t>>(uv.second).clear();
00221
00222 sendMetric(uv.first, (long unsigned int)0, "", false);
00223 }
00224 stopMetrics_();
00225 inhibit_ = false;
00226 }
00227
00228 void setRunLevel(int level) { runLevel_ = level; }
00229 int getRunLevel() { return runLevel_; }
00230
00231 protected:
00232 int runLevel_;
00233 fhicl::ParameterSet pset;
00234 double accumulationTime_;
00235 bool inhibit_;
00236
00237 private:
00238 std::unordered_map<std::string, std::vector<double>> doubleAccumulator_;
00239 std::unordered_map<std::string, std::vector<int>> intAccumulator_;
00240 std::unordered_map<std::string, std::vector<float>> floatAccumulator_;
00241 std::unordered_map<std::string, std::vector<uint32_t>> uintAccumulator_;
00242 std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
00243
00244 bool readyToSend_(std::string name)
00245 {
00246 auto now = std::chrono::steady_clock::now();
00247 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
00248 {
00249 lastSendTime_[name] = now;
00250 return true;
00251 }
00252
00253 return false;
00254 }
00255 };
00256 }
00257
00258 #endif //End ifndef __METRIC_INTERFACE__