7 #ifndef __PCPMMV_METRIC__
8 #define __PCPMMV_METRIC__ 1
10 #define TRACE_NAME "PCPMMVMetric"
13 #include "artdaq-utilities/Plugins/MetricMacros.hh"
14 #include "fhiclcpp/fwd.h"
16 #include <pcp/pmapi.h>
18 #include <pcp/mmv_stats.h>
34 std::unordered_map<std::string, int> registered_metric_types_;
35 std::vector<mmv_metric_t> registered_metrics_;
40 size_t initial_metric_collection_time_;
41 std::chrono::steady_clock::time_point metric_start_time_;
45 if (registered_metrics_.size() > 0)
47 mmv_stats_flags_t flags{};
48 TLOG(TLVL_INFO) <<
"Going to initialize mmv metric with name " << normalize_name_(app_name_) <<
", metric count " << registered_metrics_.size();
49 TLOG(TLVL_INFO) <<
"First metric name: " << registered_metrics_[0].name <<
", type " << registered_metrics_[0].type <<
", item " << registered_metrics_[0].item;
50 mmvAddr_ = mmv_stats_init(normalize_name_(app_name_).c_str(), domain_, flags, ®istered_metrics_[0], registered_metrics_.size(), 0, 0);
58 mmv_stats_stop(normalize_name_(app_name_).c_str(), mmvAddr_);
63 std::string normalize_name_(std::string name)
67 auto pos = nameTemp.find(
'%');
68 while (pos != std::string::npos)
70 nameTemp = nameTemp.replace(pos, 1,
"Percent");
71 pos = nameTemp.find(
'%');
73 std::replace(nameTemp.begin(), nameTemp.end(),
' ',
'_');
75 if (nameTemp.size() > MMV_NAMEMAX - 1)
77 nameTemp = nameTemp.substr(0, MMV_NAMEMAX - 1);
84 auto dur = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - metric_start_time_).count();
85 TLOG(TLVL_INFO) <<
"Duration since start: " << dur <<
" seconds. (initial = " << initial_metric_collection_time_ <<
" seconds)";
86 if (dur < 0)
return false;
87 return static_cast<size_t>(dur) > initial_metric_collection_time_;
90 pmUnits infer_units_(std::string unitString)
93 output.scaleCount = PM_COUNT_ONE;
94 output.scaleSpace = PM_SPACE_BYTE;
95 output.scaleTime = PM_TIME_SEC;
97 std::transform(unitString.begin(), unitString.end(), unitString.begin(), ::tolower);
98 std::string before = unitString;
99 std::string after =
"";
101 if (
auto pos = unitString.find(
'/') != std::string::npos)
103 before = unitString.substr(0, pos - 1);
104 after = unitString.substr(pos);
106 std::istringstream iss(before);
107 std::vector<std::string> before_tokens{std::istream_iterator<std::string>{iss},
108 std::istream_iterator<std::string>{}};
111 std::vector<std::string> after_tokens{std::istream_iterator<std::string>{iss},
112 std::istream_iterator<std::string>{}};
114 for (
auto token : before_tokens)
116 if (token ==
"")
continue;
117 if (token ==
"s" || token.find(
"sec") == 0)
121 else if (token ==
"b" || token.find(
"byte") == 0)
131 for (
auto token : after_tokens)
133 if (token ==
"")
continue;
134 if (token ==
"s" || token.find(
"sec") == 0)
138 else if (token ==
"b" || token.find(
"byte") == 0)
160 explicit PCPMMVMetric(fhicl::ParameterSet
const& pset, std::string
const& app_name)
161 : MetricPlugin(pset, app_name)
162 , registered_metric_types_()
163 , registered_metrics_()
165 , domain_(pset.get<int>(
"pcp_domain_number", 0))
166 , initial_metric_collection_time_(pset.get<size_t>(
"seconds_before_init", 30))
169 virtual ~
PCPMMVMetric() { MetricPlugin::stopMetrics(); }
185 void startMetrics_()
override { metric_start_time_ = std::chrono::steady_clock::now(); }
193 void sendMetric_(
const std::string& name,
const std::string& value,
const std::string& unit)
override
195 auto nname = normalize_name_(name);
196 if (!registered_metric_types_.count(nname))
198 TLOG(TLVL_INFO) <<
"Adding string metric named " << nname;
199 mmv_metric_t newMetric;
200 strcpy(newMetric.name, nname.c_str());
201 newMetric.item = registered_metrics_.size();
202 newMetric.type = MMV_TYPE_STRING;
203 newMetric.semantics = MMV_SEM_INSTANT;
204 newMetric.dimension = infer_units_(unit);
206 newMetric.helptext = 0;
207 newMetric.shorttext = 0;
209 registered_metrics_.push_back(newMetric);
210 registered_metric_types_[nname] = MMV_TYPE_STRING;
214 if (registered_metric_types_[nname] != MMV_TYPE_STRING)
216 TLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
217 <<
", got std::string";
221 if (!mmvAddr_ && check_time_())
228 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(), 0);
230 if (val.size() > MMV_STRINGMAX - 1)
232 val = val.substr(0, MMV_STRINGMAX - 1);
235 mmv_set_string(mmvAddr_, base, value.c_str(), value.size());
245 void sendMetric_(
const std::string& name,
const int& value,
const std::string& unit)
override
247 auto nname = normalize_name_(name);
248 if (!registered_metric_types_.count(nname))
250 TLOG(TLVL_INFO) <<
"Adding int metric named " << nname;
251 mmv_metric_t newMetric;
252 strcpy(newMetric.name, nname.c_str());
253 newMetric.item = registered_metrics_.size();
254 newMetric.type = MMV_TYPE_I64;
255 newMetric.semantics = MMV_SEM_INSTANT;
256 newMetric.dimension = infer_units_(unit);
258 newMetric.helptext = 0;
259 newMetric.shorttext = 0;
261 registered_metrics_.push_back(newMetric);
262 registered_metric_types_[nname] = MMV_TYPE_I64;
266 if (registered_metric_types_[nname] != MMV_TYPE_I64)
268 TLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
273 if (!mmvAddr_ && check_time_())
280 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(), 0);
281 mmv_set_value(mmvAddr_, base, value);
291 void sendMetric_(
const std::string& name,
const double& value,
const std::string& unit)
override
293 auto nname = normalize_name_(name);
294 if (!registered_metric_types_.count(nname))
296 TLOG(TLVL_INFO) <<
"Adding double metric named " << nname;
297 mmv_metric_t newMetric;
298 strcpy(newMetric.name, nname.c_str());
299 newMetric.item = registered_metrics_.size();
300 newMetric.type = MMV_TYPE_DOUBLE;
301 newMetric.semantics = MMV_SEM_INSTANT;
302 newMetric.dimension = infer_units_(unit);
304 newMetric.helptext = 0;
305 newMetric.shorttext = 0;
307 registered_metrics_.push_back(newMetric);
308 registered_metric_types_[nname] = MMV_TYPE_DOUBLE;
312 if (registered_metric_types_[nname] != MMV_TYPE_DOUBLE)
314 TLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
319 if (!mmvAddr_ && check_time_())
326 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(), 0);
327 mmv_set_value(mmvAddr_, base, value);
337 void sendMetric_(
const std::string& name,
const float& value,
const std::string& unit)
override
339 auto nname = normalize_name_(name);
340 if (!registered_metric_types_.count(nname))
342 TLOG(TLVL_INFO) <<
"Adding float metric named " << nname;
343 mmv_metric_t newMetric;
344 strcpy(newMetric.name, nname.c_str());
345 newMetric.item = registered_metrics_.size();
346 newMetric.type = MMV_TYPE_FLOAT;
347 newMetric.semantics = MMV_SEM_INSTANT;
348 newMetric.dimension = infer_units_(unit);
350 newMetric.helptext = 0;
351 newMetric.shorttext = 0;
353 registered_metrics_.push_back(newMetric);
354 registered_metric_types_[nname] = MMV_TYPE_FLOAT;
358 if (registered_metric_types_[nname] != MMV_TYPE_FLOAT)
360 TLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
365 if (!mmvAddr_ && check_time_())
372 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(), 0);
373 mmv_set_value(mmvAddr_, base, value);
383 void sendMetric_(
const std::string& name,
const unsigned long int& value,
const std::string& unit)
override
385 auto nname = normalize_name_(name);
386 if (!registered_metric_types_.count(nname))
388 TLOG(TLVL_INFO) <<
"Adding unsigned metric named " << nname;
389 mmv_metric_t newMetric;
390 strcpy(newMetric.name, nname.c_str());
391 newMetric.item = registered_metrics_.size();
392 newMetric.type = MMV_TYPE_U64;
393 newMetric.semantics = MMV_SEM_INSTANT;
394 newMetric.dimension = infer_units_(unit);
396 newMetric.helptext = 0;
397 newMetric.shorttext = 0;
399 registered_metrics_.push_back(newMetric);
400 registered_metric_types_[nname] = MMV_TYPE_U64;
404 if (registered_metric_types_[nname] != MMV_TYPE_U64)
406 TLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
407 <<
", got unsigned int";
411 if (!mmvAddr_ && check_time_())
418 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(), 0);
419 mmv_set_value(mmvAddr_, base, value);
427 #endif // End ifndef __PCPMMV_METRIC__
void sendMetric_(const std::string &name, const int &value, const std::string &unit) override
Send a integer metric to PCPMMV.
PCPMMVMetric(fhicl::ParameterSet const &pset, std::string const &app_name)
Construct an instance of the PCPMMV metric.
std::string getLibName() const override
Gets the unique library name of this plugin.
void sendMetric_(const std::string &name, const std::string &value, const std::string &unit) override
Send a string metric to PCPMMV.
void stopMetrics_() override
PCPMMV does not need any specific action on stop.
void startMetrics_() override
PCPMMV does not need any specific action on start.
void sendMetric_(const std::string &name, const double &value, const std::string &unit) override
Send a double metric to PCPMMV.
void sendMetric_(const std::string &name, const float &value, const std::string &unit) override
Send a float metric to PCPMMV.
An instance of the MetricPlugin class that sends metric data to PCPMMV.
void sendMetric_(const std::string &name, const unsigned long int &value, const std::string &unit) override
Send an unsigned long metric to PCPMMV.