artdaq_utilities  v1_04_00
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 
156  void sendMetrics()
157  {
158  for (auto metric : metricData_)
159  {
160  auto metricName = metric.first;
161  if (readyToSend_(metricName))
162  {
163  if (metricData_[metricName].size() == 0 && metricRegistry_.count(metricName))
164  {
165  sendZero_(metricRegistry_[metricName]);
166  }
167  else if (metricData_[metricName].size() > 0)
168  {
169  auto metricMode = metricData_[metricName].back().Mode;
170  auto metricUnits = metricData_[metricName].back().Unit;
171  auto metricType = metricData_[metricName].back().Type;
172 
173  if (metricMode == MetricMode::LastPoint)
174  {
175  if (metricData_[metricName].size() > 1)
176  {
177  metricData_[metricName].erase(metricData_[metricName].begin(), std::prev(metricData_[metricName].end()));
178  }
179  sendMetric_(metricData_[metricName].back());
180  }
181  else
182  {
183  switch (metricType)
184  {
186  {
187  auto ds = 0.0;
188  for (auto& mv : metricData_[metricName]) { ds += mv.DoubleValue; }
189  if (metricMode == MetricMode::Average) { ds /= metricData_[metricName].size(); }
190  sendMetric_(metricName, ds, metricUnits);
191  }
192  break;
194  {
195  auto fs = 0.0;
196  for (auto& mv : metricData_[metricName]) { fs += mv.FloatValue; }
197  if (metricMode == MetricMode::Average) { fs /= metricData_[metricName].size(); }
198  sendMetric_(metricName, fs, metricUnits);
199  }
200  break;
202  {
203  auto is = 0;
204  for (auto& mv : metricData_[metricName]) { is += mv.IntValue; }
205  if (metricMode == MetricMode::Average) { is /= metricData_[metricName].size(); }
206  sendMetric_(metricName, is, metricUnits);
207  }
208  break;
210  {
211  auto us = 0;
212  for (auto& mv : metricData_[metricName]) { us += mv.UnsignedValue; }
213  if (metricMode == MetricMode::Average) { us /= metricData_[metricName].size(); }
214  sendMetric_(metricName, us, metricUnits);
215  }
216  break;
217  default:
218  break;
219  }
220  metricData_[metricName].clear();
221  }
222  }
223  }
224  }
225  }
226 
231 
236  void stopMetrics()
237  {
238  inhibit_ = true;
239  for (auto metric : metricRegistry_)
240  {
241  sendZero_(metric.second);
242  }
243  stopMetrics_();
244  inhibit_ = false;
245  }
246 
251  void setRunLevel(int level) { runLevel_ = level; }
256  int getRunLevel() const { return runLevel_; }
257 
258  protected:
259  int runLevel_;
260  fhicl::ParameterSet pset;
262  bool inhibit_;
263 
264  private:
265  std::unordered_map<std::string, std::list<MetricData>> metricData_;
266  std::unordered_map<std::string, MetricData> metricRegistry_;
267  std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
268 
269  bool readyToSend_(std::string name)
270  {
271  auto now = std::chrono::steady_clock::now();
272  if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
273  {
274  lastSendTime_[name] = now;
275  return true;
276  }
277 
278  return false;
279  }
280 
281  void sendZero_(MetricData data)
282  {
283  switch (data.Type)
284  {
286  sendMetric_(data.Name, static_cast<double>(0.0), data.Unit);
287  break;
289  sendMetric_(data.Name, static_cast<float>(0.0), data.Unit);
290  break;
292  sendMetric_(data.Name, static_cast<int>(0), data.Unit);
293  break;
295  sendMetric_(data.Name, static_cast<unsigned long>(0), data.Unit);
296  break;
297  default:
298  break;
299  }
300  }
301 
302  void sendMetric_(MetricData data)
303  {
304  switch (data.Type)
305  {
307  sendMetric_(data.Name, data.DoubleValue, data.Unit);
308  break;
310  sendMetric_(data.Name, data.FloatValue, data.Unit);
311  break;
313  sendMetric_(data.Name, data.IntValue, data.Unit);
314  break;
316  sendMetric_(data.Name, data.UnsignedValue, data.Unit);
317  break;
318  default:
319  break;
320  }
321  }
322  };
323 } //End namespace artdaq
324 
325 #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 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
void sendMetrics()
For each known metric, determine whether the reporting interval has elapsed, and if so...
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 ...