artdaq_utilities  v1_04_01
MetricPlugin.hh
1 // MetricPlugin.hh: Metric Plugin Interface
2 // Author: Eric Flumerfelt
3 // Last Modified: 11/05/2014 (Created)
4 //
5 // Defines the interface that any ARTDAQ metric plugin must implement
6 
7 
8 #ifndef __METRIC_INTERFACE__
9 #define __METRIC_INTERFACE__
10 
11 #include <string>
12 #include <chrono>
13 #include <unordered_map>
14 #include "fhiclcpp/ParameterSet.h"
15 #include "artdaq-utilities/Plugins/MetricData.hh"
16 
17 namespace artdaq
18 {
24  {
25  public:
39  explicit MetricPlugin(fhicl::ParameterSet const& ps) : pset(ps)
40  , inhibit_(false)
41  {
42  runLevel_ = pset.get<int>("level", 0);
43  accumulationTime_ = pset.get<double>("reporting_interval", 15.0);
44  }
45 
49  virtual ~MetricPlugin() = default;
50 
52  //
53  // Interface Functions: These should be reimplemented in plugin classes!
54  //
56 
60  virtual std::string getLibName() const { return "ERROR"; }
61  protected:
70  virtual void sendMetric_(const std::string& name, const std::string& value, const std::string& unit) = 0;
71 
80  virtual void sendMetric_(const std::string& name, const int& value, const std::string& unit) = 0;
81 
90  virtual void sendMetric_(const std::string& name, const double& value, const std::string& unit) = 0;
91 
100  virtual void sendMetric_(const std::string& name, const float& value, const std::string& unit) = 0;
101 
110  virtual void sendMetric_(const std::string& name, const long unsigned int& value, const std::string& unit) = 0;
111 
117  virtual void startMetrics_() = 0;
118 
124  virtual void stopMetrics_() = 0;
125 
127  //
128  // Implementation Functions: These should be called from ARTDAQ code!
129  //
131  public:
137  {
138  if (data.Type == MetricType::StringMetric)
139  {
140  sendMetric_(data.Name, data.StringValue, data.Unit);
141  }
142  else
143  {
144  if (!metricRegistry_.count(data.Name))
145  {
146  metricRegistry_[data.Name] = data;
147  }
148  metricData_[data.Name].push_back(data);
149  //sendMetrics();
150  }
151  }
152 
157  void sendMetrics(bool forceSend = false)
158  {
159  for (auto metric : metricData_)
160  {
161  auto metricName = metric.first;
162  if (readyToSend_(metricName) || forceSend)
163  {
164  if (metricData_[metricName].size() == 0 && metricRegistry_.count(metricName))
165  {
166  sendZero_(metricRegistry_[metricName]);
167  }
168  else if (metricData_[metricName].size() > 0)
169  {
170  auto metricMode = metricData_[metricName].back().Mode;
171  auto metricUnits = metricData_[metricName].back().Unit;
172  auto metricType = metricData_[metricName].back().Type;
173 
174  if (metricMode == MetricMode::LastPoint)
175  {
176  if (metricData_[metricName].size() > 1)
177  {
178  metricData_[metricName].erase(metricData_[metricName].begin(), std::prev(metricData_[metricName].end()));
179  }
180  sendMetric_(metricData_[metricName].back());
181  }
182  else
183  {
184  switch (metricType)
185  {
187  {
188  auto ds = 0.0;
189  for (auto& mv : metricData_[metricName]) { ds += mv.DoubleValue; }
190  if (metricMode == MetricMode::Average) { ds /= metricData_[metricName].size(); }
191  sendMetric_(metricName, ds, metricUnits);
192  }
193  break;
195  {
196  auto fs = 0.0;
197  for (auto& mv : metricData_[metricName]) { fs += mv.FloatValue; }
198  if (metricMode == MetricMode::Average) { fs /= metricData_[metricName].size(); }
199  sendMetric_(metricName, fs, metricUnits);
200  }
201  break;
203  {
204  auto is = 0;
205  for (auto& mv : metricData_[metricName]) { is += mv.IntValue; }
206  if (metricMode == MetricMode::Average) { is /= metricData_[metricName].size(); }
207  sendMetric_(metricName, is, metricUnits);
208  }
209  break;
211  {
212  auto us = 0;
213  for (auto& mv : metricData_[metricName]) { us += mv.UnsignedValue; }
214  if (metricMode == MetricMode::Average) { us /= metricData_[metricName].size(); }
215  sendMetric_(metricName, us, metricUnits);
216  }
217  break;
218  default:
219  break;
220  }
221  metricData_[metricName].clear();
222  }
223  }
224  }
225  }
226  }
227 
232 
237  void stopMetrics()
238  {
239  inhibit_ = true;
240  sendMetrics(true);
241  for (auto metric : metricRegistry_)
242  {
243  sendZero_(metric.second);
244  }
245  stopMetrics_();
246  inhibit_ = false;
247  }
248 
253  void setRunLevel(int level) { runLevel_ = level; }
258  int getRunLevel() const { return runLevel_; }
259 
260  protected:
261  int runLevel_;
262  fhicl::ParameterSet pset;
264  bool inhibit_;
265 
266  private:
267  std::unordered_map<std::string, std::list<MetricData>> metricData_;
268  std::unordered_map<std::string, MetricData> metricRegistry_;
269  std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
270 
271  bool readyToSend_(std::string name)
272  {
273  auto now = std::chrono::steady_clock::now();
274  if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
275  {
276  lastSendTime_[name] = now;
277  return true;
278  }
279 
280  return false;
281  }
282 
283  void sendZero_(MetricData data)
284  {
285  switch (data.Type)
286  {
288  sendMetric_(data.Name, static_cast<double>(0.0), data.Unit);
289  break;
291  sendMetric_(data.Name, static_cast<float>(0.0), data.Unit);
292  break;
294  sendMetric_(data.Name, static_cast<int>(0), data.Unit);
295  break;
297  sendMetric_(data.Name, static_cast<unsigned long>(0), data.Unit);
298  break;
299  default:
300  break;
301  }
302  }
303 
304  void sendMetric_(MetricData data)
305  {
306  switch (data.Type)
307  {
309  sendMetric_(data.Name, data.DoubleValue, data.Unit);
310  break;
312  sendMetric_(data.Name, data.FloatValue, data.Unit);
313  break;
315  sendMetric_(data.Name, data.IntValue, data.Unit);
316  break;
318  sendMetric_(data.Name, data.UnsignedValue, data.Unit);
319  break;
320  default:
321  break;
322  }
323  }
324  };
325 } //End namespace artdaq
326 
327 #endif //End ifndef __METRIC_INTERFACE__
virtual void startMetrics_()=0
Perform any start-up actions necessary for the metric plugin.
std::string StringValue
Value of the metric, if it is a MetricType::StringMetric
Definition: MetricData.hh:76
The MetricPlugin class defines the interface that MetricManager uses to send metric data to the vario...
Definition: MetricPlugin.hh:23
void startMetrics()
Perform startup actions. Simply calls the virtual startMetrics_ function.
MetricPlugin(fhicl::ParameterSet const &ps)
MetricPlugin Constructor.
Definition: MetricPlugin.hh:39
Report the average of all values. Use for rates to report accurate results.
fhicl::ParameterSet pset
The ParameterSet used to configure the MetricPlugin.
virtual void sendMetric_(const std::string &name, const std::string &value, const std::string &unit)=0
Send a metric to the underlying metric storage (file, Graphite, Ganglia, etc.)
std::string Unit
Units of the metric
Definition: MetricData.hh:96
Metric is a std::string (not in union)
std::string Name
Name of the metric
Definition: MetricData.hh:72
void addMetricData(MetricData data)
Send a metric value to the MetricPlugin.
void sendMetrics(bool forceSend=false)
For each known metric, determine whether the reporting interval has elapsed, and if so...
void stopMetrics()
Perform shutdown actions. Zeroes out all accumulators, and sends zeros for each metric. Calls stopMetrics_() for any plugin-defined shutdown actions.
Metric is a long unsigned int.
int getRunLevel() const
Get the threshold for sending metrics to the underlying storage.
virtual std::string getLibName() const
Return the name of the current MetricPlugin instance.
Definition: MetricPlugin.hh:60
virtual void stopMetrics_()=0
Perform any shutdown actions necessary for the metric plugin.
MetricType Type
Type of the metric
Definition: MetricData.hh:92
double accumulationTime_
The amount of time to average metric values; except for accumulate=false metrics, will be the interva...
Small structure used to hold a metric data point before sending to the metric plugins ...
Definition: MetricData.hh:41
Report only the last value recorded. Useful for event counters, run numbers, etc. ...
virtual ~MetricPlugin()=default
Default virtual Desctructor.
void setRunLevel(int level)
Set the threshold for sending metrics to the underlying storage.
bool inhibit_
Whether to inhibit all metric sending.
int runLevel_
The threshold for sending metrics to the underlying storage. Metrics with level &lt;= to runLevel_ will ...