From e277e51d10fded3011300b4b371553029ab933cf Mon Sep 17 00:00:00 2001 From: Jean Christophe Roques Date: Thu, 14 Nov 2024 15:52:55 +0100 Subject: [PATCH] fix agent test memory corruption, add drive_size ut --- agent/inc/com/centreon/agent/drive_size.hh | 39 +- agent/native_windows/src/check_drive_size.cc | 4 + agent/src/drive_size.cc | 41 +- agent/test/CMakeLists.txt | 1 + agent/test/check_linux_cpu_test.cc | 26 +- agent/test/check_uptime_test.cc | 29 +- agent/test/check_windows_cpu_test.cc | 25 +- agent/test/drive_size_test.cc | 601 +++++++++++++++++++ broker/victoria_metrics/src/factory.cc | 7 +- broker/victoria_metrics/test/request_test.cc | 2 +- common/inc/com/centreon/common/perfdata.hh | 4 +- common/src/perfdata.cc | 4 + 12 files changed, 714 insertions(+), 69 deletions(-) create mode 100644 agent/test/drive_size_test.cc diff --git a/agent/inc/com/centreon/agent/drive_size.hh b/agent/inc/com/centreon/agent/drive_size.hh index c4c1ffe2f51..f176290abe1 100644 --- a/agent/inc/com/centreon/agent/drive_size.hh +++ b/agent/inc/com/centreon/agent/drive_size.hh @@ -22,6 +22,7 @@ #include #include #include "absl/base/thread_annotations.h" +#include "absl/container/btree_set.h" #include "absl/synchronization/mutex.h" #include "boost/asio/io_context.hpp" #include "check.hh" @@ -109,9 +110,28 @@ class filter { struct fs_stat { fs_stat() = default; fs_stat(std::string&& fs_in, uint64_t used_in, uint64_t total_in) - : fs(fs_in), used(used_in), total(total_in) {} + : fs(fs_in), mount_point(fs), used(used_in), total(total_in) {} + + fs_stat(std::string&& fs_in, + std::string&& mount_point_in, + uint64_t used_in, + uint64_t total_in) + : fs(fs_in), + mount_point(mount_point_in), + used(used_in), + total(total_in) {} + + fs_stat(const std::string_view& fs_in, + const std::string_view& mount_point_in, + uint64_t used_in, + uint64_t total_in) + : fs(fs_in), + mount_point(mount_point_in), + used(used_in), + total(total_in) {} std::string fs; + std::string mount_point; uint64_t used; uint64_t total; @@ -119,8 +139,8 @@ struct fs_stat { return used >= threshold; } - bool is_free_more_than_threshold(uint64_t threshold) const { - return total - used >= threshold; + bool is_free_less_than_threshold(uint64_t threshold) const { + return total - used < threshold; } bool is_used_more_than_prct_threshold(uint64_t percent_hundredth) const { @@ -130,11 +150,11 @@ struct fs_stat { return (used * 10000) / total >= percent_hundredth; } - bool is_free_more_than_prct_threshold(uint64_t percent_hundredth) const { + bool is_free_less_than_prct_threshold(uint64_t percent_hundredth) const { if (!total) { return true; } - return ((total - used) * 10000) / total >= percent_hundredth; + return ((total - used) * 10000) / total < percent_hundredth; } double get_used_prct() const { @@ -182,8 +202,9 @@ class drive_size_thread static get_fs_stats os_fs_stats; - drive_size_thread(const std::shared_ptr& logger) - : _logger(logger) {} + drive_size_thread(const std::shared_ptr& io_context, + const std::shared_ptr& logger) + : _io_context(io_context), _logger(logger) {} void run(); @@ -197,6 +218,10 @@ class drive_size_thread } // namespace check_drive_size_detail +/** + * @brief drive size check object (same for linux and windows) + * + */ class check_drive_size : public check { std::shared_ptr _filter; bool _prct_threshold; diff --git a/agent/native_windows/src/check_drive_size.cc b/agent/native_windows/src/check_drive_size.cc index 82441bafa58..8b81b695a90 100644 --- a/agent/native_windows/src/check_drive_size.cc +++ b/agent/native_windows/src/check_drive_size.cc @@ -129,6 +129,10 @@ std::list os_fs_stats(filter& filt, &total_number_of_free_bytes); if (success) { + SPDLOG_LOGGER_TRACE(logger, "{} total: {}, free {}", fs_to_test, + total_number_of_bytes.QuadPart , + total_number_of_free_bytes.QuadPart); + result.emplace_back(std::move(fs_to_test), total_number_of_bytes.QuadPart - total_number_of_free_bytes.QuadPart, diff --git a/agent/src/drive_size.cc b/agent/src/drive_size.cc index 276c91921f5..23ef5b16dd2 100644 --- a/agent/src/drive_size.cc +++ b/agent/src/drive_size.cc @@ -103,7 +103,7 @@ filter::filter(const rapidjson::Value& args) : _fs_type_filter(0xFFFFFFFFU) { throw exceptions::msg_fmt("invalid regex for filter-storage-type: {}", member_iter->value.GetString()); } - + _fs_type_filter = 0; for (const auto& [label, flag] : _fs_type) { if (RE2::FullMatch(label, filter_typ_re)) { _fs_type_filter |= flag; @@ -115,7 +115,7 @@ filter::filter(const rapidjson::Value& args) : _fs_type_filter(0xFFFFFFFFU) { throw exceptions::msg_fmt("invalid regex for filter-fs: {}", member_iter->value.GetString()); } - } else if (member_iter->name == "filter-exclude-fs") { + } else if (member_iter->name == "exclude-fs") { _filter_exclude_fs = std::make_unique(member_iter->value.GetString()); if (!_filter_exclude_fs->ok()) { // NOLINT @@ -129,7 +129,7 @@ filter::filter(const rapidjson::Value& args) : _fs_type_filter(0xFFFFFFFFU) { throw exceptions::msg_fmt("invalid regex for filter-mountpoint: {}", member_iter->value.GetString()); } - } else if (member_iter->name == "filter-exclude-mountpoint") { + } else if (member_iter->name == "exclude-mountpoint") { _filter_exclude_mountpoint = std::make_unique(member_iter->value.GetString()); if (!_filter_exclude_mountpoint->ok()) { @@ -261,20 +261,23 @@ void drive_size_thread::run() { while (!_queue.empty()) { if (_queue.begin()->timeout < now) { _queue.pop_front(); + } else { + break; } } if (!_queue.empty()) { + auto to_execute = _queue.begin(); std::list stats = - os_fs_stats(*_queue.begin()->request_filter, _logger); + os_fs_stats(*to_execute->request_filter, _logger); // main code of this program is not thread safe, so we use io_context // launched from main thread to call callback _io_context->post( [result = std::move(stats), - completion_handler = std::move(_queue.begin()->handler)]() { + completion_handler = std::move(to_execute->handler)]() { completion_handler(result); }); - _queue.pop_front(); + _queue.erase(to_execute); } } } @@ -342,7 +345,11 @@ check_drive_size::check_drive_size( if (args.IsObject()) { common::rapidjson_helper helper(args); - _prct_threshold = helper.get_string("units", "%") == "%"sv; + if (args.HasMember("unit")) { + _prct_threshold = helper.get_string("unit", "%") == "%"sv; + } else { + _prct_threshold = helper.get_string("units", "%") == "%"sv; + } _free_threshold = helper.get_bool("free", false); _warning = helper.get_uint64_t("warning", 0); @@ -416,10 +423,10 @@ e_status check_drive_size::_prct_used_test( */ e_status check_drive_size::_free_test( const check_drive_size_detail::fs_stat& fs) const { - if (_critical && fs.is_free_more_than_threshold(_critical)) { + if (_critical && fs.is_free_less_than_threshold(_critical)) { return e_status::critical; } - if (_warning && fs.is_free_more_than_threshold(_warning)) { + if (_warning && fs.is_free_less_than_threshold(_warning)) { return e_status::warning; } return e_status::ok; @@ -433,10 +440,10 @@ e_status check_drive_size::_free_test( */ e_status check_drive_size::_prct_free_test( const check_drive_size_detail::fs_stat& fs) const { - if (_critical && fs.is_free_more_than_prct_threshold(_critical)) { + if (_critical && fs.is_free_less_than_prct_threshold(_critical)) { return e_status::critical; } - if (_warning && fs.is_free_more_than_prct_threshold(_warning)) { + if (_warning && fs.is_free_less_than_prct_threshold(_warning)) { return e_status::warning; } return e_status::ok; @@ -454,8 +461,8 @@ void check_drive_size::start_check(const duration& timeout) { } if (!_worker_thread) { - _worker = - std::make_shared(_logger); + _worker = std::make_shared( + _io_context, _logger); _worker_thread = new std::thread([worker = _worker] { worker->run(); }); } @@ -496,18 +503,18 @@ void check_drive_size::_completion_handler( output += fs_status == e_status::critical ? "CRITICAL: " : "WARNING: "; if (_prct_threshold) { output += fmt::format("{} Total: {}G Used: {:.2f}% Free: {:.2f}%", - fs.fs, fs.total / 1024 / 1024 / 1024, + fs.mount_point, fs.total / 1024 / 1024 / 1024, fs.get_used_prct(), fs.get_free_prct()); } else { - output += fmt::format("{} Total: {}G Used: {}G Free: {}G", fs.fs, - fs.total / 1024 / 1024 / 1024, + output += fmt::format("{} Total: {}G Used: {}G Free: {}G", + fs.mount_point, fs.total / 1024 / 1024 / 1024, fs.used / 1024 / 1024 / 1024, (fs.total - fs.used) / 1024 / 1024 / 1024); } } centreon::common::perfdata perf; - perf.name((_free_threshold ? "free_" : "used_") + fs.fs); + perf.name((_free_threshold ? "free_" : "used_") + fs.mount_point); if (_prct_threshold) { perf.unit("%"); diff --git a/agent/test/CMakeLists.txt b/agent/test/CMakeLists.txt index 94b89f859d8..0bdeed186fc 100644 --- a/agent/test/CMakeLists.txt +++ b/agent/test/CMakeLists.txt @@ -19,6 +19,7 @@ set( SRC_COMMON check_test.cc check_exec_test.cc + drive_size_test.cc scheduler_test.cc test_main.cc ) diff --git a/agent/test/check_linux_cpu_test.cc b/agent/test/check_linux_cpu_test.cc index 30d8a6b021d..44ef0653efa 100644 --- a/agent/test/check_linux_cpu_test.cc +++ b/agent/test/check_linux_cpu_test.cc @@ -123,6 +123,8 @@ procs_blocked 0 softirq 166407220 66442046 14763247 1577070 4447556 33 0 18081353 30219191 75659 30801065 )"; +using namespace std::string_literals; + TEST(proc_stat_file_test, no_threshold) { constexpr const char* test_file_path = "/tmp/proc_stat_test"; { @@ -149,8 +151,8 @@ TEST(proc_stat_file_test, no_threshold) { rapidjson::Document check_args; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -222,8 +224,8 @@ TEST(proc_stat_file_test, no_threshold_detailed) { rapidjson::Document check_args = R"({"cpu-detailed":true})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -354,8 +356,8 @@ TEST(proc_stat_file_test, threshold_nodetailed) { R"({"warning-core" : "24.1", "critical-core" : "24.4", "warning-average" : "10", "critical-average" : "20"})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -435,8 +437,8 @@ TEST(proc_stat_file_test, threshold_nodetailed2) { R"({"warning-core-iowait" : "0.36", "critical-core-iowait" : "0.39", "warning-average-iowait" : "0.3", "critical-average-iowait" : "0.4"})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -494,8 +496,8 @@ TEST(proc_stat_file_test, threshold_detailed) { R"({"cpu-detailed":true, "warning-core" : "24.1", "critical-core" : "24.4", "warning-average" : "10", "critical-average" : "20"})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -568,8 +570,8 @@ TEST(proc_stat_file_test, threshold_detailed2) { R"({"cpu-detailed":"true", "warning-core-iowait" : "0.36", "critical-core-iowait" : "0.39", "warning-average-iowait" : "0.3", "critical-average-iowait" : "0.4"})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& diff --git a/agent/test/check_uptime_test.cc b/agent/test/check_uptime_test.cc index 092541bb7c6..1fe8d9f5bd6 100644 --- a/agent/test/check_uptime_test.cc +++ b/agent/test/check_uptime_test.cc @@ -25,6 +25,7 @@ extern std::shared_ptr g_io_context; using namespace com::centreon::agent; +using namespace std::string_literals; TEST(native_check_uptime, ok) { using namespace com::centreon::common::literals; @@ -32,8 +33,8 @@ TEST(native_check_uptime, ok) { R"({ "warning-uptime" : "345600", "critical-uptime" : "172800"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -62,8 +63,8 @@ TEST(native_check_uptime, ok_m) { R"({ "warning-uptime" : "5760", "critical-uptime" : "2880", "unit": "m"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -92,8 +93,8 @@ TEST(native_check_uptime, ok_h) { R"({ "warning-uptime" : "96", "critical-uptime" : "48", "unit": "h"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -122,8 +123,8 @@ TEST(native_check_uptime, ok_d) { R"({ "warning-uptime" : "4", "critical-uptime" : "2", "unit": "d"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -152,8 +153,8 @@ TEST(native_check_uptime, ok_w) { R"({ "warning-uptime" : "2", "critical-uptime" : "1", "unit": "w"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -182,8 +183,8 @@ TEST(native_check_uptime, warning) { R"({ "warning-uptime" : "4", "critical-uptime" : "2", "unit": "d"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -212,8 +213,8 @@ TEST(native_check_uptime, critical) { R"({ "warning-uptime" : "4", "critical-uptime" : "2", "unit": "d"})"_json; check_uptime checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& diff --git a/agent/test/check_windows_cpu_test.cc b/agent/test/check_windows_cpu_test.cc index 22000b48815..1856aa4e42a 100644 --- a/agent/test/check_windows_cpu_test.cc +++ b/agent/test/check_windows_cpu_test.cc @@ -25,6 +25,7 @@ extern std::shared_ptr g_io_context; using namespace com::centreon::agent; +using namespace std::string_literals; TEST(native_check_cpu_windows, construct) { check_cpu_detail::M_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info; @@ -76,8 +77,8 @@ TEST(native_check_cpu_windows, output_no_threshold) { rapidjson::Document check_args; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -137,8 +138,8 @@ TEST(native_check_cpu_windows, output_no_threshold_detailed) { rapidjson::Document check_args = R"({"cpu-detailed":true})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -232,8 +233,8 @@ TEST(native_check_cpu_windows, output_threshold) { R"({"warning-core" : "39", "critical-core" : "59", "warning-average" : "49", "critical-average" : "60"})"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -305,8 +306,8 @@ TEST(native_check_cpu_windows, output_threshold_detailed) { R"({"cpu-detailed":true, "warning-core" : "39", "critical-core" : "59", "warning-average" : "49", "critical-average" : "60", "warning-core-user": "30", "critical-core-user": "40", "warning-average-user": "31", "critical-average-user": "41" })"_json; check_cpu checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -455,8 +456,8 @@ TEST(native_check_cpu_windows, compare_kernel_dph) { R"({"use-nt-query-system-information":true })"_json; check_cpu nt_checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", nt_check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, nt_check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& @@ -467,8 +468,8 @@ TEST(native_check_cpu_windows, compare_kernel_dph) { R"({"use-nt-query-system-information":false })"_json; check_cpu pdh_checker( - g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name", - "cmd_line", pdh_check_args, nullptr, + g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s, + "cmd_line"s, pdh_check_args, nullptr, []([[maybe_unused]] const std::shared_ptr& caller, [[maybe_unused]] int status, [[maybe_unused]] const std::list& diff --git a/agent/test/drive_size_test.cc b/agent/test/drive_size_test.cc new file mode 100644 index 00000000000..4b18fe59bbc --- /dev/null +++ b/agent/test/drive_size_test.cc @@ -0,0 +1,601 @@ +/** + * Copyright 2024 Centreon + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * For more information : contact@centreon.com + */ + +#include +#include +#include +#include +#include +#include + +#include "com/centreon/common/rapidjson_helper.hh" + +#include "drive_size.hh" + +extern std::shared_ptr g_io_context; + +using namespace com::centreon::agent; +using namespace com::centreon::agent::check_drive_size_detail; + +struct sample { + std::string_view fs; + std::string_view mount_point; + uint64_t fs_type; + uint64_t used; + uint64_t total; +}; + +std::array _samples = { + {{"udev", "/dev", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_other, + 0, 6024132000}, + + {"tmpfs", "/run", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_other, + 16760000, 1212868000}, + {"/dev/sda12", "/", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_linux_ext4, + 136830444000, 346066920000}, + {"tmpfs", "/dev/shm", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_other, + 0, 6072708000}, + {"tmpfs", "/run/lock", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_other, + 4000, 5116000}, + {"tmpfs", "/sys/fs/cgroup", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_other, + 0, 6072708000}, + {"/dev/sda11", "/boot/efi", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_fat, + 24000, 524248000}, + {"/dev/sda5", "/data", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_fat32, + 3072708000, 6072708000}, + {"tmpfs", "/run/user/1001", + check_drive_size_detail::e_drive_fs_type::hr_storage_fixed_disk | + check_drive_size_detail::e_drive_fs_type::hr_fs_other, + 100000, 1214440000}}}; + +class drive_size_test : public ::testing::Test { + public: + static std::list compute( + filter& filt, + const std::shared_ptr& logger); + + static void SetUpTestCase() { drive_size_thread::os_fs_stats = compute; } + static void TearDownTestCase() { check_drive_size::thread_kill(); } +}; + +std::list drive_size_test::compute( + filter& filt, + const std::shared_ptr&) { + std::list result; + for (const auto& s : _samples) { + if (filt.is_allowed(s.fs, s.mount_point, + static_cast(s.fs_type))) { + result.emplace_back(s.fs, s.mount_point, s.used, s.total); + } + } + return result; +} + +using namespace std::string_literals; + +TEST_F(drive_size_test, test_fs_filter1) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "1000000", "critical" : "20000000", "unit": "b", + "filter-type": "^hrfsother$"})"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, "WARNING: /run Total: 1G Used: 0G Free: 1G"); + ASSERT_EQ(perfs.size(), 6); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "B"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 1000000); + ASSERT_EQ(p.critical(), 20000000); + if (p.name() == "used_/dev") { + ASSERT_EQ(p.value(), 0); + ASSERT_EQ(p.max(), 6024132000); + } else if (p.name() == "used_/run") { + ASSERT_EQ(p.value(), 16760000); + ASSERT_EQ(p.max(), 1212868000); + } else if (p.name() == "used_/dev/shm") { + ASSERT_EQ(p.value(), 0); + ASSERT_EQ(p.max(), 6072708000); + } else if (p.name() == "used_/run/lock") { + ASSERT_EQ(p.value(), 4000); + ASSERT_EQ(p.max(), 5116000); + } else if (p.name() == "used_/sys/fs/cgroup") { + ASSERT_EQ(p.value(), 0); + ASSERT_EQ(p.max(), 6072708000); + } else if (p.name() == "used_/run/user/1001") { + ASSERT_EQ(p.value(), 100000); + ASSERT_EQ(p.max(), 1214440000); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} + +TEST_F(drive_size_test, test_fs_filter_percent) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "1", "critical" : "5", "unit": "%", + "filter-type": "^hrfsother$"})"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, "WARNING: /run Total: 1G Used: 1.38% Free: 98.62%"); + ASSERT_EQ(perfs.size(), 6); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "%"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 1); + ASSERT_EQ(p.critical(), 5); + if (p.name() == "used_/dev") { + ASSERT_EQ(p.value(), 0); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run") { + ASSERT_NEAR(p.value(), 1.38, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/dev/shm") { + ASSERT_NEAR(p.value(), 0, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/lock") { + ASSERT_NEAR(p.value(), 0.08, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/sys/fs/cgroup") { + ASSERT_EQ(p.value(), 0); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/user/1001") { + ASSERT_NEAR(p.value(), 0, 0.01); + ASSERT_EQ(p.max(), 100); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} + +TEST_F(drive_size_test, test_fs_filter2) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "1000000", "critical" : "20000000", "unit": "b", + "filter-type": "^(hrfsfat$|hrfsfat32)$"})"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, "CRITICAL: /data Total: 5G Used: 2G Free: 2G"); + ASSERT_EQ(perfs.size(), 2); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "B"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 1000000); + ASSERT_EQ(p.critical(), 20000000); + if (p.name() == "used_/boot/efi") { + ASSERT_EQ(p.value(), 24000); + ASSERT_EQ(p.max(), 524248000); + } else if (p.name() == "used_/data") { + ASSERT_EQ(p.value(), 3072708000); + ASSERT_EQ(p.max(), 6072708000); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} + +TEST_F(drive_size_test, test_fs_filter_percent_2) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "1", "critical" : "5", "unit": "%", + "filter-type": "^hrfsother$", "filter-fs": "^tmp.*$"})"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, "WARNING: /run Total: 1G Used: 1.38% Free: 98.62%"); + ASSERT_EQ(perfs.size(), 5); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "%"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 1); + ASSERT_EQ(p.critical(), 5); + if (p.name() == "used_/run") { + ASSERT_NEAR(p.value(), 1.38, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/dev/shm") { + ASSERT_NEAR(p.value(), 0, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/lock") { + ASSERT_NEAR(p.value(), 0.08, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/sys/fs/cgroup") { + ASSERT_EQ(p.value(), 0); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/user/1001") { + ASSERT_NEAR(p.value(), 0, 0.01); + ASSERT_EQ(p.max(), 100); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} + +TEST_F(drive_size_test, test_fs_filter_percent_3) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "1", "critical" : "5", "unit": "%", + "filter-type": "^hrfsother$", "filter-fs": "tmpfs", "filter-mountpoint":"^/run/.*$" })"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, "OK: All storages are ok"); + ASSERT_EQ(perfs.size(), 2); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "%"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 1); + ASSERT_EQ(p.critical(), 5); + if (p.name() == "used_/run") { + ASSERT_NEAR(p.value(), 1.38, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/lock") { + ASSERT_NEAR(p.value(), 0.08, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/user/1001") { + ASSERT_NEAR(p.value(), 0, 0.01); + ASSERT_EQ(p.max(), 100); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} + +TEST_F(drive_size_test, test_fs_filter_percent_4) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "1", "critical" : "5", "unit": "%", + "filter-type": "^hrfsother$", "filter-fs": "tmpfs", "filter-mountpoint":"^/run.*$", "exclude-mountpoint": ".*lock.*" })"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + { + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, "WARNING: /run Total: 1G Used: 1.38% Free: 98.62%"); + ASSERT_EQ(perfs.size(), 2); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "%"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 1); + ASSERT_EQ(p.critical(), 5); + if (p.name() == "used_/run") { + ASSERT_NEAR(p.value(), 1.38, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/run/user/1001") { + ASSERT_NEAR(p.value(), 0, 0.01); + ASSERT_EQ(p.max(), 100); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } + } + // recheck to validate filter cache + std::string output_save = output; + std::list perfs_save = perfs; + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, output_save); + ASSERT_EQ(perfs, perfs_save); +} + +TEST_F(drive_size_test, test_fs_filter_percent_5) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "30", "critical" : "50", "unit": "%", + "exclude-fs": "tmpfs", "exclude-mountpoint":"/dev" })"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, + "WARNING: / Total: 322G Used: 39.54% Free: 60.46% CRITICAL: /data " + "Total: 5G Used: 50.60% Free: 49.40%"); + ASSERT_EQ(perfs.size(), 3); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "%"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 30); + ASSERT_EQ(p.critical(), 50); + if (p.name() == "used_/") { + ASSERT_NEAR(p.value(), 39.54, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/data") { + ASSERT_NEAR(p.value(), 50.60, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "used_/boot/efi") { + ASSERT_NEAR(p.value(), 0.0045, 0.0001); + ASSERT_EQ(p.max(), 100); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} + +TEST_F(drive_size_test, test_fs_filter_free_percent) { + using namespace com::centreon::common::literals; + rapidjson::Document check_args = + R"({ "warning" : "70", "critical" : "50", "unit": "%", "free": true, + "exclude-fs": "tmpfs", "exclude-mountpoint":"/dev" })"_json; + + absl::Mutex wait_m; + std::list perfs; + std::string output; + + auto is_complete = [&]() { return !perfs.empty(); }; + + auto debug_logger = spdlog::default_logger(); + + auto checker = std::make_shared( + g_io_context, spdlog::default_logger(), std::chrono::system_clock::now(), + std::chrono::seconds(1), "serv"s, "cmd_name"s, "cmd_line"s, check_args, + nullptr, + [&]([[maybe_unused]] const std::shared_ptr& caller, + [[maybe_unused]] int status, + [[maybe_unused]] const std::list& + perfdata, + [[maybe_unused]] const std::list& outputs) { + absl::MutexLock lck(&wait_m); + perfs = perfdata; + output = outputs.front(); + }); + + checker->start_check(std::chrono::seconds(1)); + + absl::MutexLock lck(&wait_m); + wait_m.Await(absl::Condition(&is_complete)); + + ASSERT_EQ(output, + "WARNING: / Total: 322G Used: 39.54% Free: 60.46% CRITICAL: /data " + "Total: 5G Used: 50.60% Free: 49.40%"); + ASSERT_EQ(perfs.size(), 3); + + for (const auto& p : perfs) { + ASSERT_EQ(p.unit(), "%"); + ASSERT_EQ(p.min(), 0); + ASSERT_EQ(p.warning_low(), 0); + ASSERT_EQ(p.critical_low(), 0); + ASSERT_EQ(p.warning(), 70); + ASSERT_EQ(p.critical(), 50); + if (p.name() == "free_/") { + ASSERT_NEAR(p.value(), 60.46, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "free_/data") { + ASSERT_NEAR(p.value(), 49.40, 0.01); + ASSERT_EQ(p.max(), 100); + } else if (p.name() == "free_/boot/efi") { + ASSERT_NEAR(p.value(), 99.99, 0.01); + ASSERT_EQ(p.max(), 100); + } else { + FAIL() << "Unexpected perfdata name: " << p.name(); + } + } +} diff --git a/broker/victoria_metrics/src/factory.cc b/broker/victoria_metrics/src/factory.cc index 492195cdd04..0d98747effe 100644 --- a/broker/victoria_metrics/src/factory.cc +++ b/broker/victoria_metrics/src/factory.cc @@ -28,7 +28,7 @@ using namespace nlohmann::literals; const json factory::default_extra_status_column = R"([ {"name" : "host", "is_tag" : "true", "value" : "$HOST$", "type":"string"}, - {"name" : "serv", "is_tag" : "true", "value" : "$SERVICE$", "type":"string"}, + {"name" : "serv"s, "is_tag" : "true", "value" : "$SERVICE$", "type":"string"}, {"name" : "host_grp", "is_tag" : "true", "value" : "$HOSTGROUP$", "type":"string"}, {"name" : "serv_grp", "is_tag" : "true", "value" : "$SERVICE_GROUP$", "type":"string"}, {"name" : "host_tag_cat", "is_tag" : "true", "value" : "$HOST_TAG_CAT_NAME$", "type":"string"}, @@ -38,7 +38,7 @@ const json factory::default_extra_status_column = R"([ const json factory::default_extra_metric_column = R"([ {"name" : "host", "is_tag" : "true", "value" : "$HOST$", "type":"string"}, - {"name" : "serv", "is_tag" : "true", "value" : "$SERVICE$", "type":"string"}, + {"name" : "serv"s, "is_tag" : "true", "value" : "$SERVICE$", "type":"string"}, {"name" : "min", "is_tag" : "true", "value" : "$MIN$", "type":"number"}, {"name" : "max", "is_tag" : "true", "value" : "$MAX$", "type":"number"}, {"name" : "host_grp", "is_tag" : "true", "value" : "$HOSTGROUP$", "type":"string"}, @@ -54,8 +54,7 @@ factory::factory() io::endpoint* factory::new_endpoint( config::endpoint& cfg, - const std::map& global_params - [[maybe_unused]], + const std::map& global_params [[maybe_unused]], bool& is_acceptor, std::shared_ptr) const { is_acceptor = false; diff --git a/broker/victoria_metrics/test/request_test.cc b/broker/victoria_metrics/test/request_test.cc index 0ceaf56bfab..87444fbe7ad 100644 --- a/broker/victoria_metrics/test/request_test.cc +++ b/broker/victoria_metrics/test/request_test.cc @@ -254,7 +254,7 @@ TEST_F(victoria_request_test, request_body_test_victoria_extra_column) { json column = R"([ {"name" : "host", "is_tag" : "true", "value" : "$HOST$", "type":"string"}, - {"name" : "serv", "is_tag" : "true", "value" : "$SERVICE$", "type":"string"}, + {"name" : "serv"s, "is_tag" : "true", "value" : "$SERVICE$", "type":"string"}, {"name" : "host_grp", "is_tag" : "true", "value" : "$HOSTGROUP$", "type":"string"}, {"name" : "serv_grp", "is_tag" : "true", "value" : "$SERVICE_GROUP$", "type":"string"}, {"name" : "host_tag_cat_id", "is_tag" : "true", "value" : "$HOST_TAG_CAT_ID$", "type":"string"}, diff --git a/common/inc/com/centreon/common/perfdata.hh b/common/inc/com/centreon/common/perfdata.hh index 8ad6e3905a7..d60f3dc2588 100644 --- a/common/inc/com/centreon/common/perfdata.hh +++ b/common/inc/com/centreon/common/perfdata.hh @@ -76,11 +76,11 @@ class perfdata { void warning_mode(bool val) { _warning_mode = val; } }; -} // namespace com::centreon::common - bool operator==(com::centreon::common::perfdata const& left, com::centreon::common::perfdata const& right); bool operator!=(com::centreon::common::perfdata const& left, com::centreon::common::perfdata const& right); +} // namespace com::centreon::common + #endif diff --git a/common/src/perfdata.cc b/common/src/perfdata.cc index 80945b75950..d44f41d3161 100644 --- a/common/src/perfdata.cc +++ b/common/src/perfdata.cc @@ -54,6 +54,7 @@ static inline bool float_equal(float a, float b) { fabs(a - b) <= 0.01 * fabs(a)); } +namespace com::centreon::common { /** * Compare two perfdata objects. * @@ -87,6 +88,9 @@ bool operator==(perfdata const& left, perfdata const& right) { bool operator!=(perfdata const& left, perfdata const& right) { return !(left == right); } + +} // namespace com::centreon::common + /** * @brief in case of db insertions we need to ensure that name can be stored in * table With it, you can reduce name size