From 1debbb461f347323520b9681231bb8b016edcb0f Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Thu, 16 Dec 2021 09:55:44 +0100
Subject: [PATCH 01/16] Refacto streamconnector BSM v2
---
.../bsm/bsm_connector-apiv2.lua | 300 ++++++++++++++++++
1 file changed, 300 insertions(+)
create mode 100644 centreon-certified/bsm/bsm_connector-apiv2.lua
diff --git a/centreon-certified/bsm/bsm_connector-apiv2.lua b/centreon-certified/bsm/bsm_connector-apiv2.lua
new file mode 100644
index 00000000..358d6621
--- /dev/null
+++ b/centreon-certified/bsm/bsm_connector-apiv2.lua
@@ -0,0 +1,300 @@
+--
+-- Copyright © 2021 Centreon
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the Licensself.sc_event.event.
+-- You may obtain a copy of the License at
+--
+-- http://www.apachself.sc_event.event.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 Licensself.sc_event.event.
+--
+-- For more information : contact@centreon.com
+--
+-- To work you need to provide to this script a Broker stream connector output configuration
+-- with the following informations:
+--
+-- source_ci (string): Name of the transmiter, usually Centreon server name
+-- http_server_url (string): the full HTTP URL. Default: https://my.bsm.server:30005/bsmc/rest/events/ws-centreon/.
+-- http_proxy_string (string): the full proxy URL if needed to reach the BSM server. Default: empty.
+-- log_path (string): the log file to use
+-- log_level (number): the log level (0, 1, 2, 3) where 3 is the maximum level. 0 logs almost nothing. 1 logs only the beginning of the script and errors. 2 logs a reasonable amount of verbosself.sc_event.event. 3 logs almost everything possible, to be used only for debug. Recommended value in production: 1.
+-- max_buffer_size (number): how many events to store before sending them to the server.
+-- max_buffer_age (number): flush the events when the specified time (in second) is reached (even if max_size is not reached).
+
+-- Libraries
+local curl = require "cURL"
+require("LuaXML")
+
+-- Centreon lua core libraries
+local sc_common = require("centreon-stream-connectors-lib.sc_common")
+local sc_logger = require("centreon-stream-connectors-lib.sc_logger")
+local sc_broker = require("centreon-stream-connectors-lib.sc_broker")
+local sc_event = require("centreon-stream-connectors-lib.sc_event")
+local sc_params = require("centreon-stream-connectors-lib.sc_params")
+local sc_macros = require("centreon-stream-connectors-lib.sc_macros")
+local sc_flush = require("centreon-stream-connectors-lib.sc_flush")
+
+-- workaround https://github.com/centreon/centreon-broker/issues/201
+local previous_event = ""
+
+--------------------------------------------------------------------------------
+-- EventQueue class
+--------------------------------------------------------------------------------
+
+local EventQueue = {}
+EventQueue.__index = EventQueue
+
+--------------------------------------------------------------------------------
+-- Constructor
+-- @param conf The table given by the init() function and returned from the GUI
+-- @return the new EventQueue
+--------------------------------------------------------------------------------
+
+function EventQueue.new(params)
+ local self = {}
+ self.fail = false
+
+ local mandatory_parameters = {
+ "http_server_url"
+ }
+
+ -- set up log configuration
+ local logfile = params.logfile or "/var/log/centreon-broker/bsm_connector-apiv2.log"
+ local log_level = params.log_level or 1
+
+ -- initiate mandatory objects
+ self.sc_logger = sc_logger.new(logfile, log_level)
+ self.sc_common = sc_common.new(self.sc_logger)
+ self.sc_broker = sc_broker.new(self.sc_logger)
+ self.sc_params = sc_params.new(self.sc_common, self.sc_logger)
+
+ -- checking mandatory parameters and setting a fail flag
+ if not self.sc_params:is_mandatory_config_set(mandatory_parameters, params) then
+ self.fail = true
+ end
+
+ -- overriding default parameters for this stream connector if the default values doesn't suit the basic needs
+ self.sc_params.params.accepted_categories = params.accepted_categories or "neb"
+ self.sc_params.params.accepted_elements = params.accepted_elements or "host_status,service_status"
+ self.sc_params.params.source_ci = params.source_ci or "Centreon"
+ self.sc_params.params.max_output_length = params.max_output_length or 1024
+
+ -- apply users params and check syntax of standard ones
+ self.sc_params:param_override(params)
+ self.sc_params:check_params()
+
+ self.sc_macros = sc_macros.new(self.sc_params.params, self.sc_logger)
+ self.format_template = self.sc_params:load_event_format_file(true)
+ self.sc_params:build_accepted_elements_info()
+ self.sc_flush = sc_flush.new(self.sc_params.params, self.sc_logger)
+
+ local categories = self.sc_params.params.bbdo.categories
+ local elements = self.sc_params.params.bbdo.elements
+
+ self.format_event = {
+ [categories.neb.id] = {
+ [elements.host_status.id] = function () return self:format_event_host() end,
+ [elements.service_status.id] = function () return self:format_event_service() end
+ },
+ [categories.bam.id] = {}
+ }
+ self.send_data_method = {
+ [1] = function (data, element) return self:send_data(data, element) end
+ }
+
+ -- return EventQueue object
+ setmetatable(self, { __index = EventQueue })
+ return self
+end
+
+-- Format XML file with host infoamtion
+function EventQueue:format_event_host()
+ local xml_host_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id) , '0') .. ""
+ local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.service.action_url, 'no action url for this host')
+ local xml_notes = "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.cache.service.notes, 'OS not set') .. ""
+
+ self.sc_event.event.formated_event = {
+ ""
+ .. "" .. hostname .. ""
+ .. xml_host_severity .. xml_notes
+ .. "" .. xml_url .. ""
+ .. "" .. ifnil_or_empty(self.source_ci, 'Centreon') .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.host_id, '0') .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, '0') .. ""
+ .. ""
+ }
+end
+
+-- Format XML file with service infoamtion
+function EventQueue:format_event_service()
+ local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.service.notes_url, 'no notes url for this service')
+ local xml_service_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id, self.sc_event.event.service_id) , '0') .. ""
+
+ self.sc_event.event.formated_event = {
+ ""
+ .. "" .. hostname .. ""
+ .. "" .. service_description .. ""
+ .. "" ..self.sc_event.event.state .. ""
+ .. "" ..self.sc_event.event.last_update .. ""
+ .. ""
+ .. xml_service_severity
+ .. "" .. xml_url .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.host_id, '0') .. ""
+ .."" .. ifnil_or_empty(self.sc_event.event.service_id, '0') .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, '0') .. ""
+ ..""
+ }
+end
+
+--------------------------------------------------------------------------------
+-- EventQueue:add method
+-- @param e An event
+--------------------------------------------------------------------------------
+
+function EventQueue:add()
+ -- store event in self.events lists
+ local category = self.sc_event.event.category
+ local element = self.sc_event.event.element
+
+ self.sc_logger:debug("[EventQueue:add]: add event in queue category: " .. tostring(self.sc_params.params.reverse_category_mapping[category])
+ .. " element: " .. tostring(self.sc_params.params.reverse_element_mapping[category][element]))
+
+ self.sc_logger:debug("[EventQueue:add]: queue size before adding event: " .. tostring(#self.sc_flush.queues[category][element].events))
+ self.sc_flush.queues[category][element].events[#self.sc_flush.queues[category][element].events + 1] = self.sc_event.event.formated_event
+
+ self.sc_logger:info("[EventQueue:add]: queue size is now: " .. tostring(#self.sc_flush.queues[category][element].events)
+ .. "max is: " .. tostring(self.sc_params.params.max_buffer_size))
+end
+
+function EventQueue:send_data(data, element)
+ self.sc_logger:debug("[EventQueue:send_data]: Starting to send data")
+
+ -- write payload in the logfile for test purpose
+ if self.sc_params.params.send_data_test == 1 then
+ for _, xml_str in ipairs(data) do
+ http_post_data = http_post_data .. tostring(xml.eval(xml_str))
+ end
+
+ self.sc_logger:info(http_post_data)
+ return true
+ end
+
+ local http_post_data = ""
+
+ for _, xml_str in ipairs(data) do
+ http_post_data = http_post_data .. tostring(xml.eval(xml_str))
+ end
+
+ self.sc_logger:info("[EventQueue:send_data]: Going to send the following json " .. tostring(http_post_data))
+ self.sc_logger:info("[EventQueue:send_data]: BSM Http Server URL is: \"" .. tostring(self.sc_params.params.http_server_url .. "\""))
+
+ local http_response_body = ""
+ local http_request = curl.easy()
+ :setopt_url(self.sc_params.params.http_server_url)
+ :setopt_writefunction(
+ function (response)
+ http_response_body = http_response_body .. tostring(response)
+ end
+ )
+ :setopt(curl.OPT_TIMEOUT, self.sc_params.params.connection_timeout)
+ :setopt(curl.OPT_SSL_VERIFYPEER, self.sc_params.params.allow_insecure_connection)
+ :setopt(
+ curl.OPT_HTTPHEADER,
+ {
+ "Content-Type: text/xml",
+ "content-length: " .. string.len(http_post_data)
+ }
+ )
+
+ -- set proxy address configuration
+ if (self.sc_params.params.proxy_address ~= '') then
+ if (self.sc_params.params.proxy_port ~= '') then
+ http_request:setopt(curl.OPT_PROXY, self.sc_params.params.proxy_address .. ':' .. self.sc_params.params.proxy_port)
+ else
+ self.sc_logger:error("[EventQueue:send_data]: proxy_port parameter is not set but proxy_address is used")
+ end
+ end
+
+ -- set proxy user configuration
+ if (self.sc_params.params.proxy_username ~= '') then
+ if (self.sc_params.params.proxy_password ~= '') then
+ http_request:setopt(curl.OPT_PROXYUSERPWD, self.sc_params.params.proxy_username .. ':' .. self.sc_params.params.proxy_password)
+ else
+ self.sc_logger:error("[EventQueue:send_data]: proxy_password parameter is not set but proxy_username is used")
+ end
+ end
+
+ -- adding the HTTP POST data
+ http_request:setopt_postfields(http_post_data)
+ -- performing the HTTP request
+ http_request:perform()
+ -- collecting results
+ http_response_code = http_request:getinfo(curl.INFO_RESPONSE_CODE)
+ http_request:close()
+
+ -- Handling the return code
+ local retval = false
+ if http_response_code == 202 or http_response_code == 200 then
+ self.sc_logger:info("[EventQueue:send_data]: HTTP POST request successful: return code is " .. tostring(http_response_code))
+ retval = true
+ else
+ self.sc_logger:error("[EventQueue:send_data]: HTTP POST request FAILED, return code is " .. tostring(http_response_code) .. ". Message is: " .. tostring(http_response_body))
+ end
+ return retval
+end
+
+--------------------------------------------------------------------------------
+-- Required functions for Broker StreamConnector
+--------------------------------------------------------------------------------
+
+local queue
+
+-- Fonction init()
+function init(conf)
+ queue = EventQueue.sc_event.event.new(conf)
+end
+
+-- Fonction write()
+function write(event)
+ -- First, flush all queues if needed (too old or size too big)
+ Queue.sc_event.event.sc_flush:flush_all_queues(Queue.sc_event.event.send_data_method[1])
+
+ -- skip event if a mandatory parameter is missing
+ if Queue.sc_event.event.fail then
+ Queue.sc_event.event.sc_logger:error("Skipping event because a mandatory parameter is not set")
+ return true
+ end
+
+ -- initiate event object
+ Queue.sc_event.event.sc_event = sc_event.new(event, Queue.sc_event.event.sc_params.params, Queue.sc_event.event.sc_common, Queue.sc_event.event.sc_logger, Queue.sc_event.event.sc_broker)
+
+ -- drop event if wrong category
+ if not Queue.sc_event.event.sc_event:is_valid_category() then
+ Queue.sc_event.event.sc_logger:debug("dropping event because category is not valid. Event category is: "
+ .. tostring(Queue.sc_event.event.sc_params.params.reverse_category_mapping[Queue.sc_event.event.sc_event.event.category]))
+ return true
+ end
+
+ -- drop event if wrong element
+ if not Queue.sc_event.event.sc_event:is_valid_element() then
+ Queue.sc_event.event.sc_logger:debug("dropping event because element is not valid. Event element is: "
+ .. tostring(Queue.sc_event.event.sc_params.params.reverse_element_mapping[Queue.sc_event.event.sc_event.event.category][Queue.sc_event.event.sc_event.event.element]))
+ return true
+ end
+
+ -- drop event if it is not validated
+ if Queue.sc_event.event.sc_event:is_valid_event() then
+ queue:format_accepted_event()
+ else
+ return true
+ end
+
+ -- Since we've added an event to a specific queue, flush it if queue is full
+ Queue.sc_event.event.sc_flush:flush_queue(Queue.sc_event.event.send_data_method[1], Queue.sc_event.event.sc_event.event.category, Queue.sc_event.event.sc_event.event.element)
+ return true
+end
From 30cb05a936390d35449b8eb85c4657d27d378f8b Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Mon, 20 Dec 2021 10:39:04 +0100
Subject: [PATCH 02/16] Review code after firts recommandations
---
.../bsm/bsm_connector-apiv2.lua | 55 ++++++++++---------
1 file changed, 28 insertions(+), 27 deletions(-)
diff --git a/centreon-certified/bsm/bsm_connector-apiv2.lua b/centreon-certified/bsm/bsm_connector-apiv2.lua
index 358d6621..192f4a17 100644
--- a/centreon-certified/bsm/bsm_connector-apiv2.lua
+++ b/centreon-certified/bsm/bsm_connector-apiv2.lua
@@ -114,26 +114,27 @@ end
-- Format XML file with host infoamtion
function EventQueue:format_event_host()
- local xml_host_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id) , '0') .. ""
- local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.service.action_url, 'no action url for this host')
- local xml_notes = "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.cache.service.notes, 'OS not set') .. ""
+ local xml_host_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id) , 0) .. ""
+ local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.action_url, 'no action url for this host')
+ local xml_notes = "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.notes, 'no notes found on host') .. ""
self.sc_event.event.formated_event = {
""
.. "" .. hostname .. ""
- .. xml_host_severity .. xml_notes
+ .. "" .. xml_host_severity .. ""
+ .. "" .. xml_notes .. ""
.. "" .. xml_url .. ""
.. "" .. ifnil_or_empty(self.source_ci, 'Centreon') .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.host_id, '0') .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, '0') .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
.. ""
}
end
-- Format XML file with service infoamtion
function EventQueue:format_event_service()
- local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.service.notes_url, 'no notes url for this service')
- local xml_service_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id, self.sc_event.event.service_id) , '0') .. ""
+ local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.notes_url, 'no url for this service')
+ local xml_service_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id, self.sc_event.event.service_id) , 0) .. ""
self.sc_event.event.formated_event = {
""
@@ -141,13 +142,13 @@ function EventQueue:format_event_service()
.. "" .. service_description .. ""
.. "" ..self.sc_event.event.state .. ""
.. "" ..self.sc_event.event.last_update .. ""
- .. ""
- .. xml_service_severity
+ .. ""
+ .. "" .. xml_service_severity .. ""
.. "" .. xml_url .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.host_id, '0') .. ""
- .."" .. ifnil_or_empty(self.sc_event.event.service_id, '0') .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, '0') .. ""
- ..""
+ .. "" .. ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.service_id, 0) .. ""
+ .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
+ .. ""
}
end
@@ -256,45 +257,45 @@ local queue
-- Fonction init()
function init(conf)
- queue = EventQueue.sc_event.event.new(conf)
+ queue = EventQueue.new(conf)
end
-- Fonction write()
function write(event)
-- First, flush all queues if needed (too old or size too big)
- Queue.sc_event.event.sc_flush:flush_all_queues(Queue.sc_event.event.send_data_method[1])
+ queue.sc_flush:flush_all_queues(queue.send_data_method[1])
-- skip event if a mandatory parameter is missing
- if Queue.sc_event.event.fail then
- Queue.sc_event.event.sc_logger:error("Skipping event because a mandatory parameter is not set")
+ if queue.event.fail then
+ queue.event.sc_logger:error("Skipping event because a mandatory parameter is not set")
return true
end
-- initiate event object
- Queue.sc_event.event.sc_event = sc_event.new(event, Queue.sc_event.event.sc_params.params, Queue.sc_event.event.sc_common, Queue.sc_event.event.sc_logger, Queue.sc_event.event.sc_broker)
+ queue.event.sc_event = sc_event.new(event, queue.event.sc_params.params, queue.event.sc_common, queue.event.sc_logger, queue.event.sc_broker)
-- drop event if wrong category
- if not Queue.sc_event.event.sc_event:is_valid_category() then
- Queue.sc_event.event.sc_logger:debug("dropping event because category is not valid. Event category is: "
- .. tostring(Queue.sc_event.event.sc_params.params.reverse_category_mapping[Queue.sc_event.event.sc_event.event.category]))
+ if not queue.event.sc_event:is_valid_category() then
+ queue.event.sc_logger:debug("dropping event because category is not valid. Event category is: "
+ .. tostring(queue.event.sc_params.params.reverse_category_mapping[queue.event.sc_event.event.category]))
return true
end
-- drop event if wrong element
- if not Queue.sc_event.event.sc_event:is_valid_element() then
- Queue.sc_event.event.sc_logger:debug("dropping event because element is not valid. Event element is: "
- .. tostring(Queue.sc_event.event.sc_params.params.reverse_element_mapping[Queue.sc_event.event.sc_event.event.category][Queue.sc_event.event.sc_event.event.element]))
+ if not queue.event.sc_event:is_valid_element() then
+ queue.event.sc_logger:debug("dropping event because element is not valid. Event element is: "
+ .. tostring(queue.event.sc_params.params.reverse_element_mapping[queue.event.sc_event.event.category][queue.event.sc_event.event.element]))
return true
end
-- drop event if it is not validated
- if Queue.sc_event.event.sc_event:is_valid_event() then
+ if queue.event.sc_event:is_valid_event() then
queue:format_accepted_event()
else
return true
end
-- Since we've added an event to a specific queue, flush it if queue is full
- Queue.sc_event.event.sc_flush:flush_queue(Queue.sc_event.event.send_data_method[1], Queue.sc_event.event.sc_event.event.category, Queue.sc_event.event.sc_event.event.element)
+ queue.event.sc_flush:flush_queue(queue.event.send_data_method[1], queue.event.sc_event.event.category, queue.event.sc_event.event.element)
return true
end
From 69cb151f2a0ff591851fc7d955dfb44e9d2b2a8b Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Mon, 20 Dec 2021 10:40:56 +0100
Subject: [PATCH 03/16] Change name file
---
.../bsm/{bsm_connector-apiv2.lua => bsm-events-apiv2.lua} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename centreon-certified/bsm/{bsm_connector-apiv2.lua => bsm-events-apiv2.lua} (100%)
diff --git a/centreon-certified/bsm/bsm_connector-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
similarity index 100%
rename from centreon-certified/bsm/bsm_connector-apiv2.lua
rename to centreon-certified/bsm/bsm-events-apiv2.lua
From 17414d567c9caa10cfb0e94e51405e173b9917a7 Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Mon, 20 Dec 2021 16:20:00 +0100
Subject: [PATCH 04/16] Review function write
---
centreon-certified/bsm/bsm-events-apiv2.lua | 22 ++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index 192f4a17..9bbbb9e0 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -266,36 +266,36 @@ function write(event)
queue.sc_flush:flush_all_queues(queue.send_data_method[1])
-- skip event if a mandatory parameter is missing
- if queue.event.fail then
- queue.event.sc_logger:error("Skipping event because a mandatory parameter is not set")
+ if queue.fail then
+ queue.sc_logger:error("Skipping event because a mandatory parameter is not set")
return true
end
-- initiate event object
- queue.event.sc_event = sc_event.new(event, queue.event.sc_params.params, queue.event.sc_common, queue.event.sc_logger, queue.event.sc_broker)
+ queue.sc_event = sc_event.new(event, queue.sc_params.params, queue.sc_common, queue.sc_logger, queue.sc_broker)
-- drop event if wrong category
- if not queue.event.sc_event:is_valid_category() then
- queue.event.sc_logger:debug("dropping event because category is not valid. Event category is: "
- .. tostring(queue.event.sc_params.params.reverse_category_mapping[queue.event.sc_event.event.category]))
+ if not queue.sc_event:is_valid_category() then
+ queue.sc_logger:debug("dropping event because category is not valid. Event category is: "
+ .. tostring(queue.sc_params.params.reverse_category_mapping[queue.sc_event.event.category]))
return true
end
-- drop event if wrong element
- if not queue.event.sc_event:is_valid_element() then
- queue.event.sc_logger:debug("dropping event because element is not valid. Event element is: "
- .. tostring(queue.event.sc_params.params.reverse_element_mapping[queue.event.sc_event.event.category][queue.event.sc_event.event.element]))
+ if not queue.sc_event:is_valid_element() then
+ queue.sc_logger:debug("dropping event because element is not valid. Event element is: "
+ .. tostring(queue.sc_params.params.reverse_element_mapping[queue.sc_event.event.category][queue.sc_event.event.element]))
return true
end
-- drop event if it is not validated
- if queue.event.sc_event:is_valid_event() then
+ if queue.sc_event:is_valid_event() then
queue:format_accepted_event()
else
return true
end
-- Since we've added an event to a specific queue, flush it if queue is full
- queue.event.sc_flush:flush_queue(queue.event.send_data_method[1], queue.event.sc_event.event.category, queue.event.sc_event.event.element)
+ queue.sc_flush:flush_queue(queue.send_data_method[1], queue.sc_event.event.category, queue.sc_event.event.element)
return true
end
From 5cef5f5862d4c918e8b48f777a64ccf874902de3 Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Tue, 28 Dec 2021 13:47:35 +0100
Subject: [PATCH 05/16] Refacto event treatment for when send_data_test=1
---
centreon-certified/bsm/bsm-events-apiv2.lua | 82 +++++++++++++++------
1 file changed, 58 insertions(+), 24 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index 9bbbb9e0..85732fea 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -112,21 +112,54 @@ function EventQueue.new(params)
return self
end
+--------------------------------------------------------------------------------
+---- EventQueue:format_event method
+---------------------------------------------------------------------------------
+function EventQueue:format_accepted_event()
+ local category = self.sc_event.event.category
+ local element = self.sc_event.event.element
+ local template = self.sc_params.params.format_template[category][element]
+ self.sc_logger:debug("[EventQueue:format_event]: starting format event")
+ self.sc_event.event.formated_event = {}
+
+ if self.format_template and template ~= nil and template ~= "" then
+ for index, value in pairs(template) do
+ self.sc_event.event.formated_event[index] = self.sc_macros:replace_sc_macro(value, self.sc_event.event)
+ end
+ else
+ -- can't format event if stream connector is not handling this kind of event and that it is not handled with a template file
+ if not self.format_event[category][element] then
+ self.sc_logger:error("[format_event]: You are trying to format an event with category: "
+ .. tostring(self.sc_params.params.reverse_category_mapping[category]) .. " and element: "
+ .. tostring(self.sc_params.params.reverse_element_mapping[category][element])
+ .. ". If it is a not a misconfiguration, you should create a format file to handle this kind of element")
+ else
+ self.format_event[category][element]()
+ end
+ end
+
+ self:add()
+ self.sc_logger:debug("[EventQueue:format_event]: event formatting is finished")
+end
+
-- Format XML file with host infoamtion
function EventQueue:format_event_host()
- local xml_host_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id) , 0) .. ""
+ local xml_host_severity = self.sc_broker:get_severity(self.sc_event.event.host_id)
local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.action_url, 'no action url for this host')
- local xml_notes = "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.notes, 'no notes found on host') .. ""
+ local xml_notes = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.notes, 'no notes found on host')
+ if xml_host_severity == false then
+ xml_host_severity = 0
+ end
self.sc_event.event.formated_event = {
""
- .. "" .. hostname .. ""
+ .. "" .. self.sc_event.event.cache.host.name .. ""
.. "" .. xml_host_severity .. ""
- .. "" .. xml_notes .. ""
+ .. "" .. xml_notes .. ""
.. "" .. xml_url .. ""
- .. "" .. ifnil_or_empty(self.source_ci, 'Centreon') .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
+ .. "" .. self.sc_common:ifnil_or_empty(self.source_ci, 'Centreon') .. ""
+ .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
+ .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
.. ""
}
end
@@ -134,20 +167,24 @@ end
-- Format XML file with service infoamtion
function EventQueue:format_event_service()
local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.notes_url, 'no url for this service')
- local xml_service_severity = "" .. self.sc_common:ifnil_or_empty(self.sc_broker:get_severity(self.sc_event.event.host_id, self.sc_event.event.service_id) , 0) .. ""
-
+ local xml_service_severity = self.sc_broker:get_severity(self.sc_event.event.host_id, self.sc_event.event.service_id)
+
+ if xml_service_severity == false then
+ xml_service_severity = 0
+ end
+
self.sc_event.event.formated_event = {
""
- .. "" .. hostname .. ""
- .. "" .. service_description .. ""
+ .. "" .. self.sc_event.event.cache.host.name .. ""
+ .. "" .. self.sc_event.event.cache.service.description .. ""
.. "" ..self.sc_event.event.state .. ""
.. "" ..self.sc_event.event.last_update .. ""
.. ""
- .. "" .. xml_service_severity .. ""
+ .. "" .. xml_service_severity .. ""
.. "" .. xml_url .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.service_id, 0) .. ""
- .. "" .. ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
+ .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
+ .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.service_id, 0) .. ""
+ .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
.. ""
}
end
@@ -177,21 +214,18 @@ function EventQueue:send_data(data, element)
-- write payload in the logfile for test purpose
if self.sc_params.params.send_data_test == 1 then
- for _, xml_str in ipairs(data) do
- http_post_data = http_post_data .. tostring(xml.eval(xml_str))
+ for _, xml_str in pairs(data) do
+ self.sc_logger:info( " value is: " .. xml.str(xml.new(xml_str,0,'<event_data>')))
end
-
- self.sc_logger:info(http_post_data)
- return true
+ return true
end
-
local http_post_data = ""
- for _, xml_str in ipairs(data) do
- http_post_data = http_post_data .. tostring(xml.eval(xml_str))
+ for _, xml_str in pairs(data) do
+ http_post_data = http_post_data .. xml.str(xml.new(xml_str,0,'<event_data>'))
end
- self.sc_logger:info("[EventQueue:send_data]: Going to send the following json " .. tostring(http_post_data))
+ self.sc_logger:info("[EventQueue:send_data]: Going to send the following xml " .. xml.str(http_post_data))
self.sc_logger:info("[EventQueue:send_data]: BSM Http Server URL is: \"" .. tostring(self.sc_params.params.http_server_url .. "\""))
local http_response_body = ""
From ecb51472ca7bae748792f0012cabd19a50a55271 Mon Sep 17 00:00:00 2001
From: psamecentreon
Date: Fri, 14 Jan 2022 19:33:05 +0000
Subject: [PATCH 06/16] Review code with of formated data
---
centreon-certified/bsm/bsm-events-apiv2.lua | 55 ++++++++++++++++-----
1 file changed, 42 insertions(+), 13 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index 85732fea..b2424c95 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -65,8 +65,8 @@ function EventQueue.new(params)
-- set up log configuration
local logfile = params.logfile or "/var/log/centreon-broker/bsm_connector-apiv2.log"
- local log_level = params.log_level or 1
-
+ local log_level = params.log_level or 1
+
-- initiate mandatory objects
self.sc_logger = sc_logger.new(logfile, log_level)
self.sc_common = sc_common.new(self.sc_logger)
@@ -106,7 +106,7 @@ function EventQueue.new(params)
self.send_data_method = {
[1] = function (data, element) return self:send_data(data, element) end
}
-
+
-- return EventQueue object
setmetatable(self, { __index = EventQueue })
return self
@@ -125,7 +125,7 @@ function EventQueue:format_accepted_event()
if self.format_template and template ~= nil and template ~= "" then
for index, value in pairs(template) do
self.sc_event.event.formated_event[index] = self.sc_macros:replace_sc_macro(value, self.sc_event.event)
- end
+ end
else
-- can't format event if stream connector is not handling this kind of event and that it is not handled with a template file
if not self.format_event[category][element] then
@@ -147,11 +147,11 @@ function EventQueue:format_event_host()
local xml_host_severity = self.sc_broker:get_severity(self.sc_event.event.host_id)
local xml_url = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.action_url, 'no action url for this host')
local xml_notes = self.sc_common:ifnil_or_empty(self.sc_event.event.cache.host.notes, 'no notes found on host')
-
+
if xml_host_severity == false then
xml_host_severity = 0
end
- self.sc_event.event.formated_event = {
+ --[[.sc_event.event.formated_event = {
""
.. "" .. self.sc_event.event.cache.host.name .. ""
.. "" .. xml_host_severity .. ""
@@ -161,6 +161,15 @@ function EventQueue:format_event_host()
.. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
.. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
.. ""
+ }--]]
+ self.sc_event.event.formated_event = {
+ hostname = self.sc_event.event.cache.host.name,
+ host_severity = xml_host_severity,
+ host_notes = xml_notes,
+ url = xml_url,
+ source_ci = self.sc_common:ifnil_or_empty(self.source_ci, 'Centreon'),
+ source_host_id = self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0),
+ scheduled_downtime_depth = self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0)
}
end
@@ -173,7 +182,7 @@ function EventQueue:format_event_service()
xml_service_severity = 0
end
- self.sc_event.event.formated_event = {
+ --[[self.sc_event.event.formated_event = {
""
.. "" .. self.sc_event.event.cache.host.name .. ""
.. "" .. self.sc_event.event.cache.service.description .. ""
@@ -186,7 +195,20 @@ function EventQueue:format_event_service()
.. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.service_id, 0) .. ""
.. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
.. ""
- }
+ }--]]
+
+ self.sc_event.event.formated_event = {
+ hostname = self.sc_event.event.cache.host.name,
+ svc_desc = self.sc_event.event.cache.service.description,
+ state = self.sc_event.event.state,
+ last_update = self.sc_event.event.last_update,
+ output = string.match(self.sc_event.event.output, "^(.*)\n"),
+ service_severity = xml_service_severity,
+ url = xml_url,
+ source_host_id = self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0),
+ source_svc_id = self.sc_common:ifnil_or_empty(self.sc_event.event.service_id, 0),
+ scheduled_downtime_depth = self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0)
+ }
end
--------------------------------------------------------------------------------
@@ -211,19 +233,26 @@ end
function EventQueue:send_data(data, element)
self.sc_logger:debug("[EventQueue:send_data]: Starting to send data")
-
+
-- write payload in the logfile for test purpose
if self.sc_params.params.send_data_test == 1 then
+ local data_formated = ""
for _, xml_str in pairs(data) do
- self.sc_logger:info( " value is: " .. xml.str(xml.new(xml_str,0,'<event_data>')))
+ for index, http_post_data in pairs(xml_str) do
+ data_formated = data_formated .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(http_post_data)) .. "" .. tostring(index) .. ">"
+ end
end
+ self.sc_logger:notice(tostring(data_formated) .. "")
return true
end
- local http_post_data = ""
+ local http_post_data = ""
for _, xml_str in pairs(data) do
- http_post_data = http_post_data .. xml.str(xml.new(xml_str,0,'<event_data>'))
+ for index, data_formated in pairs(xml_str) do
+ http_post_data = http_post_data .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(data_formated)) .. "" .. tostring(index) .. ">"
+ end
end
+ http_post_data = http_post_data .. ""
self.sc_logger:info("[EventQueue:send_data]: Going to send the following xml " .. xml.str(http_post_data))
self.sc_logger:info("[EventQueue:send_data]: BSM Http Server URL is: \"" .. tostring(self.sc_params.params.http_server_url .. "\""))
@@ -332,4 +361,4 @@ function write(event)
-- Since we've added an event to a specific queue, flush it if queue is full
queue.sc_flush:flush_queue(queue.send_data_method[1], queue.sc_event.event.category, queue.sc_event.event.element)
return true
-end
+end
\ No newline at end of file
From 84fb5bfd235f2f8de97a21edc30d79a02272000b Mon Sep 17 00:00:00 2001
From: psamecentreon
Date: Fri, 14 Jan 2022 19:55:01 +0000
Subject: [PATCH 07/16] delete comment block
---
centreon-certified/bsm/bsm-events-apiv2.lua | 29 ++-------------------
1 file changed, 2 insertions(+), 27 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index b2424c95..542dc927 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -151,17 +151,7 @@ function EventQueue:format_event_host()
if xml_host_severity == false then
xml_host_severity = 0
end
- --[[.sc_event.event.formated_event = {
- ""
- .. "" .. self.sc_event.event.cache.host.name .. ""
- .. "" .. xml_host_severity .. ""
- .. "" .. xml_notes .. ""
- .. "" .. xml_url .. ""
- .. "" .. self.sc_common:ifnil_or_empty(self.source_ci, 'Centreon') .. ""
- .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
- .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
- .. ""
- }--]]
+
self.sc_event.event.formated_event = {
hostname = self.sc_event.event.cache.host.name,
host_severity = xml_host_severity,
@@ -182,21 +172,6 @@ function EventQueue:format_event_service()
xml_service_severity = 0
end
- --[[self.sc_event.event.formated_event = {
- ""
- .. "" .. self.sc_event.event.cache.host.name .. ""
- .. "" .. self.sc_event.event.cache.service.description .. ""
- .. "" ..self.sc_event.event.state .. ""
- .. "" ..self.sc_event.event.last_update .. ""
- .. ""
- .. "" .. xml_service_severity .. ""
- .. "" .. xml_url .. ""
- .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.host_id, 0) .. ""
- .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.service_id, 0) .. ""
- .. "" .. self.sc_common:ifnil_or_empty(self.sc_event.event.scheduled_downtime_depth, 0) .. ""
- .. ""
- }--]]
-
self.sc_event.event.formated_event = {
hostname = self.sc_event.event.cache.host.name,
svc_desc = self.sc_event.event.cache.service.description,
@@ -361,4 +336,4 @@ function write(event)
-- Since we've added an event to a specific queue, flush it if queue is full
queue.sc_flush:flush_queue(queue.send_data_method[1], queue.sc_event.event.category, queue.sc_event.event.element)
return true
-end
\ No newline at end of file
+end
From 85b28b7200a5c9e8f67d8be1ba579dc270e12916 Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Fri, 14 Jan 2022 20:57:22 +0100
Subject: [PATCH 08/16] Create function xml_escape for bsm-event SC
---
.../sc_common.lua | 27 +++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/modules/centreon-stream-connectors-lib/sc_common.lua b/modules/centreon-stream-connectors-lib/sc_common.lua
index 0d42b7a3..9d9ba13f 100644
--- a/modules/centreon-stream-connectors-lib/sc_common.lua
+++ b/modules/centreon-stream-connectors-lib/sc_common.lua
@@ -247,4 +247,31 @@ function ScCommon:json_escape(string)
return string
end
+--- xml_escape: escape xml special characters in a string
+-- @param string (string) the string that must be escaped
+-- @return string (string) the string with escaped characters
+function ScCommon:xml_escape(string)
+ local type = type(string)
+
+ -- check that param is a valid string
+ if string == nil or type == "table" then
+ self.sc_logger:error("[sc_common:escape_string]: the input parameter is not valid, it is either nil or a table. Sent value: " .. tostring(string))
+ return string
+ end
+
+ -- nothing to escape in a boolean or number value
+ if type ~= "string" then
+ return string
+ end
+
+ -- escape all characters
+ string = string.gsub(string, '<', '<')
+ string = string.gsub(string, '>', '>')
+ string = string.gsub(string, '&', '&')
+ string = string.gsub(string, ''', "'")
+ string = string.gsub(string, '"', '"')
+
+ return string
+end
+
return sc_common
From fac6bb3828307c9f4c9dfcff8bc4cc670b0d2ace Mon Sep 17 00:00:00 2001
From: psamecentreon
Date: Fri, 21 Jan 2022 16:16:26 +0000
Subject: [PATCH 09/16] refacto to v3
---
centreon-certified/bsm/bsm-events-apiv2.lua | 112 +++++++++++++-------
1 file changed, 74 insertions(+), 38 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index 542dc927..d60ad368 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -104,7 +104,11 @@ function EventQueue.new(params)
[categories.bam.id] = {}
}
self.send_data_method = {
- [1] = function (data, element) return self:send_data(data, element) end
+ [1] = function (payload) return self:send_data(payload) end
+ }
+
+ self.build_payload_method = {
+ [1] = function (payload, event) return self:build_payload(payload, event) end
}
-- return EventQueue object
@@ -151,7 +155,7 @@ function EventQueue:format_event_host()
if xml_host_severity == false then
xml_host_severity = 0
end
-
+
self.sc_event.event.formated_event = {
hostname = self.sc_event.event.cache.host.name,
host_severity = xml_host_severity,
@@ -206,30 +210,41 @@ function EventQueue:add()
.. "max is: " .. tostring(self.sc_params.params.max_buffer_size))
end
-function EventQueue:send_data(data, element)
+--------------------------------------------------------------------------------
+-- EventQueue:build_payload, concatenate data so it is ready to be sent
+-- @param payload {string} json encoded string
+-- @param event {table} the event that is going to be added to the payload
+-- @return payload {string} json encoded string
+--------------------------------------------------------------------------------
+function EventQueue:build_payload(payload, event)
+ if not payload then
+ payload = "[send_data]: " .. ""
+ for index, xml_str in pairs(event) do
+ payload = payload .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(xml_str)) .. "" .. tostring(index) .. ">"
+ end
+ payload = payload .. ""
+
+ else
+ payload = payload .. "[send_data]: " .. ""
+ for index, xml_str in pairs(event) do
+ payload = payload .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(xml_str)) .. "" .. tostring(index) .. ">"
+ end
+ payload = payload .. ""
+ end
+
+ return payload
+end
+
+function EventQueue:send_data(payload)
self.sc_logger:debug("[EventQueue:send_data]: Starting to send data")
-- write payload in the logfile for test purpose
if self.sc_params.params.send_data_test == 1 then
- local data_formated = ""
- for _, xml_str in pairs(data) do
- for index, http_post_data in pairs(xml_str) do
- data_formated = data_formated .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(http_post_data)) .. "" .. tostring(index) .. ">"
- end
- end
- self.sc_logger:notice(tostring(data_formated) .. "")
+ self.sc_logger:notice("[send_data]: " .. tostring(payload))
return true
end
- local http_post_data = ""
- for _, xml_str in pairs(data) do
- for index, data_formated in pairs(xml_str) do
- http_post_data = http_post_data .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(data_formated)) .. "" .. tostring(index) .. ">"
- end
- end
- http_post_data = http_post_data .. ""
-
- self.sc_logger:info("[EventQueue:send_data]: Going to send the following xml " .. xml.str(http_post_data))
+ self.sc_logger:info("[EventQueue:send_data]: Going to send the following xml " .. tostring(payload))
self.sc_logger:info("[EventQueue:send_data]: BSM Http Server URL is: \"" .. tostring(self.sc_params.params.http_server_url .. "\""))
local http_response_body = ""
@@ -246,7 +261,7 @@ function EventQueue:send_data(data, element)
curl.OPT_HTTPHEADER,
{
"Content-Type: text/xml",
- "content-length: " .. string.len(http_post_data)
+ "content-length: " .. string.len(payload)
}
)
@@ -269,7 +284,7 @@ function EventQueue:send_data(data, element)
end
-- adding the HTTP POST data
- http_request:setopt_postfields(http_post_data)
+ http_request:setopt_postfields(payload)
-- performing the HTTP request
http_request:perform()
-- collecting results
@@ -300,40 +315,61 @@ end
-- Fonction write()
function write(event)
- -- First, flush all queues if needed (too old or size too big)
- queue.sc_flush:flush_all_queues(queue.send_data_method[1])
-
-- skip event if a mandatory parameter is missing
if queue.fail then
queue.sc_logger:error("Skipping event because a mandatory parameter is not set")
- return true
+ return false
end
-- initiate event object
queue.sc_event = sc_event.new(event, queue.sc_params.params, queue.sc_common, queue.sc_logger, queue.sc_broker)
- -- drop event if wrong category
- if not queue.sc_event:is_valid_category() then
+ if queue.sc_event:is_valid_category() then
+ if queue.sc_event:is_valid_element() then
+ -- format event if it is validated
+ if queue.sc_event:is_valid_event() then
+ queue:format_accepted_event()
+ end
+ --- log why the event has been dropped
+ else
+ queue.sc_logger:debug("dropping event because element is not valid. Event element is: "
+ .. tostring(queue.sc_params.params.reverse_element_mapping[queue.sc_event.event.category][queue.sc_event.event.element]))
+ end
+ else
queue.sc_logger:debug("dropping event because category is not valid. Event category is: "
.. tostring(queue.sc_params.params.reverse_category_mapping[queue.sc_event.event.category]))
+ end
+
+ return flush()
+end
+
+-- flush method is called by broker every now and then (more often when broker has nothing else to do)
+function flush()
+ local queues_size = queue.sc_flush:get_queues_size()
+
+ -- nothing to flush
+ if queues_size == 0 then
return true
end
- -- drop event if wrong element
- if not queue.sc_event:is_valid_element() then
- queue.sc_logger:debug("dropping event because element is not valid. Event element is: "
- .. tostring(queue.sc_params.params.reverse_element_mapping[queue.sc_event.event.category][queue.sc_event.event.element]))
+ -- flush all queues because last global flush is too old
+ if queue.sc_flush.last_global_flush < os.time() - queue.sc_params.params.max_all_queues_age then
+ if not queue.sc_flush:flush_all_queues(queue.build_payload_method[1], queue.send_data_method[1]) then
+ return false
+ end
+
return true
end
- -- drop event if it is not validated
- if queue.sc_event:is_valid_event() then
- queue:format_accepted_event()
- else
+ -- flush queues because too many events are stored in them
+ if queues_size > queue.sc_params.params.max_buffer_size then
+ if not queue.sc_flush:flush_all_queues(queue.build_payload_method[1], queue.send_data_method[1]) then
+ return false
+ end
+
return true
end
- -- Since we've added an event to a specific queue, flush it if queue is full
- queue.sc_flush:flush_queue(queue.send_data_method[1], queue.sc_event.event.category, queue.sc_event.event.element)
- return true
+ -- there are events in the queue but they were not ready to be send
+ return false
end
From 5fcca75f512b27a43482a17d43897e4c16e92b6a Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Fri, 21 Jan 2022 17:20:13 +0100
Subject: [PATCH 10/16] Delete file because already in others PR
---
.../sc_common.lua | 277 ------------------
1 file changed, 277 deletions(-)
delete mode 100644 modules/centreon-stream-connectors-lib/sc_common.lua
diff --git a/modules/centreon-stream-connectors-lib/sc_common.lua b/modules/centreon-stream-connectors-lib/sc_common.lua
deleted file mode 100644
index 9d9ba13f..00000000
--- a/modules/centreon-stream-connectors-lib/sc_common.lua
+++ /dev/null
@@ -1,277 +0,0 @@
-#!/usr/bin/lua
-
----
--- Module with common methods for Centreon Stream Connectors
--- @module sc_common
--- @alias sc_common
-
-local sc_common = {}
-
-local sc_logger = require("centreon-stream-connectors-lib.sc_logger")
-
---- ifnil_or_empty: change a nil or empty variable for a specified value
--- @param var (string|number) the variable that needs to be checked
--- @param alt (string|number|table) the alternate value if "var" is nil or empty
--- @return var or alt (string|number|table) the variable or the alternate value
-local function ifnil_or_empty(var, alt)
- if var == nil or var == "" then
- return alt
- else
- return var
- end
-end
-
-local ScCommon = {}
-
-function sc_common.new(sc_logger)
- local self = {}
-
- self.sc_logger = sc_logger
- if not self.sc_logger then
- self.sc_logger = sc_logger.new()
- end
-
- setmetatable(self, { __index = ScCommon })
-
- return self
-end
-
---- ifnil_or_empty: change a nil or empty variable for a specified value
--- @param var (string|number) the variable that needs to be checked
--- @param alt (string|number|table) the alternate value if "var" is nil or empty
--- @return var or alt (string|number|table) the variable or the alternate value
-function ScCommon:ifnil_or_empty(var, alt)
- return ifnil_or_empty(var, alt)
-end
-
---- if_wrong_type: change a wrong type variable with a default value
--- @param var (any) the variable that needs to be checked
--- @param type (string) the expected type of the variable
--- @param default (any) the default value for the variable if type is wrong
--- @return var or default (any) the variable if type is good or the default value
-function ScCommon:if_wrong_type(var, var_type, default)
- if type(var) == var_type then
- return var
- end
-
- return default
-end
-
---- boolean_to_number: convert boolean variable to number
--- @param boolean (boolean) the boolean that will be converted
--- @return (number) a number according to the boolean value
-function ScCommon:boolean_to_number(boolean)
- return boolean and 1 or 0
-end
-
---- number_to_boolean: convert a 0, 1 number to its boolean counterpart
--- @param number (number) the number to convert
--- @return (boolean) true if param is 1, false if param is 0
-function ScCommon:number_to_boolean(number)
- if number ~= 0 and number ~= 1 then
- self.sc_logger:error("[sc_common:number_to_boolean]: number is not 1 or 0. Returning nil. Parameter value is: " .. tostring(number))
- return nil
- end
-
- if number == 1 then
- return true
- end
-
- return false
-end
-
-
---- check_boolean_number_option_syntax: make sure the number is either 1 or 0
--- @param number (number) the boolean number that must be validated
--- @param default (number) the default value that is going to be return if the default number is not validated
--- @return number (number) a boolean number
-function ScCommon:check_boolean_number_option_syntax(number, default)
- if number ~= 1 and number ~= 0 then
- number = default
- end
-
- return number
-end
-
---- split: convert a string into a table
--- @param text (string) the string that is going to be splitted into a table
--- @param [opt] separator (string) the separator character that will be used to split the string
--- @return false (boolean) if text param is empty or nil
--- @return table (table) a table of strings
-function ScCommon:split (text, separator)
- -- return false if text is nil or empty
- if text == nil or text == "" then
- self.sc_logger:error("[sc_common:split]: could not split text because it is nil or empty")
- return false
- end
-
- local hash = {}
-
- -- set default separator
- separator = ifnil_or_empty(separator, ",")
-
- for value in string.gmatch(text, "([^" .. separator .. "]+)") do
- table.insert(hash, value)
- end
-
- return hash
-end
-
---- compare_numbers: compare two numbers, if comparison is valid, then return true
--- @param firstNumber {number}
--- @param secondNumber {number}
--- @param operator {string} the mathematical operator that is used for the comparison
--- @return {boolean}
-function ScCommon:compare_numbers(firstNumber, secondNumber, operator)
- if operator ~= "==" and operator ~= "~=" and operator ~= "<" and operator ~= ">" and operator ~= ">=" and operator ~= "<=" then
- return nil
- end
-
- if type(firstNumber) ~= "number" or type(secondNumber) ~= "number" then
- return nil
- end
-
- if operator == "<" then
- if firstNumber < secondNumber then
- return true
- end
- elseif operator == ">" then
- if firstNumber > secondNumber then
- return true
- end
- elseif operator == ">=" then
- if firstNumber >= secondNumber then
- return true
- end
- elseif operator == "<=" then
- if firstNumber <= secondNumber then
- return true
- end
- elseif operator == "==" then
- if firstNumber == secondNumber then
- return true
- end
- elseif operator == "~=" then
- if firstNumber ~= secondNumber then
- return true
- end
- end
-
- return false
-end
-
---- generate_postfield_param_string: convert a table of parameters into an url encoded url parameters string
--- @param params (table) the table of all url string parameters to convert
--- @return false (boolean) if params variable is not a table
--- @return param_string (string) the url encoded parameters string
-function ScCommon:generate_postfield_param_string(params)
- -- return false because params type is wrong
- if (type(params) ~= "table") then
- self.sc_logger:error("[sc_common:generate_postfield_param_string]: parameters to convert aren't in a table")
- return false
- end
-
- local param_string = ""
-
- -- concatenate data in params table into a string
- for field, value in pairs(params) do
- if param_string == "" then
- param_string = field .. "=" .. broker.url_encode(value)
- else
- param_string = param_string .. "&" .. field .. "=" .. broker.url_encode(value)
- end
- end
-
- -- return url encoded string
- return param_string
-end
-
---- load_json_file: load a json file
--- @param json_file (string) path to the json file
--- @return true|false (boolean) if json file is valid or not
--- @return content (table) the parsed json
-function ScCommon:load_json_file(json_file)
- local file = io.open(json_file, "r")
-
- -- return false if we can't open the file
- if not file then
- self.sc_logger:error("[sc_common:load_json_file]: couldn't open file "
- .. tostring(json_file) .. ". Make sure your file is there and that it is readable by centreon-broker")
- return false
- end
-
- -- get content of the file
- local file_content = file:read("*a")
- io.close(file)
-
- -- parse it
- local content, error = broker.json_decode(file_content)
-
- -- return false if json couldn't be parsed
- if error then
- self.sc_logger:error("[sc_common:load_json_file]: could not parse json file "
- .. tostring(json_file) .. ". Error is: " .. tostring(error))
- return false
- end
-
- return true, content
-end
-
---- json_escape: escape json special characters in a string
--- @param string (string) the string that must be escaped
--- @return string (string) the string with escaped characters
-function ScCommon:json_escape(string)
- local type = type(string)
-
- -- check that param is a valid string
- if string == nil or type == "table" then
- self.sc_logger:error("[sc_common:escape_string]: the input parameter is not valid, it is either nil or a table. Sent value: " .. tostring(string))
- return string
- end
-
- -- nothing to escape in a boolean or number value
- if type ~= "string" then
- return string
- end
-
- -- escape all characters
- string = string.gsub(string, '\\', '\\\\')
- string = string.gsub(string, '\t', '\\t')
- string = string.gsub(string, '\n', '\\n')
- string = string.gsub(string, '\b', '\\b')
- string = string.gsub(string, '\r', '\\r')
- string = string.gsub(string, '\f', '\\f')
- string = string.gsub(string, '/', '\\/')
- string = string.gsub(string, '"', '\\"')
-
- return string
-end
-
---- xml_escape: escape xml special characters in a string
--- @param string (string) the string that must be escaped
--- @return string (string) the string with escaped characters
-function ScCommon:xml_escape(string)
- local type = type(string)
-
- -- check that param is a valid string
- if string == nil or type == "table" then
- self.sc_logger:error("[sc_common:escape_string]: the input parameter is not valid, it is either nil or a table. Sent value: " .. tostring(string))
- return string
- end
-
- -- nothing to escape in a boolean or number value
- if type ~= "string" then
- return string
- end
-
- -- escape all characters
- string = string.gsub(string, '<', '<')
- string = string.gsub(string, '>', '>')
- string = string.gsub(string, '&', '&')
- string = string.gsub(string, ''', "'")
- string = string.gsub(string, '"', '"')
-
- return string
-end
-
-return sc_common
From 92641dd248a4d20e570b4791c57fae1c4318aa67 Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Tue, 25 Jan 2022 11:01:09 +0100
Subject: [PATCH 11/16] Apply suggestions from code review
Co-authored-by: tcharles
---
centreon-certified/bsm/bsm-events-apiv2.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index d60ad368..f61c1a65 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -218,14 +218,14 @@ end
--------------------------------------------------------------------------------
function EventQueue:build_payload(payload, event)
if not payload then
- payload = "[send_data]: " .. ""
+ payload = ""
for index, xml_str in pairs(event) do
payload = payload .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(xml_str)) .. "" .. tostring(index) .. ">"
end
payload = payload .. ""
else
- payload = payload .. "[send_data]: " .. ""
+ payload = payload .. ""
for index, xml_str in pairs(event) do
payload = payload .. "<" .. tostring(index) .. ">" .. tostring(self.sc_common:xml_escape(xml_str)) .. "" .. tostring(index) .. ">"
end
From 92c7063160be81c8b5f58c0ff76010c8fa8aa9f2 Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Tue, 25 Jan 2022 15:15:49 +0100
Subject: [PATCH 12/16] Create sc_common.lua
---
.../sc_common.lua | 250 ++++++++++++++++++
1 file changed, 250 insertions(+)
create mode 100644 modules/centreon-stream-connectors-lib/sc_common.lua
diff --git a/modules/centreon-stream-connectors-lib/sc_common.lua b/modules/centreon-stream-connectors-lib/sc_common.lua
new file mode 100644
index 00000000..0d42b7a3
--- /dev/null
+++ b/modules/centreon-stream-connectors-lib/sc_common.lua
@@ -0,0 +1,250 @@
+#!/usr/bin/lua
+
+---
+-- Module with common methods for Centreon Stream Connectors
+-- @module sc_common
+-- @alias sc_common
+
+local sc_common = {}
+
+local sc_logger = require("centreon-stream-connectors-lib.sc_logger")
+
+--- ifnil_or_empty: change a nil or empty variable for a specified value
+-- @param var (string|number) the variable that needs to be checked
+-- @param alt (string|number|table) the alternate value if "var" is nil or empty
+-- @return var or alt (string|number|table) the variable or the alternate value
+local function ifnil_or_empty(var, alt)
+ if var == nil or var == "" then
+ return alt
+ else
+ return var
+ end
+end
+
+local ScCommon = {}
+
+function sc_common.new(sc_logger)
+ local self = {}
+
+ self.sc_logger = sc_logger
+ if not self.sc_logger then
+ self.sc_logger = sc_logger.new()
+ end
+
+ setmetatable(self, { __index = ScCommon })
+
+ return self
+end
+
+--- ifnil_or_empty: change a nil or empty variable for a specified value
+-- @param var (string|number) the variable that needs to be checked
+-- @param alt (string|number|table) the alternate value if "var" is nil or empty
+-- @return var or alt (string|number|table) the variable or the alternate value
+function ScCommon:ifnil_or_empty(var, alt)
+ return ifnil_or_empty(var, alt)
+end
+
+--- if_wrong_type: change a wrong type variable with a default value
+-- @param var (any) the variable that needs to be checked
+-- @param type (string) the expected type of the variable
+-- @param default (any) the default value for the variable if type is wrong
+-- @return var or default (any) the variable if type is good or the default value
+function ScCommon:if_wrong_type(var, var_type, default)
+ if type(var) == var_type then
+ return var
+ end
+
+ return default
+end
+
+--- boolean_to_number: convert boolean variable to number
+-- @param boolean (boolean) the boolean that will be converted
+-- @return (number) a number according to the boolean value
+function ScCommon:boolean_to_number(boolean)
+ return boolean and 1 or 0
+end
+
+--- number_to_boolean: convert a 0, 1 number to its boolean counterpart
+-- @param number (number) the number to convert
+-- @return (boolean) true if param is 1, false if param is 0
+function ScCommon:number_to_boolean(number)
+ if number ~= 0 and number ~= 1 then
+ self.sc_logger:error("[sc_common:number_to_boolean]: number is not 1 or 0. Returning nil. Parameter value is: " .. tostring(number))
+ return nil
+ end
+
+ if number == 1 then
+ return true
+ end
+
+ return false
+end
+
+
+--- check_boolean_number_option_syntax: make sure the number is either 1 or 0
+-- @param number (number) the boolean number that must be validated
+-- @param default (number) the default value that is going to be return if the default number is not validated
+-- @return number (number) a boolean number
+function ScCommon:check_boolean_number_option_syntax(number, default)
+ if number ~= 1 and number ~= 0 then
+ number = default
+ end
+
+ return number
+end
+
+--- split: convert a string into a table
+-- @param text (string) the string that is going to be splitted into a table
+-- @param [opt] separator (string) the separator character that will be used to split the string
+-- @return false (boolean) if text param is empty or nil
+-- @return table (table) a table of strings
+function ScCommon:split (text, separator)
+ -- return false if text is nil or empty
+ if text == nil or text == "" then
+ self.sc_logger:error("[sc_common:split]: could not split text because it is nil or empty")
+ return false
+ end
+
+ local hash = {}
+
+ -- set default separator
+ separator = ifnil_or_empty(separator, ",")
+
+ for value in string.gmatch(text, "([^" .. separator .. "]+)") do
+ table.insert(hash, value)
+ end
+
+ return hash
+end
+
+--- compare_numbers: compare two numbers, if comparison is valid, then return true
+-- @param firstNumber {number}
+-- @param secondNumber {number}
+-- @param operator {string} the mathematical operator that is used for the comparison
+-- @return {boolean}
+function ScCommon:compare_numbers(firstNumber, secondNumber, operator)
+ if operator ~= "==" and operator ~= "~=" and operator ~= "<" and operator ~= ">" and operator ~= ">=" and operator ~= "<=" then
+ return nil
+ end
+
+ if type(firstNumber) ~= "number" or type(secondNumber) ~= "number" then
+ return nil
+ end
+
+ if operator == "<" then
+ if firstNumber < secondNumber then
+ return true
+ end
+ elseif operator == ">" then
+ if firstNumber > secondNumber then
+ return true
+ end
+ elseif operator == ">=" then
+ if firstNumber >= secondNumber then
+ return true
+ end
+ elseif operator == "<=" then
+ if firstNumber <= secondNumber then
+ return true
+ end
+ elseif operator == "==" then
+ if firstNumber == secondNumber then
+ return true
+ end
+ elseif operator == "~=" then
+ if firstNumber ~= secondNumber then
+ return true
+ end
+ end
+
+ return false
+end
+
+--- generate_postfield_param_string: convert a table of parameters into an url encoded url parameters string
+-- @param params (table) the table of all url string parameters to convert
+-- @return false (boolean) if params variable is not a table
+-- @return param_string (string) the url encoded parameters string
+function ScCommon:generate_postfield_param_string(params)
+ -- return false because params type is wrong
+ if (type(params) ~= "table") then
+ self.sc_logger:error("[sc_common:generate_postfield_param_string]: parameters to convert aren't in a table")
+ return false
+ end
+
+ local param_string = ""
+
+ -- concatenate data in params table into a string
+ for field, value in pairs(params) do
+ if param_string == "" then
+ param_string = field .. "=" .. broker.url_encode(value)
+ else
+ param_string = param_string .. "&" .. field .. "=" .. broker.url_encode(value)
+ end
+ end
+
+ -- return url encoded string
+ return param_string
+end
+
+--- load_json_file: load a json file
+-- @param json_file (string) path to the json file
+-- @return true|false (boolean) if json file is valid or not
+-- @return content (table) the parsed json
+function ScCommon:load_json_file(json_file)
+ local file = io.open(json_file, "r")
+
+ -- return false if we can't open the file
+ if not file then
+ self.sc_logger:error("[sc_common:load_json_file]: couldn't open file "
+ .. tostring(json_file) .. ". Make sure your file is there and that it is readable by centreon-broker")
+ return false
+ end
+
+ -- get content of the file
+ local file_content = file:read("*a")
+ io.close(file)
+
+ -- parse it
+ local content, error = broker.json_decode(file_content)
+
+ -- return false if json couldn't be parsed
+ if error then
+ self.sc_logger:error("[sc_common:load_json_file]: could not parse json file "
+ .. tostring(json_file) .. ". Error is: " .. tostring(error))
+ return false
+ end
+
+ return true, content
+end
+
+--- json_escape: escape json special characters in a string
+-- @param string (string) the string that must be escaped
+-- @return string (string) the string with escaped characters
+function ScCommon:json_escape(string)
+ local type = type(string)
+
+ -- check that param is a valid string
+ if string == nil or type == "table" then
+ self.sc_logger:error("[sc_common:escape_string]: the input parameter is not valid, it is either nil or a table. Sent value: " .. tostring(string))
+ return string
+ end
+
+ -- nothing to escape in a boolean or number value
+ if type ~= "string" then
+ return string
+ end
+
+ -- escape all characters
+ string = string.gsub(string, '\\', '\\\\')
+ string = string.gsub(string, '\t', '\\t')
+ string = string.gsub(string, '\n', '\\n')
+ string = string.gsub(string, '\b', '\\b')
+ string = string.gsub(string, '\r', '\\r')
+ string = string.gsub(string, '\f', '\\f')
+ string = string.gsub(string, '/', '\\/')
+ string = string.gsub(string, '"', '\\"')
+
+ return string
+end
+
+return sc_common
From d41d32660adc08f4e833d712e5bb177e74d779fa Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Tue, 25 Jan 2022 16:50:39 +0100
Subject: [PATCH 13/16] Last review
---
centreon-certified/bsm/bsm-events-apiv2.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index f61c1a65..a9169de2 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -28,7 +28,6 @@
-- Libraries
local curl = require "cURL"
-require("LuaXML")
-- Centreon lua core libraries
local sc_common = require("centreon-stream-connectors-lib.sc_common")
@@ -103,6 +102,7 @@ function EventQueue.new(params)
},
[categories.bam.id] = {}
}
+
self.send_data_method = {
[1] = function (payload) return self:send_data(payload) end
}
@@ -330,6 +330,7 @@ function write(event)
if queue.sc_event:is_valid_event() then
queue:format_accepted_event()
end
+
--- log why the event has been dropped
else
queue.sc_logger:debug("dropping event because element is not valid. Event element is: "
From ce03a507c10ce8c976adbbd230660a73a35c7cc4 Mon Sep 17 00:00:00 2001
From: psame <44295022+psamecentreon@users.noreply.github.com>
Date: Wed, 26 Jan 2022 14:45:17 +0100
Subject: [PATCH 14/16] Update bsm-events-apiv2.lua
---
centreon-certified/bsm/bsm-events-apiv2.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index a9169de2..b166bb4e 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -63,7 +63,7 @@ function EventQueue.new(params)
}
-- set up log configuration
- local logfile = params.logfile or "/var/log/centreon-broker/bsm_connector-apiv2.log"
+ local logfile = params.logfile or "/var/log/centreon-broker/bsm_event-apiv2.log"
local log_level = params.log_level or 1
-- initiate mandatory objects
From 6f23a773aada9a9bd4414016599580693092dc6b Mon Sep 17 00:00:00 2001
From: tcharles
Date: Mon, 9 May 2022 16:48:31 +0200
Subject: [PATCH 15/16] Update centreon-certified/bsm/bsm-events-apiv2.lua
---
centreon-certified/bsm/bsm-events-apiv2.lua | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index b166bb4e..ca76ddf1 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -127,9 +127,7 @@ function EventQueue:format_accepted_event()
self.sc_event.event.formated_event = {}
if self.format_template and template ~= nil and template ~= "" then
- for index, value in pairs(template) do
- self.sc_event.event.formated_event[index] = self.sc_macros:replace_sc_macro(value, self.sc_event.event)
- end
+ self.sc_event.event.formated_event = self.sc_macros:replace_sc_macro(template, self.sc_event.event, true)
else
-- can't format event if stream connector is not handling this kind of event and that it is not handled with a template file
if not self.format_event[category][element] then
From 2cd14e127387f588d4dc6df662dfebab5d75bc67 Mon Sep 17 00:00:00 2001
From: tcharles
Date: Mon, 9 May 2022 16:48:52 +0200
Subject: [PATCH 16/16] Update centreon-certified/bsm/bsm-events-apiv2.lua
---
centreon-certified/bsm/bsm-events-apiv2.lua | 2 --
1 file changed, 2 deletions(-)
diff --git a/centreon-certified/bsm/bsm-events-apiv2.lua b/centreon-certified/bsm/bsm-events-apiv2.lua
index ca76ddf1..94f548e4 100644
--- a/centreon-certified/bsm/bsm-events-apiv2.lua
+++ b/centreon-certified/bsm/bsm-events-apiv2.lua
@@ -38,8 +38,6 @@ local sc_params = require("centreon-stream-connectors-lib.sc_params")
local sc_macros = require("centreon-stream-connectors-lib.sc_macros")
local sc_flush = require("centreon-stream-connectors-lib.sc_flush")
--- workaround https://github.com/centreon/centreon-broker/issues/201
-local previous_event = ""
--------------------------------------------------------------------------------
-- EventQueue class