artdaq_utilities  v1_05_00
procFile_metric.cc
1 
2 #include "artdaq-utilities/Plugins/MetricMacros.hh"
3 #include "fhiclcpp/ParameterSet.h"
4 #include "messagefacility/MessageLogger/MessageLogger.h"
5 #define TRACE_NAME "procFile_metric"
6 #include "trace.h"
7 
8 #include <fcntl.h> // open
9 #include <stdlib.h> // exit
10 #include <sys/stat.h> // mkfifo
11 #include <boost/thread.hpp>
12 #include <ctime>
13 #include <map>
14 #include <string>
15 
16 namespace artdaq {
24 {
25 private:
26  std::string pipe_;
27  std::unordered_map<std::string, std::string> value_map_;
28  bool stopped_;
29  boost::thread thread_;
30 
31 public:
43  explicit ProcFileMetric(fhicl::ParameterSet const& config, std::string const& app_name)
44  : MetricPlugin(config, app_name)
45  , pipe_(pset.get<std::string>("pipe", "/tmp/eventQueueStat"))
46  , value_map_()
47  , stopped_(true)
48  {
49  auto names = pset.get<std::vector<std::string>>("names", std::vector<std::string>());
50 
51  for (auto name : names)
52  {
53  value_map_[name] = "";
54  }
55 
56  int sts = mkfifo(pipe_.c_str(), 0777);
57  if (sts != 0) { perror("ProcFileMetric mkfifo"); }
58  TLOG(10) << "ProcFileMetric mkfifo()" << pipe_ << " sts=" << sts;
59  startMetrics();
60  }
61 
66  {
67  TLOG(11) << "~ProcFileMetric";
68  stopMetrics();
69  }
70 
75  std::string getLibName() const override { return "procFile"; }
76 
82  void sendMetric_(const std::string& name, const std::string& value, const std::string&) override
83  {
84  if (value_map_.count(name))
85  {
86  TLOG(12) << "sendMetric_ setting value=" << value;
87  value_map_[name] = value;
88  }
89  }
90 
97  void sendMetric_(const std::string& name, const int& value, const std::string& unit) override
98  {
99  sendMetric_(name, std::to_string(value), unit);
100  }
101 
108  void sendMetric_(const std::string& name, const double& value, const std::string& unit) override
109  {
110  sendMetric_(name, std::to_string(value), unit);
111  }
112 
119  void sendMetric_(const std::string& name, const float& value, const std::string& unit) override
120  {
121  sendMetric_(name, std::to_string(value), unit);
122  }
123 
130  void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
131  {
132  sendMetric_(name, std::to_string(value), unit);
133  }
134 
138  void startMetrics_() override
139  {
140  if (stopped_)
141  {
142  // start thread
143  stopped_ = false;
144  boost::thread::attributes attrs;
145  attrs.set_stack_size(4096 * 2000); // 8000 KB
146  try
147  {
148  thread_ = boost::thread(attrs, boost::bind(&ProcFileMetric::writePipe, this));
149  }
150  catch (boost::exception const& e)
151  {
152  std::cerr << "Creating ProcFile Metric thread failed! e: " << boost::diagnostic_information(e) << std::endl;
153  exit(4);
154  }
155  }
156  }
157 
161  void stopMetrics_() override
162  {
163  if (!stopped_)
164  {
165  stopped_ = true;
166  // do read on pipe to make sure writePipe is not blocking on open
167  TLOG(11) << "stopMetrics_ before open " << pipe_;
168  int fd = open(pipe_.c_str(), O_RDONLY | O_NONBLOCK);
169  if (fd == -1)
170  {
171  perror("stopMetrics_ open(\"r\")");
172  exit(1);
173  }
174  TLOG(10) << "stopMetrics_ between open and unlink" << pipe_ << " fd=" << fd;
175  unlink(pipe_.c_str());
176  TLOG(11) << "stopMetrics_ unlinked " << pipe_;
177 #if 0
178  char buf[256];
179  read(fd, buf, sizeof(buf));
180 #endif
181  usleep(10000);
182  close(fd);
183  TLOG(11) << "stopMetrics_ after close " << pipe_;
184  if (thread_.joinable()) thread_.join();
185  }
186  }
187 
191  void writePipe()
192  {
193  while (!stopped_)
194  {
195  TLOG(11) << "writePipe before open";
196  int fd = open(pipe_.c_str(), O_WRONLY);
197  std::string str;
198  for (auto value : value_map_)
199  {
200  TLOG(10) << "writePipe open fd=" << fd << " name=" << value.first << " value=" << value.second; // can't have args b/c name may have %
201  str += value.first + ": " + value.second + "\n";
202  //snprintf(buf, sizeof(buf), "%s: %lu\n", value.first.c_str(), value.second);
203  }
204  int sts = write(fd, str.c_str(), str.size());
205  TLOG(11) << "writePipe write complete sts=" << sts;
206  close(fd);
207  TLOG(11) << "writePipe after close -- about to usleep";
208  usleep(400000); // must wait to make sure other end closes
209  }
210  }
211 };
212 } //End namespace artdaq
213 
214 DEFINE_ARTDAQ_METRIC(artdaq::ProcFileMetric)
The MetricPlugin class defines the interface that MetricManager uses to send metric data to the vario...
Definition: MetricPlugin.hh:29
void startMetrics()
Perform startup actions. Simply calls the virtual startMetrics_ function.
std::string getLibName() const override
Get the &quot;library name&quot; of this Metric.
void stopMetrics_() override
Open the pipe for reading to allow the metric-sending thread to end gracefully.
fhicl::ParameterSet pset
The ParameterSet used to configure the MetricPlugin.
void sendMetric_(const std::string &name, const double &value, const std::string &unit) override
Set the value to be written to the pipe when it is opened by a reader.
void startMetrics_() override
Start the metric-sending thread.
ProcFileMetric(fhicl::ParameterSet const &config, std::string const &app_name)
ProcFileMetric Constructor.
void writePipe()
Wait for the pipe to be opened and then write the current value to it.
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 int &value, const std::string &unit) override
Set the value to be written to the pipe when it is opened by a reader.
void sendMetric_(const std::string &name, const unsigned long int &value, const std::string &unit) override
Set the value to be written to the pipe when it is opened by a reader.
void sendMetric_(const std::string &name, const std::string &value, const std::string &) override
Set the value to be written to the pipe when it is opened by a reader.
~ProcFileMetric()
ProcFileMetric Destructor.
A MetricPlugin which writes a long unsigned int metric with a given name to a given pipe...
void sendMetric_(const std::string &name, const float &value, const std::string &unit) override
Set the value to be written to the pipe when it is opened by a reader.