artdaq_utilities  v1_02_03a
 All Classes Namespaces Functions Variables Typedefs
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 <thread>
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  std::thread thread_;
31  public:
42  explicit ProcFileMetric(fhicl::ParameterSet config) : MetricPlugin(config)
43  , pipe_(pset.get<std::string>("pipe", "/tmp/eventQueueStat"))
44  , value_map_()
45  , stopped_(true)
46  {
47  auto names = pset.get<std::vector<std::string>>("names", std::vector<std::string>());
48 
49  for (auto name : names)
50  {
51  value_map_[name] = "";
52  }
53 
54  int sts = mkfifo(pipe_.c_str(), 0777);
55  if (sts != 0) { perror("ProcFileMetric mkfifo"); }
56  TRACE(10, "ProcFileMetric mkfifo(" + pipe_ + ") sts=%d", sts);
57  startMetrics();
58  }
59 
64  TRACE( 11, "~ProcFileMetric" );
65  stopMetrics();
66  }
67 
72  std::string getLibName() const override { return "procFile"; }
73 
79  void sendMetric_(const std::string& name, const std::string& value, const std::string&) override {
80  if (value_map_.count(name)) {
81  TRACE(12, "sendMetric_ setting value="+ value);
82  value_map_[name] = value;
83  }
84  }
85 
92  void sendMetric_(const std::string& name, const int& value, const std::string& unit) override {
93  sendMetric(name, std::to_string(value), unit);
94  }
95 
102  void sendMetric_(const std::string& name, const double& value, const std::string& unit) override {
103  sendMetric(name, std::to_string(value), unit);
104  }
105 
112  void sendMetric_(const std::string& name, const float& value, const std::string& unit) override {
113  sendMetric(name, std::to_string(value), unit);
114  }
115 
122  void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
123  {
124  sendMetric(name, std::to_string(value), unit);
125  }
126 
130  void startMetrics_() override
131  {
132  if (stopped_)
133  {
134  // start thread
135  stopped_ = false;
136  thread_ = std::thread(&ProcFileMetric::writePipe, this);
137  }
138  }
139 
143  void stopMetrics_() override
144  {
145  if (!stopped_)
146  {
147  stopped_ = true;
148  // do read on pipe to make sure writePipe is not blocking on open
149  TRACE(11, "stopMetrics_ before open " + pipe_);
150  int fd = open(pipe_.c_str(), O_RDONLY | O_NONBLOCK);
151  if (fd == -1) { perror("stopMetrics_ open(\"r\")"); exit(1); }
152  TRACE(10, "stopMetrics_ between open and unlink" + pipe_ + " fd=%d", fd);
153  unlink(pipe_.c_str());
154  TRACE(11, "stopMetrics_ unlinked " + pipe_);
155 # if 0
156  char buf[256];
157  read(fd, buf, sizeof(buf));
158 # endif
159  usleep(10000);
160  close(fd);
161  TRACE(11, "stopMetrics_ after close " + pipe_);
162  if (thread_.joinable()) thread_.join();
163  }
164  }
165 
169  void writePipe()
170  {
171  while (!stopped_)
172  {
173  TRACE(11, "writePipe before open");
174  int fd = open(pipe_.c_str(), O_WRONLY);
175  std::string str;
176  for (auto value : value_map_) {
177  TRACE(10, "writePipe open fd="+std::to_string(fd)+" name="+value.first+" value="+value.second ); // can't have args b/c name may have %
178  str += value.first + ": " + value.second + "\n";
179  //snprintf(buf, sizeof(buf), "%s: %lu\n", value.first.c_str(), value.second);
180  }
181  int sts = write(fd, str.c_str(), str.size());
182  TRACE(11, "writePipe write complete sts=%d", sts);
183  close(fd);
184  TRACE(11, "writePipe after close -- about to usleep");
185  usleep(400000); // must wait to make sure other end closes
186  }
187 
188  }
189  };
190 } //End namespace artdaq
191 
192 DEFINE_ARTDAQ_METRIC(artdaq::ProcFileMetric)
The MetricPlugin class defines the interface that MetricManager uses to send metric data to the vario...
Definition: MetricPlugin.hh:22
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.
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(fhicl::ParameterSet config)
ProcFileMetric Constructor.
~ProcFileMetric()
ProcFileMetric Destructor.
void sendMetric(const std::string &name, const std::string &value, const std::string &unit, bool accumulate=true)
Send a metric value to the MetricPlugin.
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.