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 if (metricData_[metricName].size() > 1)
00176 {
00177 metricData_[metricName].erase(metricData_[metricName].begin(), std::prev(metricData_[metricName].end()));
00178 }
00179 sendMetric_(metricData_[metricName].back());
00180 }
00181 else
00182 {
00183 switch (metricType)
00184 {
00185 case MetricType::DoubleMetric:
00186 {
00187 auto ds = 0.0;
00188 for (auto& mv : metricData_[metricName]) { ds += mv.DoubleValue; }
00189 if (metricMode == MetricMode::Average) { ds /= metricData_[metricName].size(); }
00190 sendMetric_(metricName, ds, metricUnits);
00191 }
00192 break;
00193 case MetricType::FloatMetric:
00194 {
00195 auto fs = 0.0;
00196 for (auto& mv : metricData_[metricName]) { fs += mv.FloatValue; }
00197 if (metricMode == MetricMode::Average) { fs /= metricData_[metricName].size(); }
00198 sendMetric_(metricName, fs, metricUnits);
00199 }
00200 break;
00201 case MetricType::IntMetric:
00202 {
00203 auto is = 0;
00204 for (auto& mv : metricData_[metricName]) { is += mv.IntValue; }
00205 if (metricMode == MetricMode::Average) { is /= metricData_[metricName].size(); }
00206 sendMetric_(metricName, is, metricUnits);
00207 }
00208 break;
00209 case MetricType::UnsignedMetric:
00210 {
00211 auto us = 0;
00212 for (auto& mv : metricData_[metricName]) { us += mv.UnsignedValue; }
00213 if (metricMode == MetricMode::Average) { us /= metricData_[metricName].size(); }
00214 sendMetric_(metricName, us, metricUnits);
00215 }
00216 break;
00217 default:
00218 break;
00219 }
00220 metricData_[metricName].clear();
00221 }
00222 }
00223 }
00224 }
00225 }
00226
00230 void startMetrics() { startMetrics_(); }
00231
00236 void stopMetrics()
00237 {
00238 inhibit_ = true;
00239 for (auto metric : metricRegistry_)
00240 {
00241 sendZero_(metric.second);
00242 }
00243 stopMetrics_();
00244 inhibit_ = false;
00245 }
00246
00251 void setRunLevel(int level) { runLevel_ = level; }
00256 int getRunLevel() const { return runLevel_; }
00257
00258 protected:
00259 int runLevel_;
00260 fhicl::ParameterSet pset;
00261 double accumulationTime_;
00262 bool inhibit_;
00263
00264 private:
00265 std::unordered_map<std::string, std::list<MetricData>> metricData_;
00266 std::unordered_map<std::string, MetricData> metricRegistry_;
00267 std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
00268
00269 bool readyToSend_(std::string name)
00270 {
00271 auto now = std::chrono::steady_clock::now();
00272 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
00273 {
00274 lastSendTime_[name] = now;
00275 return true;
00276 }
00277
00278 return false;
00279 }
00280
00281 void sendZero_(MetricData data)
00282 {
00283 switch (data.Type)
00284 {
00285 case MetricType::DoubleMetric:
00286 sendMetric_(data.Name, static_cast<double>(0.0), data.Unit);
00287 break;
00288 case MetricType::FloatMetric:
00289 sendMetric_(data.Name, static_cast<float>(0.0), data.Unit);
00290 break;
00291 case MetricType::IntMetric:
00292 sendMetric_(data.Name, static_cast<int>(0), data.Unit);
00293 break;
00294 case MetricType::UnsignedMetric:
00295 sendMetric_(data.Name, static_cast<unsigned long>(0), data.Unit);
00296 break;
00297 default:
00298 break;
00299 }
00300 }
00301
00302 void sendMetric_(MetricData data)
00303 {
00304 switch (data.Type)
00305 {
00306 case MetricType::DoubleMetric:
00307 sendMetric_(data.Name, data.DoubleValue, data.Unit);
00308 break;
00309 case MetricType::FloatMetric:
00310 sendMetric_(data.Name, data.FloatValue, data.Unit);
00311 break;
00312 case MetricType::IntMetric:
00313 sendMetric_(data.Name, data.IntValue, data.Unit);
00314 break;
00315 case MetricType::UnsignedMetric:
00316 sendMetric_(data.Name, data.UnsignedValue, data.Unit);
00317 break;
00318 default:
00319 break;
00320 }
00321 }
00322 };
00323 }
00324
00325 #endif //End ifndef __METRIC_INTERFACE__