diff --git a/broker/core/src/misc/parse_perfdata.cc b/broker/core/src/misc/parse_perfdata.cc index 0256fd532bf..0a50b70da39 100644 --- a/broker/core/src/misc/parse_perfdata.cc +++ b/broker/core/src/misc/parse_perfdata.cc @@ -16,6 +16,8 @@ ** For more information : contact@centreon.com */ +#include +#include #include #include #include @@ -127,6 +129,8 @@ std::list misc::parse_perfdata(uint32_t host_id, uint32_t service_id, const char* str) { std::list retval; + absl::flat_hash_set metric_name; + absl::string_view current_name; auto id = [host_id, service_id] { if (host_id || service_id) return fmt::format("({}:{})", host_id, service_id); @@ -203,10 +207,20 @@ std::list misc::parse_perfdata(uint32_t host_id, } if (end - s + 1 > 0) { + current_name = absl::string_view(s, end - s + 1); std::string name(s, end - s + 1); - name.resize(misc::string::adjust_size_utf8( - name, get_metrics_col_size(metrics_metric_name))); - p.name(std::move(name)); + if (metric_name.contains(current_name)) { + log_v2::perfdata()->warn( + "storage: The metric '{}' appears several times in the output " + "\"{}\": you will lose any new occurence of this metric", + name, str); + error = true; + } else { + name.resize(misc::string::adjust_size_utf8( + name, get_metrics_col_size( + metrics_metric_name))); + p.name(std::move(name)); + } } else { log_v2::perfdata()->error( "In service {}, metric name empty before '{}...'", id(), @@ -298,7 +312,8 @@ std::list misc::parse_perfdata(uint32_t host_id, p.max()); // Append to list. - retval.emplace_back(std::move(p)); + metric_name.insert(current_name); + retval.push_back(std::move(p)); // Skip whitespaces. while (isspace(*tmp)) diff --git a/broker/core/src/misc/perfdata.cc b/broker/core/src/misc/perfdata.cc index b21d1f66764..f47b29e642b 100644 --- a/broker/core/src/misc/perfdata.cc +++ b/broker/core/src/misc/perfdata.cc @@ -17,7 +17,6 @@ */ #include "com/centreon/broker/misc/perfdata.hh" - #include using namespace com::centreon::broker::misc; diff --git a/broker/core/test/misc/perfdata.cc b/broker/core/test/misc/perfdata.cc index 2811bb5622c..c0b758d774c 100644 --- a/broker/core/test/misc/perfdata.cc +++ b/broker/core/test/misc/perfdata.cc @@ -250,6 +250,58 @@ TEST_F(MiscParserParsePerfdata, Simple2) { ASSERT_TRUE(expected == *it); } +TEST_F(MiscParserParsePerfdata, SeveralIdenticalMetrics) { + // Parse perfdata. + std::list list{misc::parse_perfdata( + 0, 0, "'et'=18.00%;15:;10:;0;100 other=15 et=13.00%")}; + + // Assertions. + ASSERT_EQ(list.size(), 2u); + std::list::const_iterator it = list.begin(); + misc::perfdata expected; + expected.name("et"); + expected.value_type(misc::perfdata::gauge); + expected.value(18.0); + expected.unit("%"); + expected.warning(std::numeric_limits::infinity()); + expected.warning_low(15.0); + expected.critical(std::numeric_limits::infinity()); + expected.critical_low(10.0); + expected.min(0.0); + expected.max(100.0); + ASSERT_TRUE(expected == *it); + ++it; + ASSERT_EQ(it->name(), std::string_view("other")); + ASSERT_EQ(it->value(), 15); + ASSERT_EQ(it->value_type(), misc::perfdata::gauge); +} + +TEST_F(MiscParserParsePerfdata, ComplexSeveralIdenticalMetrics) { + // Parse perfdata. + std::list list{misc::parse_perfdata( + 0, 0, "'d[foo]'=18.00%;15:;10:;0;100 other=15 a[foo]=13.00%")}; + + // Assertions. + ASSERT_EQ(list.size(), 2u); + std::list::const_iterator it = list.begin(); + misc::perfdata expected; + expected.name("foo"); + expected.value_type(misc::perfdata::derive); + expected.value(18.0); + expected.unit("%"); + expected.warning(std::numeric_limits::infinity()); + expected.warning_low(15.0); + expected.critical(std::numeric_limits::infinity()); + expected.critical_low(10.0); + expected.min(0.0); + expected.max(100.0); + ASSERT_TRUE(expected == *it); + ++it; + ASSERT_EQ(it->name(), std::string_view("other")); + ASSERT_EQ(it->value(), 15); + ASSERT_EQ(it->value_type(), misc::perfdata::gauge); +} + TEST_F(MiscParserParsePerfdata, Complex1) { // Parse perfdata. std::list list{misc::parse_perfdata(