artdaq_utilities  v1_02_03
 All Classes Namespaces Functions Variables Typedefs
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 
16 namespace artdaq
17 {
23  {
24  public:
38  explicit MetricPlugin(fhicl::ParameterSet const& ps) : pset(ps)
39  , inhibit_(false)
40  {
41  runLevel_ = pset.get<int>("level", 0);
42  accumulationTime_ = pset.get<double>("reporting_interval", 15.0);
43  }
44 
48  virtual ~MetricPlugin() = default;
49 
51  //
52  // Interface Functions: These should be reimplemented in plugin classes!
53  //
55 
59  virtual std::string getLibName() const { return "ERROR"; }
60  protected:
69  virtual void sendMetric_(const std::string& name, const std::string& value, const std::string& unit) = 0;
70 
79  virtual void sendMetric_(const std::string& name, const int& value, const std::string& unit) = 0;
80 
89  virtual void sendMetric_(const std::string& name, const double& value, const std::string& unit) = 0;
90 
99  virtual void sendMetric_(const std::string& name, const float& value, const std::string& unit) = 0;
100 
109  virtual void sendMetric_(const std::string& name, const long unsigned int& value, const std::string& unit) = 0;
110 
116  virtual void startMetrics_() = 0;
117 
123  virtual void stopMetrics_() = 0;
124 
126  //
127  // Implementation Functions: These should be called from ARTDAQ code!
128  //
130  public:
138  void sendMetric(const std::string& name, const std::string& value, const std::string& unit, bool accumulate = true)
139  {
140  if (accumulate)
141  {
142  // There's no sensible way to accumulate string values, just pass them through...
143  sendMetric_(name, value, unit);
144  }
145  else
146  {
147  sendMetric_(name, value, unit);
148  }
149  }
150 
158  void sendMetric(const std::string& name, const int& value, const std::string& unit, bool accumulate = true)
159  {
160  // 22-Jul-2015, KAB - moved push_back here so that we always get the name
161  // added to the map, even if accumulate is false. This helps ensure that a
162  // zero is sent at stop time.
163  intAccumulator_[name].push_back(value);
164 
165  if (!accumulate)
166  {
167  sendMetric_(name, value, unit);
168  intAccumulator_[name].clear();
169  lastSendTime_[name] = std::chrono::steady_clock::now();
170  return;
171  }
172 
173  if (readyToSend_(name))
174  {
175  double sendValue = 0;
176  for (auto val : intAccumulator_[name])
177  {
178  sendValue += val / static_cast<double>(intAccumulator_[name].size());
179  }
180 
181  sendMetric_(name, sendValue, unit);
182 
183  intAccumulator_[name].clear();
184  }
185  }
186 
194  void sendMetric(const std::string& name, const double& value, const std::string& unit, bool accumulate = true)
195  {
196  // 22-Jul-2015, KAB - moved push_back here so that we always get the name
197  // added to the map, even if accumulate is false. This helps ensure that a
198  // zero is sent at stop time.
199  doubleAccumulator_[name].push_back(value);
200 
201  if (!accumulate)
202  {
203  sendMetric_(name, value, unit);
204  doubleAccumulator_[name].clear();
205  lastSendTime_[name] = std::chrono::steady_clock::now();
206  return;
207  }
208 
209  if (readyToSend_(name))
210  {
211  double sendValue = 0;
212  for (auto val : doubleAccumulator_[name])
213  {
214  sendValue += val / doubleAccumulator_[name].size();
215  }
216 
217  sendMetric_(name, sendValue, unit);
218 
219  doubleAccumulator_[name].clear();
220  }
221  }
222 
230  void sendMetric(const std::string& name, const float& value, const std::string& unit, bool accumulate = true)
231  {
232  // 22-Jul-2015, KAB - moved push_back here so that we always get the name
233  // added to the map, even if accumulate is false. This helps ensure that a
234  // zero is sent at stop time.
235  floatAccumulator_[name].push_back(value);
236 
237  if (!accumulate)
238  {
239  sendMetric_(name, value, unit);
240  floatAccumulator_[name].clear();
241  lastSendTime_[name] = std::chrono::steady_clock::now();
242  return;
243  }
244 
245  if (readyToSend_(name))
246  {
247  float sendValue = 0;
248  for (auto val : floatAccumulator_[name])
249  {
250  sendValue += val / floatAccumulator_[name].size();
251  }
252 
253  sendMetric_(name, sendValue, unit);
254 
255  floatAccumulator_[name].clear();
256  }
257  }
258 
266  void sendMetric(const std::string& name, const long unsigned int& value, const std::string& unit, bool accumulate = true)
267  {
268  // 22-Jul-2015, KAB - moved push_back here so that we always get the name
269  // added to the map, even if accumulate is false. This helps ensure that a
270  // zero is sent at stop time.
271  auto uvalue = static_cast<uint32_t>(value);
272  uintAccumulator_[name].push_back(uvalue);
273 
274  if (!accumulate)
275  {
276  sendMetric_(name, value, unit);
277  uintAccumulator_[name].clear();
278  lastSendTime_[name] = std::chrono::steady_clock::now();
279  return;
280  }
281 
282  if (readyToSend_(name))
283  {
284  double sendValue = 0;
285  for (auto val : uintAccumulator_[name])
286  {
287  sendValue += val / static_cast<double>(uintAccumulator_[name].size());
288  }
289 
290  sendMetric_(name, sendValue, unit);
291 
292  uintAccumulator_[name].clear();
293  }
294  }
295 
300 
305  void stopMetrics()
306  {
307  inhibit_ = true;
308  for (auto dv : doubleAccumulator_)
309  {
310  static_cast<std::vector<double>>(dv.second).clear();
311  // 22-Jul-2015, KAB - added cast to get correct call and false to get immediate zero
312  sendMetric(dv.first, static_cast<double>(0.0), "", false);
313  }
314  for (auto iv : intAccumulator_)
315  {
316  static_cast<std::vector<int>>(iv.second).clear();
317  // 22-Jul-2015, KAB - added cast to get correct call and false to get immediate zero
318  sendMetric(iv.first, static_cast<int>(0), "", false);
319  }
320  for (auto fv : floatAccumulator_)
321  {
322  static_cast<std::vector<float>>(fv.second).clear();
323  // 22-Jul-2015, KAB - added cast to get correct call and false to get immediate zero
324  sendMetric(fv.first, static_cast<float>(0.0), "", false);
325  }
326  for (auto uv : uintAccumulator_)
327  {
328  static_cast<std::vector<uint32_t>>(uv.second).clear();
329  // 22-Jul-2015, KAB - added cast to get correct call and false to get immediate zero
330  sendMetric(uv.first, static_cast<long unsigned int>(0), "", false);
331  }
332  stopMetrics_();
333  inhibit_ = false;
334  }
335 
340  void setRunLevel(int level) { runLevel_ = level; }
345  int getRunLevel() const { return runLevel_; }
346 
347  protected:
348  int runLevel_;
349  fhicl::ParameterSet pset;
351  bool inhibit_;
352 
353  private:
354  std::unordered_map<std::string, std::vector<double>> doubleAccumulator_;
355  std::unordered_map<std::string, std::vector<int>> intAccumulator_;
356  std::unordered_map<std::string, std::vector<float>> floatAccumulator_;
357  std::unordered_map<std::string, std::vector<uint32_t>> uintAccumulator_;
358  std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
359 
360  bool readyToSend_(std::string name)
361  {
362  auto now = std::chrono::steady_clock::now();
363  if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
364  {
365  lastSendTime_[name] = now;
366  return true;
367  }
368 
369  return false;
370  }
371  };
372 } //End namespace artdaq
373 
374 #endif //End ifndef __METRIC_INTERFACE__
virtual void startMetrics_()=0
Perform any start-up actions necessary for the metric plugin.
void sendMetric(const std::string &name, const long unsigned int &value, const std::string &unit, bool accumulate=true)
Send a metric value to the MetricPlugin.
void sendMetric(const std::string &name, const double &value, const std::string &unit, bool accumulate=true)
Send a metric value to the MetricPlugin.
The MetricPlugin class defines the interface that MetricManager uses to send metric data to the vario...
Definition: MetricPlugin.hh:22
void startMetrics()
Perform startup actions. Simply calls the virtual startMetrics_ function.
MetricPlugin(fhicl::ParameterSet const &ps)
MetricPlugin Constructor.
Definition: MetricPlugin.hh:38
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.)
void sendMetric(const std::string &name, const float &value, const std::string &unit, bool accumulate=true)
Send a metric value to the MetricPlugin.
void stopMetrics()
Perform shutdown actions. Zeroes out all accumulators, and sends zeros for each metric. Calls stopMetrics_() for any plugin-defined shutdown actions.
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:59
virtual void stopMetrics_()=0
Perform any shutdown actions necessary for the metric plugin.
double accumulationTime_
The amount of time to average metric values; except for accumulate=false metrics, will be the interva...
void sendMetric(const std::string &name, const int &value, const std::string &unit, bool accumulate=true)
Send a metric value to the MetricPlugin.
void sendMetric(const std::string &name, const std::string &value, const std::string &unit, bool accumulate=true)
Send a metric value to the MetricPlugin.
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 ...