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 #include "artdaq-utilities/Plugins/MetricData.hh"
00016
00017 namespace artdaq
00018 {
00023 class MetricPlugin
00024 {
00025 public:
00039 explicit MetricPlugin(fhicl::ParameterSet const& ps) : pset(ps)
00040 , inhibit_(false)
00041 {
00042 runLevel_ = pset.get<int>("level", 0);
00043 accumulationTime_ = pset.get<double>("reporting_interval", 15.0);
00044 }
00045
00049 virtual ~MetricPlugin() = default;
00050
00052
00053
00054
00056
00060 virtual std::string getLibName() const { return "ERROR"; }
00061 protected:
00070 virtual void sendMetric_(const std::string& name, const std::string& value, const std::string& unit) = 0;
00071
00080 virtual void sendMetric_(const std::string& name, const int& value, const std::string& unit) = 0;
00081
00090 virtual void sendMetric_(const std::string& name, const double& value, const std::string& unit) = 0;
00091
00100 virtual void sendMetric_(const std::string& name, const float& value, const std::string& unit) = 0;
00101
00110 virtual void sendMetric_(const std::string& name, const long unsigned int& value, const std::string& unit) = 0;
00111
00117 virtual void startMetrics_() = 0;
00118
00124 virtual void stopMetrics_() = 0;
00125
00127
00128
00129
00131 public:
00136 void addMetricData(MetricData data)
00137 {
00138 if (data.Type == MetricType::StringMetric)
00139 {
00140 sendMetric_(data.Name, data.StringValue, data.Unit);
00141 }
00142 else
00143 {
00144 if (!metricRegistry_.count(data.Name))
00145 {
00146 metricRegistry_[data.Name] = data;
00147 }
00148 metricData_[data.Name].push_back(data);
00149
00150 }
00151 }
00152
00157 void sendMetrics(bool forceSend = false)
00158 {
00159 for (auto metric : metricData_)
00160 {
00161 auto metricName = metric.first;
00162 if (readyToSend_(metricName) || forceSend)
00163 {
00164 if (metricData_[metricName].size() == 0 && metricRegistry_.count(metricName))
00165 {
00166 sendZero_(metricRegistry_[metricName]);
00167 }
00168 else if (metricData_[metricName].size() > 0)
00169 {
00170 auto metricMode = metricData_[metricName].back().Mode;
00171 auto metricUnits = metricData_[metricName].back().Unit;
00172 auto metricType = metricData_[metricName].back().Type;
00173
00174 if (metricMode == MetricMode::LastPoint)
00175 {
00176 if (metricData_[metricName].size() > 1)
00177 {
00178 metricData_[metricName].erase(metricData_[metricName].begin(), std::prev(metricData_[metricName].end()));
00179 }
00180 sendMetric_(metricData_[metricName].back());
00181 }
00182 else
00183 {
00184 switch (metricType)
00185 {
00186 case MetricType::DoubleMetric:
00187 {
00188 auto ds = 0.0;
00189 for (auto& mv : metricData_[metricName]) { ds += mv.DoubleValue; }
00190 if (metricMode == MetricMode::Average) { ds /= metricData_[metricName].size(); }
00191 sendMetric_(metricName, ds, metricUnits);
00192 }
00193 break;
00194 case MetricType::FloatMetric:
00195 {
00196 auto fs = 0.0;
00197 for (auto& mv : metricData_[metricName]) { fs += mv.FloatValue; }
00198 if (metricMode == MetricMode::Average) { fs /= metricData_[metricName].size(); }
00199 sendMetric_(metricName, fs, metricUnits);
00200 }
00201 break;
00202 case MetricType::IntMetric:
00203 {
00204 auto is = 0;
00205 for (auto& mv : metricData_[metricName]) { is += mv.IntValue; }
00206 if (metricMode == MetricMode::Average) { is /= metricData_[metricName].size(); }
00207 sendMetric_(metricName, is, metricUnits);
00208 }
00209 break;
00210 case MetricType::UnsignedMetric:
00211 {
00212 auto us = 0;
00213 for (auto& mv : metricData_[metricName]) { us += mv.UnsignedValue; }
00214 if (metricMode == MetricMode::Average) { us /= metricData_[metricName].size(); }
00215 sendMetric_(metricName, us, metricUnits);
00216 }
00217 break;
00218 default:
00219 break;
00220 }
00221 metricData_[metricName].clear();
00222 }
00223 }
00224 }
00225 }
00226 }
00227
00231 void startMetrics() { startMetrics_(); }
00232
00237 void stopMetrics()
00238 {
00239 inhibit_ = true;
00240 sendMetrics(true);
00241 for (auto metric : metricRegistry_)
00242 {
00243 sendZero_(metric.second);
00244 }
00245 stopMetrics_();
00246 inhibit_ = false;
00247 }
00248
00253 void setRunLevel(int level) { runLevel_ = level; }
00258 int getRunLevel() const { return runLevel_; }
00259
00260 protected:
00261 int runLevel_;
00262 fhicl::ParameterSet pset;
00263 double accumulationTime_;
00264 bool inhibit_;
00265
00266 private:
00267 std::unordered_map<std::string, std::list<MetricData>> metricData_;
00268 std::unordered_map<std::string, MetricData> metricRegistry_;
00269 std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
00270
00271 bool readyToSend_(std::string name)
00272 {
00273 auto now = std::chrono::steady_clock::now();
00274 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
00275 {
00276 lastSendTime_[name] = now;
00277 return true;
00278 }
00279
00280 return false;
00281 }
00282
00283 void sendZero_(MetricData data)
00284 {
00285 switch (data.Type)
00286 {
00287 case MetricType::DoubleMetric:
00288 sendMetric_(data.Name, static_cast<double>(0.0), data.Unit);
00289 break;
00290 case MetricType::FloatMetric:
00291 sendMetric_(data.Name, static_cast<float>(0.0), data.Unit);
00292 break;
00293 case MetricType::IntMetric:
00294 sendMetric_(data.Name, static_cast<int>(0), data.Unit);
00295 break;
00296 case MetricType::UnsignedMetric:
00297 sendMetric_(data.Name, static_cast<unsigned long>(0), data.Unit);
00298 break;
00299 default:
00300 break;
00301 }
00302 }
00303
00304 void sendMetric_(MetricData data)
00305 {
00306 switch (data.Type)
00307 {
00308 case MetricType::DoubleMetric:
00309 sendMetric_(data.Name, data.DoubleValue, data.Unit);
00310 break;
00311 case MetricType::FloatMetric:
00312 sendMetric_(data.Name, data.FloatValue, data.Unit);
00313 break;
00314 case MetricType::IntMetric:
00315 sendMetric_(data.Name, data.IntValue, data.Unit);
00316 break;
00317 case MetricType::UnsignedMetric:
00318 sendMetric_(data.Name, data.UnsignedValue, data.Unit);
00319 break;
00320 default:
00321 break;
00322 }
00323 }
00324 };
00325 }
00326
00327 #endif //End ifndef __METRIC_INTERFACE__