From b3557f3623c6dbf0fa68bbd1cebd9f99e89a2734 Mon Sep 17 00:00:00 2001 From: jean-christophe81 <98889244+jean-christophe81@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:15:05 +0100 Subject: [PATCH] add flapping and percent_state_change (#1926) --- broker/unified_sql/src/stream.cc | 4 ++- broker/unified_sql/src/stream_sql.cc | 25 ++++++++++----- resources/centreon_storage.sql | 2 ++ tests/broker-engine/output-tables.robot | 41 +++++++++++++++++++++++++ tests/resources/Common.py | 35 +++++++++++++++++++++ 5 files changed, 98 insertions(+), 9 deletions(-) diff --git a/broker/unified_sql/src/stream.cc b/broker/unified_sql/src/stream.cc index eaaa899f879..9555253f078 100644 --- a/broker/unified_sql/src/stream.cc +++ b/broker/unified_sql/src/stream.cc @@ -1396,7 +1396,9 @@ void stream::_init_statements() { "last_check_type=?," // 8: check_type "last_check=?," // 9: last_check "output=? " // 10: output - "WHERE id=? AND parent_id=?"); // 11, 12: service_id and host_id + "flapping=?," // 11: is_flapping + "percent_state_change=? " // 12: percent_state_change + "WHERE id=? AND parent_id=?"); // 13, 14: service_id and host_id const std::string host_exe_dep_query( "INSERT INTO hosts_hosts_dependencies (dependent_host_id, host_id, " "dependency_period, execution_failure_options, inherits_parent) " diff --git a/broker/unified_sql/src/stream_sql.cc b/broker/unified_sql/src/stream_sql.cc index adf4cbe0269..1d7817fd9f1 100644 --- a/broker/unified_sql/src/stream_sql.cc +++ b/broker/unified_sql/src/stream_sql.cc @@ -3971,8 +3971,8 @@ void stream::_process_pb_service(const std::shared_ptr& d) { "severity_id,name,parent_name,notes_url,notes,action_url," "notifications_enabled,passive_checks_enabled,active_" "checks_" - "enabled,enabled,icon_id) " - "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,?)"); + "enabled,enabled,icon_id, flapping, percent_state_change) " + "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)"); _resources_service_update = _mysql.prepare_query( "UPDATE resources SET " "type=?,internal_id=?,status=?,status_ordered=?,last_" @@ -3984,7 +3984,7 @@ void stream::_process_pb_service(const std::shared_ptr& d) { "," "notes=?,action_url=?,notifications_enabled=?," "passive_checks_enabled=?,active_checks_enabled=?,icon_id=?" - "," + ", flapping=?, percent_state_change=?," "enabled=1 WHERE resource_id=?"); if (!_resources_disable.prepared()) { _resources_disable = _mysql.prepare_query( @@ -4091,6 +4091,8 @@ uint64_t stream::_process_pb_service_in_resources(const Service& s, _resources_service_insert.bind_value_as_bool(20, s.passive_checks()); _resources_service_insert.bind_value_as_bool(21, s.active_checks()); _resources_service_insert.bind_value_as_u64(22, s.icon_id()); + _resources_service_insert.bind_value_as_bool(23, s.flapping()); + _resources_service_insert.bind_value_as_f64(24, s.percent_state_change()); std::promise p; std::future future = p.get_future(); @@ -4184,7 +4186,9 @@ uint64_t stream::_process_pb_service_in_resources(const Service& s, _resources_service_update.bind_value_as_bool(18, s.passive_checks()); _resources_service_update.bind_value_as_bool(19, s.active_checks()); _resources_service_update.bind_value_as_u64(20, s.icon_id()); - _resources_service_update.bind_value_as_u64(21, res_id); + _resources_service_update.bind_value_as_bool(21, s.flapping()); + _resources_service_update.bind_value_as_f64(22, s.percent_state_change()); + _resources_service_update.bind_value_as_u64(23, res_id); _mysql.run_statement(_resources_service_update, database::mysql_error::store_service, conn); @@ -4777,8 +4781,10 @@ void stream::_process_pb_service_status(const std::shared_ptr& d) { b->set_value_as_u64(9, sscr.last_check()); b->set_value_as_str( 10, fmt::string_view(sscr.output().c_str(), output_size)); - b->set_value_as_u64(11, sscr.service_id()); - b->set_value_as_u64(12, sscr.host_id()); + b->set_value_as_bool(11, sscr.flapping()); + b->set_value_as_f64(12, sscr.percent_state_change()); + b->set_value_as_u64(13, sscr.service_id()); + b->set_value_as_u64(14, sscr.host_id()); b->next_row(); SPDLOG_LOGGER_TRACE( _logger_sql, "{} waiting updates for service status in resources", @@ -4805,8 +4811,11 @@ void stream::_process_pb_service_status(const std::shared_ptr& d) { 9, sscr.last_check(), mapping::entry::invalid_on_zero); _sscr_resources_update->bind_value_as_str( 10, fmt::string_view(sscr.output().c_str(), output_size)); - _sscr_resources_update->bind_value_as_u64(11, sscr.service_id()); - _sscr_resources_update->bind_value_as_u64(12, sscr.host_id()); + _sscr_resources_update->bind_value_as_bool(11, sscr.flapping()); + _sscr_resources_update->bind_value_as_f64(12, + sscr.percent_state_change()); + _sscr_resources_update->bind_value_as_u64(13, sscr.service_id()); + _sscr_resources_update->bind_value_as_u64(14, sscr.host_id()); _mysql.run_statement(*_sscr_resources_update, database::mysql_error::store_service_status, conn); diff --git a/resources/centreon_storage.sql b/resources/centreon_storage.sql index 5291012a92d..9d4d886a354 100644 --- a/resources/centreon_storage.sql +++ b/resources/centreon_storage.sql @@ -1106,6 +1106,8 @@ CREATE TABLE `resources` ( `last_check` bigint(20) unsigned DEFAULT NULL COMMENT 'the last check timestamp', `output` text DEFAULT NULL, `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '0=false, 1=true', + `flapping` tinyint(1) DEFAULT NULL, + `percent_state_change` double DEFAULT NULL, PRIMARY KEY (`resource_id`), UNIQUE KEY `resources_id_parent_id_type_uindex` (`id`,`parent_id`,`type`), KEY `resources_severities_severity_id_fk` (`severity_id`), diff --git a/tests/broker-engine/output-tables.robot b/tests/broker-engine/output-tables.robot index b62670b812a..01d4bfd6769 100644 --- a/tests/broker-engine/output-tables.robot +++ b/tests/broker-engine/output-tables.robot @@ -272,3 +272,44 @@ BE_DEFAULT_NOTIFCATION_INTERVAL_IS_ZERO_SERVICE_RESOURCE Should Be Equal As Strings ${output} ((0.0, 0.0),) Ctn Stop engine Ctn Kindly Stop Broker + +BE_FLAPPING_SERVICE_RESOURCE + [Documentation] With BBDO 3, flapping detection must be set in services and resources tables. + [Tags] broker engine protobuf MON-154773 + Ctn Config Engine ${1} + Ctn Config Broker central + Ctn Config Broker module + Ctn Config Broker rrd + Ctn Config Broker Sql Output central unified_sql + Ctn Config BBDO3 1 + Ctn Engine Config Set Value 0 enable_flap_detection 1 + Ctn Set Services Passive ${0} service_1 + Ctn Engine Config Set Value In Services 0 service_1 flap_detection_enabled 1 + Ctn Engine Config Set Value In Services 0 service_1 low_flap_threshold 10 + Ctn Engine Config Set Value In Services 0 service_1 high_flap_threshold 20 + Ctn Engine Config Set Value In Services 0 service_1 flap_detection_options all + + Connect To Database pymysql ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort} + Execute SQL String DELETE FROM services + Execute SQL String DELETE FROM resources + Execute SQL String DELETE FROM hosts + + Ctn Clear Retention + + Ctn Start Broker + Ctn Start engine + + # Let's wait for the external command check start + Ctn Wait For Engine To Be Ready ${1} + + # generate flapping + FOR ${index} IN RANGE 21 + Ctn Process Service Result Hard host_1 service_1 2 flapping + Ctn Process Service Check Result host_1 service_1 0 flapping + Sleep 1s + END + + ${result} Ctn Check Service Flapping host_1 service_1 30 5 50 + Should Be True ${result} The service or resource (host_1,service_1) is not flapping as expected + + [Teardown] Ctn Stop Engine Broker And Save Logs diff --git a/tests/resources/Common.py b/tests/resources/Common.py index b636cb2881f..c33595f50ef 100644 --- a/tests/resources/Common.py +++ b/tests/resources/Common.py @@ -1940,3 +1940,38 @@ def ctn_compare_string_with_file(string_to_compare:str, file_path:str): return False return True + +def ctn_check_service_flapping(host: str, serv: str, timeout: int, precision: float, expected: int): + """ + Check if performance data are near as expected. + host (str): The hostname of the service to check. + serv (str): The service name to check. + timeout (int): The timeout value for the check. + precision (float): The precision required for the performance data comparison. + expected (int): expected flapping value. + """ + limit = time.time() + timeout + + s_query = f"""SELECT s.flapping, s.percent_state_change FROM services s JOIN hosts h on s.host_id = h.host_id WHERE h.name='{host}' AND description='{serv}'""" + r_query = f"""SELECT flapping, percent_state_change FROM resources WHERE parent_name='{host}' AND name='{serv}'""" + + + while time.time() < limit: + connection = pymysql.connect(host=DB_HOST, + user=DB_USER, + password=DB_PASS, + database=DB_NAME_STORAGE, + charset='utf8mb4', + cursorclass=pymysql.cursors.DictCursor) + with connection: + with connection.cursor() as cursor: + cursor.execute(s_query) + result = cursor.fetchall() + if len(result) == 1 and result[0]['flapping'] == 1 and abs(result[0]['percent_state_change'] - expected) < precision: + cursor.execute(r_query) + result = cursor.fetchall() + if len(result) == 1 and result[0]['flapping'] == 1 and abs(result[0]['percent_state_change'] - expected) < precision: + return True + time.sleep(1) + logger.console(f"unexpected result: {result}") + return False