artdaq_utilities  v1_04_10
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 <iostream>
12 #include <ctime>
13 #include <string>
14 #include <algorithm>
15 #include <boost/asio.hpp>
16 #include <chrono>
17 
18 using boost::asio::ip::tcp;
19 
20 namespace artdaq
21 {
33  {
34  private:
35  std::string host_;
36  int port_;
37  std::string namespace_;
38  boost::asio::io_service io_service_;
39  tcp::socket socket_;
40  bool stopped_;
41  int errorCount_;
42  std::chrono::steady_clock::time_point waitStart_;
43  public:
56  explicit GraphiteMetric(fhicl::ParameterSet const& config, std::string const& app_name) : MetricPlugin(config, app_name)
57  , host_(pset.get<std::string>("host", "localhost"))
58  , port_(pset.get<int>("port", 2003))
59  , namespace_(pset.get<std::string>("namespace", "artdaq."))
60  , io_service_()
61  , socket_(io_service_)
62  , stopped_(true)
63  , errorCount_(0)
64  {
65  startMetrics();
66  }
67 
71  virtual ~GraphiteMetric() { stopMetrics(); }
72 
77  std::string getLibName() const override { return "graphite"; }
78 
84  void sendMetric_(const std::string& name, const std::string& value, const std::string&) override
85  {
86  if (!stopped_)
87  {
88  const auto result = std::time(0);
89  boost::asio::streambuf data;
90  auto nameTemp(name);
91  std::replace(nameTemp.begin(), nameTemp.end(), ' ', '_');
92  std::ostream out(&data);
93  out << namespace_ << nameTemp << " "
94  << value << " "
95  << result << std::endl;
96 
97  boost::system::error_code error;
98  boost::asio::write(socket_, data, error);
99  if (error)
100  {
101  errorCount_++;
102  reconnect_();
103  }
104  }
105  }
106 
113  void sendMetric_(const std::string& name, const int& value, const std::string& unit) override
114  {
115  sendMetric_(name, std::to_string(value), unit);
116  }
117 
124  void sendMetric_(const std::string& name, const double& value, const std::string& unit) override
125  {
126  sendMetric_(name, std::to_string(value), unit);
127  }
128 
135  void sendMetric_(const std::string& name, const float& value, const std::string& unit) override
136  {
137  sendMetric_(name, std::to_string(value), unit);
138  }
139 
146  void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
147  {
148  sendMetric_(name, std::to_string(value), unit);
149  }
150 
154  void startMetrics_() override
155  {
156  if (stopped_)
157  {
158  reconnect_();
159  stopped_ = false;
160  }
161  }
162 
166  void stopMetrics_() override
167  {
168  if (!stopped_)
169  {
170  socket_.shutdown(boost::asio::socket_base::shutdown_send);
171  socket_.close();
172  stopped_ = true;
173  }
174  }
175 
176  private:
180  void reconnect_()
181  {
182  if (errorCount_ < 5)
183  {
184  boost::system::error_code error;
185  tcp::resolver resolver(io_service_);
186  tcp::resolver::query query(host_, std::to_string(port_));
187  boost::asio::connect(socket_, resolver.resolve(query), error);
188  if (!error) { errorCount_ = 0; }
189  else { mf::LogWarning("GraphiteMetric") << "Error reconnecting socket, attempt #" << errorCount_; }
190  waitStart_ = std::chrono::steady_clock::now();
191  }
192  else if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - waitStart_).count() >= 5)//Seconds
193  {
194  errorCount_ = 0;
195  }
196  }
197  };
198 } //End namespace artdaq
199 
200 DEFINE_ARTDAQ_METRIC(artdaq::GraphiteMetric)
void sendMetric_(const std::string &name, const double &value, const std::string &unit) override
Send a metric to Graphite.
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.
virtual ~GraphiteMetric()
GraphiteMetric Destructor. Calls stopMetrics()
void sendMetric_(const std::string &name, const float &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.
Send a metric to Graphite.
void sendMetric_(const std::string &name, const unsigned long int &value, const std::string &unit) override
Send a metric to Graphite.