artdaq_utilities  v1_05_07
MetricManager.cc
1 // MetricManager.cc: MetricManager class implementation file
2 // Author: Eric Flumerfelt
3 // Last Modified: 11/14/2014
4 //
5 // MetricManager loads a user-specified set of plugins, sends them their configuration,
6 // and sends them data as it is recieved. It also maintains the state of the plugins
7 // relative to the application state.
8 
9 #define TRACE_NAME "MetricManager"
10 #include "artdaq-utilities/Plugins/MetricManager.hh"
11 #include "artdaq-utilities/Plugins/makeMetricPlugin.hh"
12 #include "fhiclcpp/ParameterSet.h"
13 #include "tracemf.h"
14 
15 #include <boost/exception/all.hpp>
16 #include <chrono>
17 #include <memory>
18 
20  : metric_plugins_(0)
21  , system_metric_collector_(nullptr)
22  , initialized_(false)
23  , running_(false)
24  , active_(false)
25  , busy_(false)
26  , missed_metric_calls_(0)
27  , metric_calls_(0) {}
28 
29 artdaq::MetricManager::~MetricManager() noexcept { shutdown(); }
30 
31 void artdaq::MetricManager::initialize(fhicl::ParameterSet const& pset, std::string const& prefix)
32 {
33  prefix_ = prefix;
34  if (initialized_)
35  {
36  shutdown();
37  }
38  TLOG(TLVL_INFO) << "Configuring metrics with parameter set: " << pset.to_string();
39 
40  std::vector<std::string> names = pset.get_names();
41 
42  metric_plugins_.clear();
43  bool send_system_metrics = false;
44  bool send_process_metrics = false;
45 
46  for (const auto& name : names)
47  {
48  if (name == "metric_queue_size")
49  {
50  metric_cache_max_size_ = pset.get<size_t>("metric_queue_size");
51  }
52  else if (name == "metric_queue_notify_size")
53  {
54  metric_cache_notify_size_ = pset.get<size_t>("metric_queue_notify_size");
55  }
56  else if (name == "metric_cache_size")
57  {
58  metric_cache_max_size_ = pset.get<size_t>("metric_cache_size");
59  }
60  else if (name == "metric_cache_notify_size")
61  {
62  metric_cache_notify_size_ = pset.get<size_t>("metric_cache_notify_size");
63  }
64  else if (name == "metric_send_maximum_delay_ms")
65  {
66  TLOG(TLVL_INFO) << "Setting metric_send_interval_ms_ to " << pset.get<int>("metric_send_maximum_delay_ms");
67  metric_send_interval_ms_ = pset.get<int>("metric_send_maximum_delay_ms");
68  }
69  else if (name == "metric_holdoff_us")
70  {
71  TLOG(TLVL_INFO) << "Setting metric_holdoff_us_ to " << pset.get<int>("metric_holdoff_us");
72  metric_holdoff_us_ = pset.get<int>("metric_holdoff_us");
73  }
74  else if (name == "send_system_metrics")
75  {
76  send_system_metrics = pset.get<bool>("send_system_metrics");
77  }
78  else if (name == "send_process_metrics")
79  {
80  send_process_metrics = pset.get<bool>("send_process_metrics");
81  }
82  else
83  {
84  try
85  {
86  TLOG(TLVL_DEBUG) << "Constructing metric plugin with name " << name;
87  auto plugin_pset = pset.get<fhicl::ParameterSet>(name);
88  metric_plugins_.push_back(
89  makeMetricPlugin(plugin_pset.get<std::string>("metricPluginType", ""), plugin_pset, prefix_));
90  }
91  catch (const cet::exception& e)
92  {
93  TLOG(TLVL_ERROR) << "Exception caught in MetricManager::initialize, error loading plugin with name " << name
94  << ", cet::exception object caught:" << e.explain_self();
95  }
96  catch (const boost::exception& e)
97  {
98  TLOG(TLVL_ERROR) << "Exception caught in MetricManager::initialize, error loading plugin with name " << name
99  << ", boost::exception object caught: " << boost::diagnostic_information(e);
100  }
101  catch (const std::exception& e)
102  {
103  TLOG(TLVL_ERROR) << "Exception caught in MetricManager::initialize, error loading plugin with name " << name
104  << ", std::exception caught: " << e.what();
105  }
106  catch (...)
107  {
108  TLOG(TLVL_ERROR) << "Unknown Exception caught in MetricManager::initialize, error loading plugin with name "
109  << name;
110  }
111  }
112  }
113 
114  if (send_system_metrics || send_process_metrics)
115  {
116  system_metric_collector_ = std::make_unique<SystemMetricCollector>(send_process_metrics, send_system_metrics);
117  }
118 
119  initialized_ = true;
120 }
121 
123 {
124  std::lock_guard<std::mutex> lk(metric_mutex_);
125  if (!running_)
126  {
127  TLOG(TLVL_DEBUG) << "Starting MetricManager";
128  for (auto& metric : metric_plugins_)
129  {
130  if (!metric)
131  {
132  continue;
133  }
134  try
135  {
136  metric->startMetrics();
137  TLOG(TLVL_INFO) << "Metric Plugin " << metric->getLibName() << " started.";
138  active_ = true;
139  }
140  catch (...)
141  {
142  TLOG(TLVL_ERROR) << "Exception caught in MetricManager::do_start(), error starting plugin with name "
143  << metric->getLibName();
144  }
145  }
146  running_ = true;
147  startMetricLoop_();
148  }
149 }
150 
152 {
153  std::unique_lock<std::mutex> lk(metric_mutex_);
154  TLOG(TLVL_DEBUG) << "Stopping Metrics";
155  running_ = false;
156  metric_cv_.notify_all();
157  TLOG(TLVL_DEBUG) << "Joining Metric-Sending thread";
158  lk.unlock();
159  try
160  {
161  if (metric_sending_thread_.joinable())
162  {
163  metric_sending_thread_.join();
164  }
165  }
166  catch (...)
167  {
168  // IGNORED
169  }
170  TLOG(TLVL_DEBUG) << "do_stop Complete";
171 }
172 
174 { /*do_stop();*/
175 }
177 { /*do_start();*/
178 }
179 
180 void artdaq::MetricManager::reinitialize(fhicl::ParameterSet const& pset, std::string const& prefix)
181 {
182  shutdown();
183  initialize(pset, prefix);
184 }
185 
187 {
188  TLOG(TLVL_DEBUG) << "MetricManager is shutting down...";
189  do_stop();
190 
191  std::lock_guard<std::mutex> lk(metric_mutex_);
192  if (initialized_)
193  {
194  initialized_ = false;
195  for (auto& i : metric_plugins_)
196  {
197  try
198  {
199  std::string name = i->getLibName();
200  i.reset(nullptr);
201  TLOG(TLVL_DEBUG) << "Metric Plugin " << name << " shutdown.";
202  }
203  catch (...)
204  {
205  TLOG(TLVL_ERROR) << "Exception caught in MetricManager::shutdown(), error shutting down metric with name "
206  << i->getLibName();
207  }
208  }
209  metric_plugins_.clear();
210  }
211 }
212 
213 void artdaq::MetricManager::sendMetric(std::string const& name, std::string const& value, std::string const& unit,
214  int level, MetricMode mode, std::string const& metricPrefix,
215  bool useNameOverride)
216 {
217  if (!initialized_)
218  {
219  TLOG(TLVL_WARNING) << "Attempted to send metric " << name << " when MetricManager has not yet been initialized!";
220  }
221  else if (!running_)
222  {
223  TLOG(TLVL_INFO) << "Attempted to send metric when MetricManager stopped!";
224  }
225  else if (active_)
226  {
227  {
228  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
229  metric_calls_++;
230  last_metric_received_ = std::chrono::steady_clock::now();
231  auto& cached = metric_cache_[name];
232  if (cached == nullptr)
233  {
234  metric_cache_[name] = std::make_unique<MetricData>(name, value, unit, level, mode, metricPrefix, useNameOverride);
235  }
236  else
237  {
238  auto size = cached->DataPointCount;
239  if (size < metric_cache_max_size_)
240  {
241  if (size >= metric_cache_notify_size_)
242  {
243  TLOG(9) << "Metric cache is at size " << size << " of " << metric_cache_max_size_ << " for metric " << name
244  << ".";
245  }
246  if (mode == MetricMode::LastPoint)
247  {
248  cached->StringValue = value;
249  cached->DataPointCount = 1;
250  }
251  else
252  {
253  cached->StringValue += " " + value;
254  cached->DataPointCount++;
255  }
256  }
257  else
258  {
259  TLOG(10) << "Rejecting metric because queue full";
260  missed_metric_calls_++;
261  }
262  }
263  }
264  metric_cv_.notify_all();
265  }
266 }
267 
268 void artdaq::MetricManager::sendMetric(std::string const& name, int const& value, std::string const& unit, int level,
269  MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
270 {
271  if (!initialized_)
272  {
273  TLOG(TLVL_WARNING) << "Attempted to send metric " << name << " when MetricManager has not yet been initialized!";
274  }
275  else if (!running_)
276  {
277  TLOG(TLVL_INFO) << "Attempted to send metric when MetricManager stopped!";
278  }
279  else if (active_)
280  {
281  {
282  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
283  metric_calls_++;
284  last_metric_received_ = std::chrono::steady_clock::now();
285  auto& cached = metric_cache_[name];
286  if (cached == nullptr)
287  {
288  metric_cache_[name] = std::make_unique<MetricData>(name, value, unit, level, mode, metricPrefix, useNameOverride);
289  }
290  else
291  {
292  auto size = cached->DataPointCount;
293  if (size < metric_cache_max_size_)
294  {
295  if (size >= metric_cache_notify_size_)
296  {
297  TLOG(9) << "Metric cache is at size " << size << " of " << metric_cache_max_size_ << " for metric " << name
298  << ".";
299  }
300  cached->AddPoint(value);
301  }
302  else
303  {
304  TLOG(10) << "Rejecting metric because queue full";
305  missed_metric_calls_++;
306  }
307  }
308  }
309  metric_cv_.notify_all();
310  }
311 }
312 
313 void artdaq::MetricManager::sendMetric(std::string const& name, double const& value, std::string const& unit, int level,
314  MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
315 {
316  if (!initialized_)
317  {
318  TLOG(TLVL_WARNING) << "Attempted to send metric " << name << " when MetricManager has not yet been initialized!";
319  }
320  else if (!running_)
321  {
322  TLOG(TLVL_INFO) << "Attempted to send metric when MetricManager stopped!";
323  }
324  else if (active_)
325  {
326  {
327  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
328  metric_calls_++;
329  last_metric_received_ = std::chrono::steady_clock::now();
330  auto& cached = metric_cache_[name];
331  if (cached == nullptr)
332  {
333  metric_cache_[name] = std::make_unique<MetricData>(name, value, unit, level, mode, metricPrefix, useNameOverride);
334  }
335  else
336  {
337  auto size = cached->DataPointCount;
338  if (size < metric_cache_max_size_)
339  {
340  if (size >= metric_cache_notify_size_)
341  {
342  TLOG(9) << "Metric cache is at size " << size << " of " << metric_cache_max_size_ << " for metric " << name
343  << ".";
344  }
345  cached->AddPoint(value);
346  }
347  else
348  {
349  TLOG(10) << "Rejecting metric because queue full";
350  missed_metric_calls_++;
351  }
352  }
353  }
354  metric_cv_.notify_all();
355  }
356 }
357 
358 void artdaq::MetricManager::sendMetric(std::string const& name, float const& value, std::string const& unit, int level,
359  MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
360 {
361  if (!initialized_)
362  {
363  TLOG(TLVL_WARNING) << "Attempted to send metric " << name << " when MetricManager has not yet been initialized!";
364  }
365  else if (!running_)
366  {
367  TLOG(TLVL_INFO) << "Attempted to send metric when MetricManager stopped!";
368  }
369  else if (active_)
370  {
371  {
372  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
373  metric_calls_++;
374  last_metric_received_ = std::chrono::steady_clock::now();
375  auto& cached = metric_cache_[name];
376  if (cached == nullptr)
377  {
378  metric_cache_[name] = std::make_unique<MetricData>(name, value, unit, level, mode, metricPrefix, useNameOverride);
379  }
380  else
381  {
382  auto size = cached->DataPointCount;
383  if (size < metric_cache_max_size_)
384  {
385  if (size >= metric_cache_notify_size_)
386  {
387  TLOG(9) << "Metric cache is at size " << size << " of " << metric_cache_max_size_ << " for metric " << name
388  << ".";
389  }
390  cached->AddPoint(value);
391  }
392  else
393  {
394  TLOG(10) << "Rejecting metric because queue full";
395  missed_metric_calls_++;
396  }
397  }
398  }
399  metric_cv_.notify_all();
400  }
401 }
402 
403 void artdaq::MetricManager::sendMetric(std::string const& name, uint64_t const& value, std::string const& unit,
404  int level, MetricMode mode, std::string const& metricPrefix,
405  bool useNameOverride)
406 {
407  if (!initialized_)
408  {
409  TLOG(TLVL_WARNING) << "Attempted to send metric " << name << " when MetricManager has not yet been initialized!";
410  }
411  else if (!running_)
412  {
413  TLOG(TLVL_INFO) << "Attempted to send metric when MetricManager stopped!";
414  }
415  else if (active_)
416  {
417  {
418  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
419  metric_calls_++;
420  last_metric_received_ = std::chrono::steady_clock::now();
421  auto& cached = metric_cache_[name];
422  if (cached == nullptr)
423  {
424  metric_cache_[name] = std::make_unique<MetricData>(name, value, unit, level, mode, metricPrefix, useNameOverride);
425  }
426  else
427  {
428  auto size = cached->DataPointCount;
429  if (size < metric_cache_max_size_)
430  {
431  if (size >= metric_cache_notify_size_)
432  {
433  TLOG(9) << "Metric cache is at size " << size << " of " << metric_cache_max_size_ << " for metric " << name
434  << ".";
435  }
436  cached->AddPoint(value);
437  }
438  else
439  {
440  TLOG(10) << "Rejecting metric because queue full";
441  missed_metric_calls_++;
442  }
443  }
444  }
445  metric_cv_.notify_all();
446  }
447 }
448 
449 void artdaq::MetricManager::startMetricLoop_()
450 {
451  if (metric_sending_thread_.joinable())
452  {
453  metric_sending_thread_.join();
454  }
455  boost::thread::attributes attrs;
456  attrs.set_stack_size(4096 * 2000); // 8000 KB
457  TLOG(TLVL_INFO) << "Starting Metric Sending Thread";
458  try
459  {
460  metric_sending_thread_ = boost::thread(attrs, boost::bind(&MetricManager::sendMetricLoop_, this));
461  }
462  catch (const boost::exception& e)
463  {
464  TLOG(TLVL_ERROR) << "Caught boost::exception starting Metric Sending thread: " << boost::diagnostic_information(e)
465  << ", errno=" << errno;
466  std::cerr << "Caught boost::exception starting Metric Sending thread: " << boost::diagnostic_information(e)
467  << ", errno=" << errno << std::endl;
468  exit(5);
469  }
470  TLOG(TLVL_INFO) << "Metric Sending thread started";
471 }
472 
474 {
475  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
476  for (auto& cache_entry : metric_cache_)
477  {
478  if (cache_entry.second->DataPointCount > 0)
479  {
480  return false;
481  }
482  }
483 
484  return true;
485 }
486 
488 {
489  bool pluginsBusy = false;
490 
491  for (auto& p : metric_plugins_)
492  {
493  if (p->metricsPending())
494  {
495  pluginsBusy = true;
496  break;
497  }
498  }
499 
500  TLOG(TLVL_TRACE) << "Metric queue empty: " << metricQueueEmpty() << ", busy_: " << busy_ << ", Plugins busy: " << pluginsBusy;
501  return !metricQueueEmpty() || busy_ || pluginsBusy;
502 }
503 
504 size_t artdaq::MetricManager::metricQueueSize(std::string const& name)
505 {
506  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
507  size_t size = 0;
508  if (name.empty())
509  {
510  for (auto& q : metric_cache_)
511  {
512  size += q.second->DataPointCount;
513  }
514  }
515  else
516  {
517  if (metric_cache_.count(name) != 0u)
518  {
519  size = metric_cache_[name]->DataPointCount;
520  }
521  }
522 
523  return size;
524 }
525 
526 void artdaq::MetricManager::sendMetricLoop_()
527 {
528  TLOG(TLVL_INFO) << "sendMetricLoop_ START";
529  auto last_send_time = std::chrono::steady_clock::time_point();
530  while (running_)
531  {
532  TLOG(6) << "sendMetricLoop_: Entering Metric input wait loop";
533  while (metricQueueEmpty() && running_)
534  {
535  std::unique_lock<std::mutex> lk(metric_mutex_);
536  metric_cv_.wait_for(lk, std::chrono::milliseconds(100));
537  auto now = std::chrono::steady_clock::now();
538  if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_send_time).count() >
539  metric_send_interval_ms_)
540  {
541  TLOG(6) << "sendMetricLoop_: Metric send interval exceeded: Sending metrics";
542  if (std::chrono::duration_cast<std::chrono::microseconds>(now - last_metric_received_).count() < metric_holdoff_us_)
543  {
544  usleep(metric_holdoff_us_);
545  }
546  for (auto& metric : metric_plugins_)
547  {
548  if (metric)
549  {
550  metric->sendMetrics();
551  }
552  }
553  last_send_time = now;
554  }
555  }
556  if (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - last_metric_received_).count() < metric_holdoff_us_)
557  {
558  usleep(metric_holdoff_us_);
559  }
560 
561  TLOG(6) << "sendMetricLoop_: After Metric input wait loop";
562  busy_ = true;
563  auto processing_start = std::chrono::steady_clock::now();
564  auto temp_list = std::list<std::unique_ptr<MetricData>>();
565  {
566  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
567 
568  for (auto& q : metric_cache_)
569  {
570  if (q.second != nullptr && q.second->DataPointCount > 0)
571  {
572  temp_list.emplace_back(new MetricData(*q.second));
573  q.second->Reset();
574  }
575  }
576  }
577 
578  auto calls = metric_calls_.exchange(0);
579  temp_list.emplace_back(
580  new MetricData("Metric Calls", calls, "metrics", 4, MetricMode::Accumulate | MetricMode::Rate, "", false));
581 
582  auto missed = missed_metric_calls_.exchange(0);
583  temp_list.emplace_back(
584  new MetricData("Missed Metric Calls", missed, "metrics", 4, MetricMode::Accumulate | MetricMode::Rate, "", false));
585 
586  TLOG(TLVL_TRACE) << "There are " << temp_list.size() << " Metrics to process (" << calls << " calls, " << missed
587  << " missed)";
588 
589  if (system_metric_collector_ != nullptr)
590  {
591  TLOG(TLVL_TRACE) << "Collecting System metrics (CPU, RAM, Network)";
592  auto systemMetrics = system_metric_collector_->SendMetrics();
593  for (auto& m : systemMetrics) { temp_list.emplace_back(std::move(m)); }
594  }
595 
596  TLOG(6) << "sendMetricLoop_: Before processing temp_list";
597  while (!temp_list.empty())
598  {
599  auto data_ = std::move(temp_list.front());
600  temp_list.pop_front();
601  if (data_->Type == MetricType::InvalidMetric)
602  {
603  continue;
604  }
605  if (!data_->UseNameOverride)
606  {
607  if (!data_->MetricPrefix.empty())
608  {
609  data_->Name = prefix_ + "." + data_->MetricPrefix + "." + data_->Name;
610  }
611  else
612  {
613  data_->Name = prefix_ + "." + data_->Name;
614  }
615  }
616 
617  for (auto& metric : metric_plugins_)
618  {
619  if (!metric)
620  {
621  continue;
622  }
623  if (metric->IsLevelEnabled(data_->Level))
624  {
625  try
626  {
627  metric->addMetricData(data_);
628  last_send_time = std::chrono::steady_clock::now();
629  }
630  catch (...)
631  {
632  TLOG(TLVL_ERROR) << "Error in MetricManager::sendMetric: error sending value to metric plugin with name "
633  << metric->getLibName();
634  }
635  }
636  }
637  }
638 
639  TLOG(6) << "sendMetricLoop_: Before sending metrics";
640  for (auto& metric : metric_plugins_)
641  {
642  if (!metric)
643  {
644  continue;
645  }
646  metric->sendMetrics(false, processing_start);
647  }
648 
649  // Limit rate of metrics going to plugins
650  TLOG(6) << "sendMetricLoop_: End of working loop";
651  busy_ = false;
652  usleep(10000);
653  }
654 
655  busy_ = true;
656  auto temp_list = std::list<std::unique_ptr<MetricData>>();
657  {
658  std::lock_guard<std::mutex> lk(metric_cache_mutex_);
659 
660  for (auto& q : metric_cache_)
661  {
662  if (q.second != nullptr && q.second->DataPointCount > 0)
663  {
664  temp_list.emplace_back(new MetricData(*q.second));
665  q.second->Reset();
666  }
667  }
668  //metric_cache_.clear();
669  }
670 
671  auto calls = metric_calls_.exchange(0);
672  temp_list.emplace_back(
673  new MetricData("Metric Calls", calls, "metrics", 4, MetricMode::Accumulate | MetricMode::Rate, "", false));
674 
675  auto missed = missed_metric_calls_.exchange(0);
676  temp_list.emplace_back(
677  new MetricData("Missed Metric Calls", missed, "metrics", 4, MetricMode::Accumulate | MetricMode::Rate, "", false));
678 
679  TLOG(TLVL_TRACE) << "There are " << temp_list.size() << " Metrics to process (" << calls << " calls, " << missed
680  << " missed)";
681 
682  while (!temp_list.empty())
683  {
684  auto data_ = std::move(temp_list.front());
685  temp_list.pop_front();
686  if (data_->Type == MetricType::InvalidMetric)
687  {
688  continue;
689  }
690  if (!data_->UseNameOverride)
691  {
692  if (!data_->MetricPrefix.empty())
693  {
694  data_->Name = prefix_ + "." + data_->MetricPrefix + "." + data_->Name;
695  }
696  else
697  {
698  data_->Name = prefix_ + "." + data_->Name;
699  }
700  }
701 
702  for (auto& metric : metric_plugins_)
703  {
704  if (!metric)
705  {
706  continue;
707  }
708  if (metric->IsLevelEnabled(data_->Level))
709  {
710  try
711  {
712  metric->addMetricData(data_);
713  last_send_time = std::chrono::steady_clock::now();
714  }
715  catch (...)
716  {
717  TLOG(TLVL_ERROR) << "Error in MetricManager::sendMetric: error sending value to metric plugin with name "
718  << metric->getLibName();
719  }
720  }
721  }
722  }
723 
724  for (auto& metric : metric_plugins_)
725  {
726  if (!metric)
727  {
728  continue;
729  }
730  try
731  {
732  metric->stopMetrics();
733  TLOG(TLVL_DEBUG) << "Metric Plugin " << metric->getLibName() << " stopped.";
734  }
735  catch (...)
736  {
737  TLOG(TLVL_ERROR) << "Exception caught in MetricManager::do_stop(), error stopping plugin with name "
738  << metric->getLibName();
739  }
740  }
741  busy_ = false;
742  TLOG(TLVL_DEBUG) << "MetricManager has been stopped.";
743 }
void shutdown()
Call the destructors for all configured MetricPlugin instances.
void initialize(fhicl::ParameterSet const &pset, std::string const &prefix="")
Initialize the MetricPlugin instances.
void sendMetric(std::string const &name, std::string const &value, std::string const &unit, int level, MetricMode mode, std::string const &metricPrefix="", bool useNameOverride=false)
Send a metric with the given parameters to any MetricPlugins with a threshold level &gt;= to level...
bool metricManagerBusy()
Determine whether the MetricManager or any of its plugins are currently processing metrics...
size_t metricQueueSize(std::string const &name="")
Return the size of the named metric queue
void reinitialize(fhicl::ParameterSet const &pset, std::string const &prefix="")
Reinitialize all MetricPlugin Instances.
Report the sum of all values. Use for counters to report accurate results.
MetricManager()
Construct an instance of the MetricManager class.
void do_start()
Perform startup actions for each configured MetricPlugin.
void do_stop()
Stop sending metrics to the MetricPlugin instances.
virtual ~MetricManager() noexcept
MetricManager destructor.
std::unique_ptr< MetricPlugin > makeMetricPlugin(std::string const &generator_plugin_spec, fhicl::ParameterSet const &ps, std::string const &app_name)
Load a given MetricPlugin and return a pointer to it.
over. Use to create rates from counters.
Report only the last value recorded. Useful for event counters, run numbers, etc. ...
MetricMode
The Mode of the metric indicates how multiple metric values should be combined within a reporting int...
Definition: MetricData.hh:29
Default, invalid value.
void do_resume()
Resume metric sending. Currently a No-Op.
bool metricQueueEmpty()
Returns whether the metric queue is completely empty
void do_pause()
Pause metric sending. Currently a No-Op.