artdaq_utilities  v1_05_08
graphite_metric.cc
1 // graphite_metric.cc: Graphite Metric Plugin
2 // Author: Eric Flumerfelt
3 // Last Modified: 11/13/2014
4 //
5 // An implementation of the MetricPlugin for Graphite
6 
7 #include "artdaq-utilities/Plugins/MetricMacros.hh"
8 #include "fhiclcpp/ParameterSet.h"
9 #include "messagefacility/MessageLogger/MessageLogger.h"
10 
11 #include <algorithm>
12 #include <boost/asio.hpp>
13 #include <chrono>
14 #include <ctime>
15 #include <iostream>
16 #include <string>
17 
18 using boost::asio::ip::tcp;
19 
20 namespace artdaq {
31 class GraphiteMetric final : public MetricPlugin
32 {
33 private:
34  std::string host_;
35  int port_;
36  std::string namespace_;
37  boost::asio::io_service io_service_;
38  tcp::socket socket_;
39  bool stopped_;
40  int errorCount_;
41  std::chrono::steady_clock::time_point waitStart_;
42 
43 public:
56  explicit GraphiteMetric(fhicl::ParameterSet const& config, std::string const& app_name)
57  : MetricPlugin(config, app_name)
58  , host_(pset.get<std::string>("host", "localhost"))
59  , port_(pset.get<int>("port", 2003))
60  , namespace_(pset.get<std::string>("namespace", "artdaq."))
61  , io_service_()
62  , socket_(io_service_)
63  , stopped_(true)
64  , errorCount_(0)
65  {
66  startMetrics();
67  }
68 
73  ~GraphiteMetric() override { stopMetrics(); }
74 
79  std::string getLibName() const override { return "graphite"; }
80 
86  void sendMetric_(const std::string& name, const std::string& value, const std::string& /*unit*/) override
87  {
88  if (!stopped_)
89  {
90  const auto result = std::time(nullptr);
91  boost::asio::streambuf data;
92  auto nameTemp(name);
93  std::replace(nameTemp.begin(), nameTemp.end(), ' ', '_');
94  std::ostream out(&data);
95  out << namespace_ << nameTemp << " "
96  << value << " "
97  << result << std::endl;
98 
99  boost::system::error_code error;
100  boost::asio::write(socket_, data, error);
101  if (error)
102  {
103  errorCount_++;
104  reconnect_();
105  }
106  }
107  }
108 
115  void sendMetric_(const std::string& name, const int& value, const std::string& unit) override
116  {
117  sendMetric_(name, std::to_string(value), unit);
118  }
119 
126  void sendMetric_(const std::string& name, const double& value, const std::string& unit) override
127  {
128  sendMetric_(name, std::to_string(value), unit);
129  }
130 
137  void sendMetric_(const std::string& name, const float& value, const std::string& unit) override
138  {
139  sendMetric_(name, std::to_string(value), unit);
140  }
141 
148  void sendMetric_(const std::string& name, const uint64_t& value, const std::string& unit) override
149  {
150  sendMetric_(name, std::to_string(value), unit);
151  }
152 
156  void startMetrics_() override
157  {
158  if (stopped_)
159  {
160  reconnect_();
161  stopped_ = false;
162  }
163  }
164 
168  void stopMetrics_() override
169  {
170  if (!stopped_)
171  {
172  try
173  {
174  socket_.shutdown(boost::asio::socket_base::shutdown_send);
175  socket_.close();
176  stopped_ = true;
177  }
178  catch (boost::system::system_error& err)
179  {
180  mf::LogWarning("GraphiteMetric") << "In destructor of GraphiteMetric instance associated with " << host_ << ":" << port_ << ", the following boost::system::system_error exception was thrown out of a call to stopMetrics() and caught: " << err.code() << ", \"" << err.what() << "\"";
181  }
182  catch (...)
183  {
184  mf::LogWarning("GraphiteMetric") << "In destructor of GraphiteMetric instance associated with " << host_ << ":" << port_ << ", an *unknown* exception was thrown out of a call to stopMetrics() and caught!";
185  }
186  }
187  }
188 
189 private:
190  GraphiteMetric(const GraphiteMetric&) = delete;
191  GraphiteMetric(GraphiteMetric&&) = delete;
192  GraphiteMetric& operator=(const GraphiteMetric&) = delete;
193  GraphiteMetric& operator=(GraphiteMetric&&) = delete;
194 
198  void reconnect_()
199  {
200  if (errorCount_ < 5)
201  {
202  boost::system::error_code error;
203  tcp::resolver resolver(io_service_);
204  tcp::resolver::query query(host_, std::to_string(port_));
205  boost::asio::connect(socket_, resolver.resolve(query), error);
206  if (!error) { errorCount_ = 0; }
207  else
208  {
209  mf::LogWarning("GraphiteMetric") << "Error reconnecting socket, attempt #" << errorCount_;
210  }
211  waitStart_ = std::chrono::steady_clock::now();
212  }
213  else if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - waitStart_).count() >= 5) //Seconds
214  {
215  errorCount_ = 0;
216  }
217  }
218 };
219 } //End namespace artdaq
220 
221 DEFINE_ARTDAQ_METRIC(artdaq::GraphiteMetric)
void sendMetric_(const std::string &name, const double &value, const std::string &unit) override
Send a metric to Graphite.
The MetricPlugin class defines the interface that MetricManager uses to send metric data to the vario...
Definition: MetricPlugin.hh:37
void startMetrics()
Perform startup actions. Simply calls the virtual startMetrics_ function.
fhicl::ParameterSet pset
The ParameterSet used to configure the MetricPlugin.
std::string getLibName() const override
Get the library name for the Graphite metric.
void sendMetric_(const std::string &name, const int &value, const std::string &unit) override
Send a metric to Graphite.
void sendMetric_(const std::string &name, const std::string &value, const std::string &) override
Send a metric to Graphite.
void startMetrics_() override
Perform startup actions. For Graphite, this means reconnecting the socket.
void stopMetrics()
Perform shutdown actions. Zeroes out all accumulators, and sends zeros for each metric. Calls stopMetrics_() for any plugin-defined shutdown actions.
void sendMetric_(const std::string &name, const float &value, const std::string &unit) override
Send a metric to Graphite.
void sendMetric_(const std::string &name, const uint64_t &value, const std::string &unit) override
Send a metric to Graphite.
GraphiteMetric(fhicl::ParameterSet const &config, std::string const &app_name)
GraphiteMetric Constructor.
void stopMetrics_() override
Perform shutdown actions. This shuts down the socket and closes it.
~GraphiteMetric() override
GraphiteMetric Destructor. Calls stopMetrics()
Send a metric to Graphite.