artdaq_utilities  v1_04_06
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 * 200); // 800 KB
139  thread_ = boost::thread(attrs, boost::bind(&ProcFileMetric::writePipe, this));
140  }
141  }
142 
146  void stopMetrics_() override
147  {
148  if (!stopped_)
149  {
150  stopped_ = true;
151  // do read on pipe to make sure writePipe is not blocking on open
152  TLOG(11) << "stopMetrics_ before open " << pipe_;
153  int fd = open(pipe_.c_str(), O_RDONLY | O_NONBLOCK);
154  if (fd == -1) { perror("stopMetrics_ open(\"r\")"); exit(1); }
155  TLOG(10) << "stopMetrics_ between open and unlink" << pipe_ << " fd=" << fd;
156  unlink(pipe_.c_str());
157  TLOG(11) << "stopMetrics_ unlinked " << pipe_;
158 # if 0
159  char buf[256];
160  read(fd, buf, sizeof(buf));
161 # endif
162  usleep(10000);
163  close(fd);
164  TLOG(11) << "stopMetrics_ after close " << pipe_;
165  if (thread_.joinable()) thread_.join();
166  }
167  }
168 
172  void writePipe()
173  {
174  while (!stopped_)
175  {
176  TLOG(11) << "writePipe before open";
177  int fd = open(pipe_.c_str(), O_WRONLY);
178  std::string str;
179  for (auto value : value_map_) {
180  TLOG(10) << "writePipe open fd=" << fd << " name=" << value.first << " value=" << value.second; // can't have args b/c name may have %
181  str += value.first + ": " + value.second + "\n";
182  //snprintf(buf, sizeof(buf), "%s: %lu\n", value.first.c_str(), value.second);
183  }
184  int sts = write(fd, str.c_str(), str.size());
185  TLOG(11) << "writePipe write complete sts=" << sts;
186  close(fd);
187  TLOG(11) << "writePipe after close -- about to usleep";
188  usleep(400000); // must wait to make sure other end closes
189  }
190 
191  }
192  };
193 } //End namespace artdaq
194 
195 DEFINE_ARTDAQ_METRIC(artdaq::ProcFileMetric)
The MetricPlugin class defines the interface that MetricManager uses to send metric data to the vario...
Definition: MetricPlugin.hh:32
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.