00001
00002 #include "artdaq-utilities/Plugins/MetricMacros.hh"
00003 #include "fhiclcpp/ParameterSet.h"
00004 #include "messagefacility/MessageLogger/MessageLogger.h"
00005 #define TRACE_NAME "procFile_metric"
00006 #include "trace.h"
00007
00008 #include <sys/stat.h>
00009 #include <fcntl.h>
00010 #include <stdlib.h>
00011 #include <ctime>
00012 #include <string>
00013 #include <boost/thread.hpp>
00014 #include <map>
00015
00016 namespace artdaq
00017 {
00024 class ProcFileMetric : public MetricPlugin
00025 {
00026 private:
00027 std::string pipe_;
00028 std::unordered_map<std::string, std::string> value_map_;
00029 bool stopped_;
00030 boost::thread thread_;
00031 public:
00043 explicit ProcFileMetric(fhicl::ParameterSet const& config, std::string const& app_name) : MetricPlugin(config, app_name)
00044 , pipe_(pset.get<std::string>("pipe", "/tmp/eventQueueStat"))
00045 , value_map_()
00046 , stopped_(true)
00047 {
00048 auto names = pset.get<std::vector<std::string>>("names", std::vector<std::string>());
00049
00050 for (auto name : names)
00051 {
00052 value_map_[name] = "";
00053 }
00054
00055 int sts = mkfifo(pipe_.c_str(), 0777);
00056 if (sts != 0) { perror("ProcFileMetric mkfifo"); }
00057 TLOG(10) << "ProcFileMetric mkfifo()" << pipe_ << " sts=" << sts;
00058 startMetrics();
00059 }
00060
00064 ~ProcFileMetric() {
00065 TLOG(11) << "~ProcFileMetric" ;
00066 stopMetrics();
00067 }
00068
00073 std::string getLibName() const override { return "procFile"; }
00074
00080 void sendMetric_(const std::string& name, const std::string& value, const std::string&) override {
00081 if (value_map_.count(name)) {
00082 TLOG(12) << "sendMetric_ setting value=" << value;
00083 value_map_[name] = value;
00084 }
00085 }
00086
00093 void sendMetric_(const std::string& name, const int& value, const std::string& unit) override {
00094 sendMetric_(name, std::to_string(value), unit);
00095 }
00096
00103 void sendMetric_(const std::string& name, const double& value, const std::string& unit) override {
00104 sendMetric_(name, std::to_string(value), unit);
00105 }
00106
00113 void sendMetric_(const std::string& name, const float& value, const std::string& unit) override {
00114 sendMetric_(name, std::to_string(value), unit);
00115 }
00116
00123 void sendMetric_(const std::string& name, const unsigned long int& value, const std::string& unit) override
00124 {
00125 sendMetric_(name, std::to_string(value), unit);
00126 }
00127
00131 void startMetrics_() override
00132 {
00133 if (stopped_)
00134 {
00135
00136 stopped_ = false;
00137 boost::thread::attributes attrs;
00138 attrs.set_stack_size(4096 * 200);
00139 thread_ = boost::thread(attrs, boost::bind(&ProcFileMetric::writePipe, this));
00140 }
00141 }
00142
00146 void stopMetrics_() override
00147 {
00148 if (!stopped_)
00149 {
00150 stopped_ = true;
00151
00152 TLOG(11) << "stopMetrics_ before open " << pipe_;
00153 int fd = open(pipe_.c_str(), O_RDONLY | O_NONBLOCK);
00154 if (fd == -1) { perror("stopMetrics_ open(\"r\")"); exit(1); }
00155 TLOG(10) << "stopMetrics_ between open and unlink" << pipe_ << " fd=" << fd;
00156 unlink(pipe_.c_str());
00157 TLOG(11) << "stopMetrics_ unlinked " << pipe_;
00158 # if 0
00159 char buf[256];
00160 read(fd, buf, sizeof(buf));
00161 # endif
00162 usleep(10000);
00163 close(fd);
00164 TLOG(11) << "stopMetrics_ after close " << pipe_;
00165 if (thread_.joinable()) thread_.join();
00166 }
00167 }
00168
00172 void writePipe()
00173 {
00174 while (!stopped_)
00175 {
00176 TLOG(11) << "writePipe before open";
00177 int fd = open(pipe_.c_str(), O_WRONLY);
00178 std::string str;
00179 for (auto value : value_map_) {
00180 TLOG(10) << "writePipe open fd=" << fd << " name=" << value.first << " value=" << value.second;
00181 str += value.first + ": " + value.second + "\n";
00182
00183 }
00184 int sts = write(fd, str.c_str(), str.size());
00185 TLOG(11) << "writePipe write complete sts=" << sts;
00186 close(fd);
00187 TLOG(11) << "writePipe after close -- about to usleep";
00188 usleep(400000);
00189 }
00190
00191 }
00192 };
00193 }
00194
00195 DEFINE_ARTDAQ_METRIC(artdaq::ProcFileMetric)