00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __METRIC_INTERFACE__
00009 #define __METRIC_INTERFACE__
00010
00011 #include <string>
00012 #include <chrono>
00013 #include <unordered_map>
00014 #include "fhiclcpp/ParameterSet.h"
00015
00016 namespace artdaq
00017 {
00022 class MetricPlugin
00023 {
00024 public:
00038 explicit MetricPlugin(fhicl::ParameterSet const& ps) : pset(ps)
00039 , inhibit_(false)
00040 {
00041 runLevel_ = pset.get<int>("level", 0);
00042 accumulationTime_ = pset.get<double>("reporting_interval", 15.0);
00043 }
00044
00048 virtual ~MetricPlugin() = default;
00049
00051
00052
00053
00055
00059 virtual std::string getLibName() const { return "ERROR"; }
00060 protected:
00069 virtual void sendMetric_(const std::string& name, const std::string& value, const std::string& unit) = 0;
00070
00079 virtual void sendMetric_(const std::string& name, const int& value, const std::string& unit) = 0;
00080
00089 virtual void sendMetric_(const std::string& name, const double& value, const std::string& unit) = 0;
00090
00099 virtual void sendMetric_(const std::string& name, const float& value, const std::string& unit) = 0;
00100
00109 virtual void sendMetric_(const std::string& name, const long unsigned int& value, const std::string& unit) = 0;
00110
00116 virtual void startMetrics_() = 0;
00117
00123 virtual void stopMetrics_() = 0;
00124
00126
00127
00128
00130 public:
00138 void sendMetric(const std::string& name, const std::string& value, const std::string& unit, bool accumulate = true)
00139 {
00140 if (accumulate)
00141 {
00142
00143 sendMetric_(name, value, unit);
00144 }
00145 else
00146 {
00147 sendMetric_(name, value, unit);
00148 }
00149 }
00150
00158 void sendMetric(const std::string& name, const int& value, const std::string& unit, bool accumulate = true)
00159 {
00160
00161
00162
00163 intAccumulator_[name].push_back(value);
00164
00165 if (!accumulate)
00166 {
00167 sendMetric_(name, value, unit);
00168 intAccumulator_[name].clear();
00169 lastSendTime_[name] = std::chrono::steady_clock::now();
00170 return;
00171 }
00172
00173 if (readyToSend_(name))
00174 {
00175 double sendValue = 0;
00176 for (auto val : intAccumulator_[name])
00177 {
00178 sendValue += val / static_cast<double>(intAccumulator_[name].size());
00179 }
00180
00181 sendMetric_(name, sendValue, unit);
00182
00183 intAccumulator_[name].clear();
00184 }
00185 }
00186
00194 void sendMetric(const std::string& name, const double& value, const std::string& unit, bool accumulate = true)
00195 {
00196
00197
00198
00199 doubleAccumulator_[name].push_back(value);
00200
00201 if (!accumulate)
00202 {
00203 sendMetric_(name, value, unit);
00204 doubleAccumulator_[name].clear();
00205 lastSendTime_[name] = std::chrono::steady_clock::now();
00206 return;
00207 }
00208
00209 if (readyToSend_(name))
00210 {
00211 double sendValue = 0;
00212 for (auto val : doubleAccumulator_[name])
00213 {
00214 sendValue += val / doubleAccumulator_[name].size();
00215 }
00216
00217 sendMetric_(name, sendValue, unit);
00218
00219 doubleAccumulator_[name].clear();
00220 }
00221 }
00222
00230 void sendMetric(const std::string& name, const float& value, const std::string& unit, bool accumulate = true)
00231 {
00232
00233
00234
00235 floatAccumulator_[name].push_back(value);
00236
00237 if (!accumulate)
00238 {
00239 sendMetric_(name, value, unit);
00240 floatAccumulator_[name].clear();
00241 lastSendTime_[name] = std::chrono::steady_clock::now();
00242 return;
00243 }
00244
00245 if (readyToSend_(name))
00246 {
00247 float sendValue = 0;
00248 for (auto val : floatAccumulator_[name])
00249 {
00250 sendValue += val / floatAccumulator_[name].size();
00251 }
00252
00253 sendMetric_(name, sendValue, unit);
00254
00255 floatAccumulator_[name].clear();
00256 }
00257 }
00258
00266 void sendMetric(const std::string& name, const long unsigned int& value, const std::string& unit, bool accumulate = true)
00267 {
00268
00269
00270
00271 auto uvalue = static_cast<uint32_t>(value);
00272 uintAccumulator_[name].push_back(uvalue);
00273
00274 if (!accumulate)
00275 {
00276 sendMetric_(name, value, unit);
00277 uintAccumulator_[name].clear();
00278 lastSendTime_[name] = std::chrono::steady_clock::now();
00279 return;
00280 }
00281
00282 if (readyToSend_(name))
00283 {
00284 double sendValue = 0;
00285 for (auto val : uintAccumulator_[name])
00286 {
00287 sendValue += val / static_cast<double>(uintAccumulator_[name].size());
00288 }
00289
00290 sendMetric_(name, sendValue, unit);
00291
00292 uintAccumulator_[name].clear();
00293 }
00294 }
00295
00299 void startMetrics() { startMetrics_(); }
00300
00305 void stopMetrics()
00306 {
00307 inhibit_ = true;
00308 for (auto dv : doubleAccumulator_)
00309 {
00310 static_cast<std::vector<double>>(dv.second).clear();
00311
00312 sendMetric(dv.first, static_cast<double>(0.0), "", false);
00313 }
00314 for (auto iv : intAccumulator_)
00315 {
00316 static_cast<std::vector<int>>(iv.second).clear();
00317
00318 sendMetric(iv.first, static_cast<int>(0), "", false);
00319 }
00320 for (auto fv : floatAccumulator_)
00321 {
00322 static_cast<std::vector<float>>(fv.second).clear();
00323
00324 sendMetric(fv.first, static_cast<float>(0.0), "", false);
00325 }
00326 for (auto uv : uintAccumulator_)
00327 {
00328 static_cast<std::vector<uint32_t>>(uv.second).clear();
00329
00330 sendMetric(uv.first, static_cast<long unsigned int>(0), "", false);
00331 }
00332 stopMetrics_();
00333 inhibit_ = false;
00334 }
00335
00340 void setRunLevel(int level) { runLevel_ = level; }
00345 int getRunLevel() const { return runLevel_; }
00346
00347 protected:
00348 int runLevel_;
00349 fhicl::ParameterSet pset;
00350 double accumulationTime_;
00351 bool inhibit_;
00352
00353 private:
00354 std::unordered_map<std::string, std::vector<double>> doubleAccumulator_;
00355 std::unordered_map<std::string, std::vector<int>> intAccumulator_;
00356 std::unordered_map<std::string, std::vector<float>> floatAccumulator_;
00357 std::unordered_map<std::string, std::vector<uint32_t>> uintAccumulator_;
00358 std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
00359
00360 bool readyToSend_(std::string name)
00361 {
00362 auto now = std::chrono::steady_clock::now();
00363 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
00364 {
00365 lastSendTime_[name] = now;
00366 return true;
00367 }
00368
00369 return false;
00370 }
00371 };
00372 }
00373
00374 #endif //End ifndef __METRIC_INTERFACE__