7 #ifndef __PCPMMV_METRIC__
8 #define __PCPMMV_METRIC__ 1
10 #include "TRACE/tracemf.h"
11 #define TRACE_NAME (app_name_ + "_pcpmmv_metric").c_str()
13 #include "artdaq-utilities/Plugins/MetricMacros.hh"
14 #include "fhiclcpp/fwd.h"
17 #include <pcp/pmapi.h>
19 #include <pcp/mmv_stats.h>
37 std::unordered_map<std::string, int> registered_metric_types_;
38 std::vector<mmv_metric_t> registered_metrics_;
43 size_t initial_metric_collection_time_;
44 std::chrono::steady_clock::time_point metric_start_time_;
46 void copy_string(
char* dest,
size_t dstsize,
const std::string& src)
48 if (src.size() <= dstsize - 1)
50 dstsize = src.size() + 1;
52 memcpy(dest, src.c_str(), dstsize);
57 if (!registered_metrics_.empty())
59 mmv_stats_flags_t flags{};
60 METLOG(TLVL_INFO) <<
"Going to initialize mmv metric with name " << normalize_name_(app_name_) <<
", metric count " << registered_metrics_.size();
61 METLOG(TLVL_INFO) <<
"First metric name: " << registered_metrics_[0].name <<
", type " << registered_metrics_[0].type <<
", item " << registered_metrics_[0].item;
62 mmvAddr_ = mmv_stats_init(normalize_name_(app_name_).c_str(), domain_, flags, ®istered_metrics_[0], registered_metrics_.size(),
nullptr, 0);
68 if (mmvAddr_ !=
nullptr)
70 mmv_stats_stop(normalize_name_(app_name_).c_str(), mmvAddr_);
75 std::string normalize_name_(std::string name)
77 auto nameTemp(std::move(name));
79 auto pos = nameTemp.find(
'%');
80 while (pos != std::string::npos)
82 nameTemp = nameTemp.replace(pos, 1,
"Percent");
83 pos = nameTemp.find(
'%');
85 std::replace(nameTemp.begin(), nameTemp.end(),
' ',
'_');
87 if (nameTemp.size() > MMV_NAMEMAX - 1)
89 nameTemp = nameTemp.substr(0, MMV_NAMEMAX - 1);
96 auto dur = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - metric_start_time_).count();
97 METLOG(TLVL_INFO) <<
"Duration since start: " << dur <<
" seconds. (initial = " << initial_metric_collection_time_ <<
" seconds)";
102 return static_cast<size_t>(dur) > initial_metric_collection_time_;
105 pmUnits infer_units_(std::string unitString)
108 output.scaleCount = PM_COUNT_ONE;
109 output.scaleSpace = PM_SPACE_BYTE;
110 output.scaleTime = PM_TIME_SEC;
115 std::transform(unitString.begin(), unitString.end(), unitString.begin(), ::tolower);
116 std::string before = unitString;
119 if (
auto pos = unitString.find(
'/') != std::string::npos)
121 before = unitString.substr(0, static_cast<int>(pos) - 1);
122 after = unitString.substr(pos);
124 std::istringstream iss(before);
125 std::vector<std::string> before_tokens{std::istream_iterator<std::string>{iss},
126 std::istream_iterator<std::string>{}};
129 std::vector<std::string> after_tokens{std::istream_iterator<std::string>{iss},
130 std::istream_iterator<std::string>{}};
132 for (
const auto& token : before_tokens)
138 if (token ==
"s" || token.find(
"sec") == 0)
142 else if (token ==
"b" || token.find(
"byte") == 0)
152 for (
const auto& token : after_tokens)
158 if (token ==
"s" || token.find(
"sec") == 0)
162 else if (token ==
"b" || token.find(
"byte") == 0)
190 explicit PCPMMVMetric(fhicl::ParameterSet
const& pset, std::string
const& app_name, std::string
const& metric_name)
191 : MetricPlugin(pset, app_name, metric_name)
192 , registered_metric_types_()
193 , registered_metrics_()
195 , domain_(pset.get<int>(
"pcp_domain_number", 0))
196 , initial_metric_collection_time_(pset.get<size_t>(
"seconds_before_init", 30))
199 ~
PCPMMVMetric()
override { MetricPlugin::stopMetrics(); }
215 void startMetrics_()
override { metric_start_time_ = std::chrono::steady_clock::now(); }
223 void sendMetric_(
const std::string& name,
const std::string& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
225 auto nname = normalize_name_(name);
226 if (registered_metric_types_.count(nname) == 0u)
228 METLOG(TLVL_INFO) <<
"Adding string metric named " << nname;
229 mmv_metric_t newMetric;
230 copy_string(newMetric.name, MMV_NAMEMAX, nname);
231 newMetric.item = registered_metrics_.size();
232 newMetric.type = MMV_TYPE_STRING;
233 newMetric.semantics = MMV_SEM_INSTANT;
234 newMetric.dimension = infer_units_(unit);
236 newMetric.helptext =
nullptr;
237 newMetric.shorttext =
nullptr;
239 registered_metrics_.push_back(newMetric);
240 registered_metric_types_[nname] = MMV_TYPE_STRING;
244 if (registered_metric_types_[nname] != MMV_TYPE_STRING)
246 METLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
247 <<
", got std::string";
251 if ((mmvAddr_ ==
nullptr) && check_time_())
256 if (mmvAddr_ !=
nullptr)
258 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(),
nullptr);
260 if (val.size() > MMV_STRINGMAX - 1)
262 val = val.substr(0, MMV_STRINGMAX - 1);
265 mmv_set_string(mmvAddr_, base, value.c_str(), value.size());
275 void sendMetric_(
const std::string& name,
const int& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
277 auto nname = normalize_name_(name);
278 if (registered_metric_types_.count(nname) == 0u)
280 METLOG(TLVL_INFO) <<
"Adding int metric named " << nname;
281 mmv_metric_t newMetric;
282 copy_string(newMetric.name, MMV_NAMEMAX, nname);
283 newMetric.item = registered_metrics_.size();
284 newMetric.type = MMV_TYPE_I64;
285 newMetric.semantics = MMV_SEM_INSTANT;
286 newMetric.dimension = infer_units_(unit);
288 newMetric.helptext =
nullptr;
289 newMetric.shorttext =
nullptr;
291 registered_metrics_.push_back(newMetric);
292 registered_metric_types_[nname] = MMV_TYPE_I64;
296 if (registered_metric_types_[nname] != MMV_TYPE_I64)
298 METLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
303 if ((mmvAddr_ ==
nullptr) && check_time_())
308 if (mmvAddr_ !=
nullptr)
310 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(),
nullptr);
311 mmv_set_value(mmvAddr_, base, value);
321 void sendMetric_(
const std::string& name,
const double& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
323 auto nname = normalize_name_(name);
324 if (registered_metric_types_.count(nname) == 0u)
326 METLOG(TLVL_INFO) <<
"Adding double metric named " << nname;
327 mmv_metric_t newMetric;
328 copy_string(newMetric.name, MMV_NAMEMAX, nname);
329 newMetric.item = registered_metrics_.size();
330 newMetric.type = MMV_TYPE_DOUBLE;
331 newMetric.semantics = MMV_SEM_INSTANT;
332 newMetric.dimension = infer_units_(unit);
334 newMetric.helptext =
nullptr;
335 newMetric.shorttext =
nullptr;
337 registered_metrics_.push_back(newMetric);
338 registered_metric_types_[nname] = MMV_TYPE_DOUBLE;
342 if (registered_metric_types_[nname] != MMV_TYPE_DOUBLE)
344 METLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
349 if ((mmvAddr_ ==
nullptr) && check_time_())
354 if (mmvAddr_ !=
nullptr)
356 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(),
nullptr);
357 mmv_set_value(mmvAddr_, base, value);
367 void sendMetric_(
const std::string& name,
const float& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
369 auto nname = normalize_name_(name);
370 if (registered_metric_types_.count(nname) == 0u)
372 METLOG(TLVL_INFO) <<
"Adding float metric named " << nname;
373 mmv_metric_t newMetric;
374 copy_string(newMetric.name, MMV_NAMEMAX, nname);
375 newMetric.item = registered_metrics_.size();
376 newMetric.type = MMV_TYPE_FLOAT;
377 newMetric.semantics = MMV_SEM_INSTANT;
378 newMetric.dimension = infer_units_(unit);
380 newMetric.helptext =
nullptr;
381 newMetric.shorttext =
nullptr;
383 registered_metrics_.push_back(newMetric);
384 registered_metric_types_[nname] = MMV_TYPE_FLOAT;
388 if (registered_metric_types_[nname] != MMV_TYPE_FLOAT)
390 METLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
395 if ((mmvAddr_ ==
nullptr) && check_time_())
400 if (mmvAddr_ !=
nullptr)
402 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(),
nullptr);
403 mmv_set_value(mmvAddr_, base, value);
413 void sendMetric_(
const std::string& name,
const uint64_t& value,
const std::string& unit,
const std::chrono::system_clock::time_point&)
override
415 auto nname = normalize_name_(name);
416 if (registered_metric_types_.count(nname) == 0u)
418 METLOG(TLVL_INFO) <<
"Adding unsigned metric named " << nname;
419 mmv_metric_t newMetric;
420 copy_string(newMetric.name, MMV_NAMEMAX, nname);
421 newMetric.item = registered_metrics_.size();
422 newMetric.type = MMV_TYPE_U64;
423 newMetric.semantics = MMV_SEM_INSTANT;
424 newMetric.dimension = infer_units_(unit);
426 newMetric.helptext =
nullptr;
427 newMetric.shorttext =
nullptr;
429 registered_metrics_.push_back(newMetric);
430 registered_metric_types_[nname] = MMV_TYPE_U64;
434 if (registered_metric_types_[nname] != MMV_TYPE_U64)
436 METLOG(TLVL_ERROR) <<
"PCP-MMV Metric: Metric instance has wrong type! Expected " << registered_metric_types_[nname]
437 <<
", got unsigned int";
441 if ((mmvAddr_ ==
nullptr) && check_time_())
446 if (mmvAddr_ !=
nullptr)
448 auto base = mmv_lookup_value_desc(mmvAddr_, nname.c_str(),
nullptr);
449 mmv_set_value(mmvAddr_, base, value);
457 #endif // End ifndef __PCPMMV_METRIC__
void sendMetric_(const std::string &name, const float &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send a float metric to PCPMMV.
PCPMMVMetric(fhicl::ParameterSet const &pset, std::string const &app_name, std::string const &metric_name)
Construct an instance of the PCPMMV metric.
void sendMetric_(const std::string &name, const int &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send a integer metric to PCPMMV.
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, const std::chrono::system_clock::time_point &) 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 uint64_t &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send an unsigned long metric to PCPMMV.
An instance of the MetricPlugin class that sends metric data to PCPMMV.
void sendMetric_(const std::string &name, const double &value, const std::string &unit, const std::chrono::system_clock::time_point &) override
Send a double metric to PCPMMV.