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 sendMetrics();
00150 }
00151 }
00152
00156 void sendMetrics()
00157 {
00158 for (auto metric : metricData_)
00159 {
00160 auto metricName = metric.first;
00161 if (readyToSend_(metricName))
00162 {
00163 if (metricData_[metricName].size() == 0 && metricRegistry_.count(metricName))
00164 {
00165 sendZero_(metricRegistry_[metricName]);
00166 }
00167 else if (metricData_[metricName].size() > 0)
00168 {
00169 auto metricMode = metricData_[metricName].back().Mode;
00170 auto metricUnits = metricData_[metricName].back().Unit;
00171 auto metricType = metricData_[metricName].back().Type;
00172
00173 if (metricMode == MetricMode::LastPoint)
00174 {
00175 std::list<MetricData> tmpList(1);
00176 auto lastPoint = metricData_[metricName].back();
00177 tmpList.push_back(lastPoint);
00178 metricData_[metricName].swap(tmpList);
00179 assert(metricData_[metricName].size() == 1);
00180 sendMetric_(lastPoint);
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 for (auto metric : metricRegistry_)
00241 {
00242 sendZero_(metric.second);
00243 }
00244 stopMetrics_();
00245 inhibit_ = false;
00246 }
00247
00252 void setRunLevel(int level) { runLevel_ = level; }
00257 int getRunLevel() const { return runLevel_; }
00258
00259 protected:
00260 int runLevel_;
00261 fhicl::ParameterSet pset;
00262 double accumulationTime_;
00263 bool inhibit_;
00264
00265 private:
00266 std::unordered_map<std::string, std::list<MetricData>> metricData_;
00267 std::unordered_map<std::string, MetricData> metricRegistry_;
00268 std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
00269
00270 bool readyToSend_(std::string name)
00271 {
00272 auto now = std::chrono::steady_clock::now();
00273 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
00274 {
00275 lastSendTime_[name] = now;
00276 return true;
00277 }
00278
00279 return false;
00280 }
00281
00282 void sendZero_(MetricData data)
00283 {
00284 switch (data.Type)
00285 {
00286 case MetricType::DoubleMetric:
00287 sendMetric_(data.Name, static_cast<double>(0.0), data.Unit);
00288 break;
00289 case MetricType::FloatMetric:
00290 sendMetric_(data.Name, static_cast<float>(0.0), data.Unit);
00291 break;
00292 case MetricType::IntMetric:
00293 sendMetric_(data.Name, static_cast<int>(0), data.Unit);
00294 break;
00295 case MetricType::UnsignedMetric:
00296 sendMetric_(data.Name, static_cast<unsigned long>(0), data.Unit);
00297 break;
00298 default:
00299 break;
00300 }
00301 }
00302
00303 void sendMetric_(MetricData data)
00304 {
00305 switch (data.Type)
00306 {
00307 case MetricType::DoubleMetric:
00308 sendMetric_(data.Name, data.DoubleValue, data.Unit);
00309 break;
00310 case MetricType::FloatMetric:
00311 sendMetric_(data.Name, data.FloatValue, data.Unit);
00312 break;
00313 case MetricType::IntMetric:
00314 sendMetric_(data.Name, data.IntValue, data.Unit);
00315 break;
00316 case MetricType::UnsignedMetric:
00317 sendMetric_(data.Name, data.UnsignedValue, data.Unit);
00318 break;
00319 default:
00320 break;
00321 }
00322 }
00323 };
00324 }
00325
00326 #endif //End ifndef __METRIC_INTERFACE__