artdaq_utilities  v1_03_00
 All Classes Namespaces Functions Variables Typedefs
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 #include "artdaq-utilities/Plugins/MetricManager.hh"
10 #include "artdaq-utilities/Plugins/makeMetricPlugin.hh"
11 #include "tracemf.h"
12 #include "fhiclcpp/ParameterSet.h"
13 
14 #include <chrono>
15 #include <boost/exception/all.hpp>
16 
18 MetricManager() : metric_plugins_(0)
19 , initialized_(false)
20 , running_(false)
21 , active_(false)
22 {}
23 
25 {
26  shutdown();
27 }
28 
29 void artdaq::MetricManager::initialize(fhicl::ParameterSet const& pset, std::string prefix)
30 {
31  prefix_ = prefix;
32  if (initialized_)
33  {
34  shutdown();
35  }
36  TLOG_DEBUG("MetricManager") << "Configuring metrics with parameter set:\n" << pset.to_string() << TLOG_ENDL;
37 
38  std::vector<std::string> names = pset.get_pset_names();
39 
40  for (auto name : names)
41  {
42  try
43  {
44  TLOG_DEBUG("MetricManager") << "Constructing metric plugin with name " << name << TLOG_ENDL;
45  fhicl::ParameterSet plugin_pset = pset.get<fhicl::ParameterSet>(name);
46  metric_plugins_.push_back(makeMetricPlugin(
47  plugin_pset.get<std::string>("metricPluginType", ""), plugin_pset));
48  }
49  catch (const cet::exception& e)
50  {
51  TLOG_ERROR("MetricManager") << "Exception caught in MetricManager::initialize, error loading plugin with name " << name <<
52  ", cet::exception object caught:" << e.explain_self() << TLOG_ENDL;
53  }
54  catch (const boost::exception& e)
55  {
56  TLOG_ERROR("MetricManager") << "Exception caught in MetricManager::initialize, error loading plugin with name " << name <<
57  ", boost::exception object caught: " << boost::diagnostic_information(e) << TLOG_ENDL;
58  }
59  catch (const std::exception& e)
60  {
61  TLOG_ERROR("MetricManager") << "Exception caught in MetricManager::initialize, error loading plugin with name " << name <<
62  ", std::exception caught: " << e.what() << TLOG_ENDL;
63  }
64  catch (...)
65  {
66  TLOG_ERROR("MetricManager") << "Unknown Exception caught in MetricManager::initialize, error loading plugin with name " << name << TLOG_ENDL;
67  }
68  }
69 
70  initialized_ = true;
71 }
72 
74 {
75  if (!running_)
76  {
77  TLOG_DEBUG("MetricManager") << "Starting MetricManager" << TLOG_ENDL;
78  for (auto& metric : metric_plugins_)
79  {
80  try
81  {
82  metric->startMetrics();
83  TLOG_DEBUG("MetricManager") << "Metric Plugin " << metric->getLibName() << " started." << TLOG_ENDL;
84  active_ = true;
85  }
86  catch (...)
87  {
88  TLOG_ERROR("MetricManager") <<
89  "Exception caught in MetricManager::do_start(), error starting plugin with name " <<
90  metric->getLibName() << TLOG_ENDL;
91  }
92  }
93  running_ = true;
94  startMetricLoop_();
95  }
96 }
97 
99 {
100  running_ = false;
101  metric_cv_.notify_all();
102  if (metric_sending_thread_.joinable()) metric_sending_thread_.join();
103 }
104 
105 void artdaq::MetricManager::do_pause() { /*do_stop();*/ }
106 void artdaq::MetricManager::do_resume() { /*do_start();*/ }
107 
108 void artdaq::MetricManager::reinitialize(fhicl::ParameterSet const& pset, std::string prefix)
109 {
110  shutdown();
111  initialize(pset, prefix);
112 }
113 
115 {
116  TLOG_DEBUG("MetricManager") << "MetricManager is shutting down..." << TLOG_ENDL;
117  do_stop();
118 
119  if (initialized_)
120  {
121  for (auto& i : metric_plugins_)
122  {
123  try
124  {
125  std::string name = i->getLibName();
126  i.reset(nullptr);
127  TLOG_DEBUG("MetricManager") << "Metric Plugin " << name << " shutdown." << TLOG_ENDL;
128  }
129  catch (...)
130  {
131  TLOG_ERROR("MetricManager") <<
132  "Exception caught in MetricManager::shutdown(), error shutting down metric with name " <<
133  i->getLibName() << TLOG_ENDL;
134  }
135  }
136  initialized_ = false;
137  }
138 }
139 
140 void artdaq::MetricManager::sendMetric(std::string const& name, std::string const& value, std::string const& unit, int level, MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
141 {
142  if (!initialized_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager has not yet been initialized!" << TLOG_ENDL; }
143  else if (!running_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager stopped!" << TLOG_ENDL; }
144  else if (active_)
145  {
146  std::unique_ptr<MetricData> metric(new MetricData(name, value, unit, level, mode, metricPrefix, useNameOverride));
147  {
148  std::unique_lock<std::mutex> lk(metric_queue_mutex_);
149  metric_queue_.push_back(std::move(metric));
150  }
151  metric_cv_.notify_all();
152  }
153 }
154 
155 void artdaq::MetricManager::sendMetric(std::string const& name, int const& value, std::string const& unit, int level, MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
156 {
157  if (!initialized_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager has not yet been initialized!" << TLOG_ENDL; }
158  else if (!running_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager stopped!" << TLOG_ENDL; }
159  else if (active_)
160  {
161  std::unique_ptr<MetricData> metric(new MetricData(name, value, unit, level, mode, metricPrefix, useNameOverride));
162  {
163  std::unique_lock<std::mutex> lk(metric_queue_mutex_);
164  metric_queue_.push_back(std::move(metric));
165  }
166  metric_cv_.notify_all();
167  }
168 }
169 
170 void artdaq::MetricManager::sendMetric(std::string const& name, double const& value, std::string const& unit, int level, MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
171 {
172  if (!initialized_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager has not yet been initialized!" << TLOG_ENDL; }
173  else if (!running_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager stopped!" << TLOG_ENDL; }
174  else if (active_)
175  {
176  std::unique_ptr<MetricData> metric(new MetricData(name, value, unit, level, mode, metricPrefix, useNameOverride));
177  {
178  std::unique_lock<std::mutex> lk(metric_queue_mutex_);
179  metric_queue_.push_back(std::move(metric));
180  }
181  metric_cv_.notify_all();
182  }
183 }
184 
185 void artdaq::MetricManager::sendMetric(std::string const& name, float const& value, std::string const& unit, int level, MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
186 {
187  if (!initialized_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager has not yet been initialized!" << TLOG_ENDL; }
188  else if (!running_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager stopped!" << TLOG_ENDL; }
189  else if (active_)
190  {
191  std::unique_ptr<MetricData> metric(new MetricData(name, value, unit, level, mode, metricPrefix, useNameOverride));
192  {
193  std::unique_lock<std::mutex> lk(metric_queue_mutex_);
194  metric_queue_.push_back(std::move(metric));
195  }
196  metric_cv_.notify_all();
197  }
198 }
199 
200 void artdaq::MetricManager::sendMetric(std::string const& name, long unsigned int const& value, std::string const& unit, int level, MetricMode mode, std::string const& metricPrefix, bool useNameOverride)
201 {
202  if (!initialized_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager has not yet been initialized!" << TLOG_ENDL; }
203  else if (!running_) { TLOG_WARNING("MetricManager") << "Attempted to send metric when MetricManager stopped!" << TLOG_ENDL; }
204  else if (active_)
205  {
206  std::unique_ptr<MetricData> metric(new MetricData(name, value, unit, level, mode, metricPrefix, useNameOverride));
207  {
208  std::unique_lock<std::mutex> lk(metric_queue_mutex_);
209  metric_queue_.push_back(std::move(metric));
210  }
211  metric_cv_.notify_all();
212  }
213 }
214 
215 void artdaq::MetricManager::startMetricLoop_()
216 {
217  if (metric_sending_thread_.joinable()) metric_sending_thread_.join();
218  TLOG_INFO("MetricManager") << "Starting Metric Sending Thread" << TLOG_ENDL;
219  metric_sending_thread_ = std::thread(&MetricManager::sendMetricLoop_, this);
220 }
221 
222 void artdaq::MetricManager::sendMetricLoop_()
223 {
224  auto last_send_time = std::chrono::steady_clock::time_point();
225  while (running_)
226  {
227  while (metric_queue_.size() == 0 && running_)
228  {
229  std::unique_lock<std::mutex> lk(metric_mutex_);
230  metric_cv_.wait_for(lk, std::chrono::milliseconds(100));
231  auto now = std::chrono::steady_clock::now();
232  if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_send_time).count() > metric_send_interval_ms_)
233  {
234  for (auto& metric : metric_plugins_) { metric->sendMetrics(); }
235  last_send_time = now;
236  }
237  }
238 
239  auto temp_list = std::list<std::unique_ptr<MetricData>>();
240  {
241  std::unique_lock<std::mutex> lk(metric_queue_mutex_);
242  temp_list.swap(metric_queue_);
243  temp_list.emplace_back(new MetricData("Metric Calls", temp_list.size(), "metrics", 4, MetricMode::Accumulate, "", false));
244  }
245 
246  while (temp_list.size() > 0)
247  {
248  auto data_ = std::move(temp_list.front());
249  temp_list.pop_front();
250  if (data_->Type == MetricType::InvalidMetric) continue;
251  if (!data_->UseNameOverride)
252  {
253  if (data_->MetricPrefix.size() > 0)
254  {
255  data_->Name = prefix_ + "." + data_->MetricPrefix + "." + data_->Name;
256  }
257  else
258  {
259  data_->Name = prefix_ + "." + data_->Name;
260  }
261  }
262 
263  for (auto& metric : metric_plugins_)
264  {
265  if (metric->getRunLevel() >= data_->Level)
266  {
267  try
268  {
269  metric->addMetricData(*data_);
270  last_send_time = std::chrono::steady_clock::now();
271  }
272  catch (...)
273  {
274  TLOG_ERROR("MetricManager") <<
275  "Error in MetricManager::sendMetric: error sending value to metric plugin with name "
276  << metric->getLibName() << TLOG_ENDL;
277  }
278  }
279  }
280  }
281  }
282 
283  for (auto& metric : metric_plugins_)
284  {
285  try
286  {
287  metric->stopMetrics();
288  TLOG_DEBUG("MetricManager") << "Metric Plugin " << metric->getLibName() << " stopped." << TLOG_ENDL;
289  }
290  catch (...)
291  {
292  TLOG_ERROR("MetricManager") <<
293  "Exception caught in MetricManager::do_stop(), error stopping plugin with name " <<
294  metric->getLibName() << TLOG_ENDL;
295  }
296  }
297  TLOG_DEBUG("MetricManager") << "MetricManager has been stopped." << TLOG_ENDL;
298 }
void reinitialize(fhicl::ParameterSet const &pset, std::string prefix="")
Reinitialize all MetricPlugin Instances.
void shutdown()
Call the destructors for all configured MetricPlugin instances.
void initialize(fhicl::ParameterSet const &pset, std::string 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...
std::unique_ptr< MetricPlugin > makeMetricPlugin(std::string const &generator_plugin_spec, fhicl::ParameterSet const &ps)
Load a given MetricPlugin and return a pointer to it.
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.
void do_resume()
Resume metric sending. Currently a No-Op.
void do_pause()
Pause metric sending. Currently a No-Op.