artdaq_utilities  v1_03_00
 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 #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  std::list<MetricData> tmpList(1);
176  auto lastPoint = metricData_[metricName].back();
177  tmpList.push_back(lastPoint);
178  metricData_[metricName].swap(tmpList);
179  assert(metricData_[metricName].size() == 1);
180  sendMetric_(lastPoint);
181  }
182  else
183  {
184  switch (metricType)
185  {
186  case MetricType::DoubleMetric:
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;
194  case MetricType::FloatMetric:
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;
202  case MetricType::IntMetric:
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;
210  case MetricType::UnsignedMetric:
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  for (auto metric : metricRegistry_)
241  {
242  sendZero_(metric.second);
243  }
244  stopMetrics_();
245  inhibit_ = false;
246  }
247 
252  void setRunLevel(int level) { runLevel_ = level; }
257  int getRunLevel() const { return runLevel_; }
258 
259  protected:
260  int runLevel_;
261  fhicl::ParameterSet pset;
263  bool inhibit_;
264 
265  private:
266  std::unordered_map<std::string, std::list<MetricData>> metricData_;
267  std::unordered_map<std::string, MetricData> metricRegistry_;
268  std::unordered_map<std::string, std::chrono::steady_clock::time_point> lastSendTime_;
269 
270  bool readyToSend_(std::string name)
271  {
272  auto now = std::chrono::steady_clock::now();
273  if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(now - lastSendTime_[name]).count() >= accumulationTime_)
274  {
275  lastSendTime_[name] = now;
276  return true;
277  }
278 
279  return false;
280  }
281 
282  void sendZero_(MetricData data)
283  {
284  switch (data.Type)
285  {
286  case MetricType::DoubleMetric:
287  sendMetric_(data.Name, static_cast<double>(0.0), data.Unit);
288  break;
289  case MetricType::FloatMetric:
290  sendMetric_(data.Name, static_cast<float>(0.0), data.Unit);
291  break;
292  case MetricType::IntMetric:
293  sendMetric_(data.Name, static_cast<int>(0), data.Unit);
294  break;
295  case MetricType::UnsignedMetric:
296  sendMetric_(data.Name, static_cast<unsigned long>(0), data.Unit);
297  break;
298  default:
299  break;
300  }
301  }
302 
303  void sendMetric_(MetricData data)
304  {
305  switch (data.Type)
306  {
307  case MetricType::DoubleMetric:
308  sendMetric_(data.Name, data.DoubleValue, data.Unit);
309  break;
310  case MetricType::FloatMetric:
311  sendMetric_(data.Name, data.FloatValue, data.Unit);
312  break;
313  case MetricType::IntMetric:
314  sendMetric_(data.Name, data.IntValue, data.Unit);
315  break;
316  case MetricType::UnsignedMetric:
317  sendMetric_(data.Name, data.UnsignedValue, data.Unit);
318  break;
319  default:
320  break;
321  }
322  }
323  };
324 } //End namespace artdaq
325 
326 #endif //End ifndef __METRIC_INTERFACE__
virtual void startMetrics_()=0
Perform any start-up actions necessary for the metric plugin.
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
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 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.
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.
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...
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 ...