artdaq_utilities  v1_04_11
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 <sys/stat.h> // mkfifo
9 #include <fcntl.h> // open
10 #include <stdlib.h> // exit
11 #include <ctime>
12 #include <string>
13 #include <boost/thread.hpp>
14 #include <map>
15 
16 namespace artdaq
17 {
25  {
26  private:
27  std::string pipe_;
28  std::unordered_map<std::string, std::string> value_map_;
29  bool stopped_;
30  boost::thread thread_;
31  public:
43  explicit ProcFileMetric(fhicl::ParameterSet const& config, std::string const& app_name) : MetricPlugin(config, app_name)
44  , pipe_(pset.get<std::string>("pipe", "/tmp/eventQueueStat"))
45  , value_map_()
46  , stopped_(true)
47  {
48  auto names = pset.get<std::vector<std::string>>("names", std::vector<std::string>());
49 
50  for (auto name : names)
51  {
52  value_map_[name] = "";
53  }
54 
55  int sts = mkfifo(pipe_.c_str(), 0777);
56  if (sts != 0) { perror("ProcFileMetric mkfifo"); }
57  TLOG(10) << "ProcFileMetric mkfifo()" << pipe_ << " sts=" << sts;
58  startMetrics();
59  }
60 
65  TLOG(11) << "~ProcFileMetric" ;
66  stopMetrics();
67  }
68 
73  std::string getLibName() const override { return "procFile"; }
74 
80  void sendMetric_(const std::string& name, const std::string& value, const std::string&) override {
81  if (value_map_.count(name)) {
82  TLOG(12) << "sendMetric_ setting value=" << value;
83  value_map_[name] = value;
84  }
85  }
86 
93  void sendMetric_(const std::string& name, const int& value, const std::string& unit) override {
94  sendMetric_(name, std::to_string(value), unit);
95  }
96 
103  void sendMetric_(const std::string& name, const double& value, const std::string& unit) override {
104  sendMetric_(name, std::to_string(value), unit);
105  }
106 
113  void sendMetric_(const std::string& name, const float& value, const std::string& unit) override {
114  sendMetric_(name, std::to_string(value), unit);
115  }
116 
123  void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
124  {
125  sendMetric_(name, std::to_string(value), unit);
126  }
127 
131  void startMetrics_() override
132  {
133  if (stopped_)
134  {
135  // start thread
136  stopped_ = false;
137  boost::thread::attributes attrs;
138  attrs.set_stack_size(4096 * 2000); // 8000 KB
139  try {
140  thread_ = boost::thread(attrs, boost::bind(&ProcFileMetric::writePipe, this));
141  }
142  catch (boost::exception const& e)
143  {
144  std::cerr << "Creating ProcFile Metric thread failed! e: " << boost::diagnostic_information(e) << std::endl;
145  exit(4);
146  }
147  }
148  }
149 
153  void stopMetrics_() override
154  {
155  if (!stopped_)
156  {
157  stopped_ = true;
158  // do read on pipe to make sure writePipe is not blocking on open
159  TLOG(11) << "stopMetrics_ before open " << pipe_;
160  int fd = open(pipe_.c_str(), O_RDONLY | O_NONBLOCK);
161  if (fd == -1) { perror("stopMetrics_ open(\"r\")"); exit(1); }
162  TLOG(10) << "stopMetrics_ between open and unlink" << pipe_ << " fd=" << fd;
163  unlink(pipe_.c_str());
164  TLOG(11) << "stopMetrics_ unlinked " << pipe_;
165 # if 0
166  char buf[256];
167  read(fd, buf, sizeof(buf));
168 # endif
169  usleep(10000);
170  close(fd);
171  TLOG(11) << "stopMetrics_ after close " << pipe_;
172  if (thread_.joinable()) thread_.join();
173  }
174  }
175 
179  void writePipe()
180  {
181  while (!stopped_)
182  {
183  TLOG(11) << "writePipe before open";
184  int fd = open(pipe_.c_str(), O_WRONLY);
185  std::string str;
186  for (auto value : value_map_) {
187  TLOG(10) << "writePipe open fd=" << fd << " name=" << value.first << " value=" << value.second; // can't have args b/c name may have %
188  str += value.first + ": " + value.second + "\n";
189  //snprintf(buf, sizeof(buf), "%s: %lu\n", value.first.c_str(), value.second);
190  }
191  int sts = write(fd, str.c_str(), str.size());
192  TLOG(11) << "writePipe write complete sts=" << sts;
193  close(fd);
194  TLOG(11) << "writePipe after close -- about to usleep";
195  usleep(400000); // must wait to make sure other end closes
196  }
197 
198  }
199  };
200 } //End namespace artdaq
201 
202 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.