Skip to content

Commit ff5a5c5

Browse files
committed
enh: also send metrics in batches for hosts
+ count queue size as number of metrics, not of services
1 parent 3614195 commit ff5a5c5

1 file changed

Lines changed: 80 additions & 78 deletions

File tree

centreon-certified/splunk/splunk-metrics-apiv2.lua

Lines changed: 80 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function event_queue.new(params)
4949
self.sc_params.params.splunk_sourcetype = params.splunk_sourcetype or "_json"
5050
self.sc_params.params.splunk_host = params.splunk_host or "Central"
5151
self.sc_params.params.accepted_categories = params.accepted_categories or "neb"
52-
self.sc_params.params.accepted_elements = params.accepted_elements or "service_status"
52+
self.sc_params.params.accepted_elements = params.accepted_elements or "host_status,service_status"
5353
self.sc_params.params.max_buffer_size = params.max_buffer_size or 30
5454
self.sc_params.params.hard_only = params.hard_only or 0
5555
self.sc_params.params.enable_host_status_dedup = params.enable_host_status_dedup or 0
@@ -77,23 +77,6 @@ function event_queue.new(params)
7777
local categories = self.sc_params.params.bbdo.categories
7878
local elements = self.sc_params.params.bbdo.elements
7979

80-
-- it is not possible to have a payload containing metrics from different hosts or services.
81-
-- therefore, we need to check if the metric that we are working on belongs to the same host/service than the previous metric
82-
-- that's why we initiate a structure to store this info
83-
self.previous_info = {
84-
[categories.neb.id] = {
85-
[elements.host_status.id] = {
86-
host_id = "",
87-
flush_success = false
88-
},
89-
[elements.service_status.id] = {
90-
host_id = "",
91-
service_id = "",
92-
flush_success = false
93-
}
94-
}
95-
}
96-
9780
self.format_event = {
9881
[categories.neb.id] = {
9982
[elements.host_status.id] = function () return self:format_event_host() end,
@@ -116,6 +99,10 @@ function event_queue.new(params)
11699
[1] = function (payload, event) return self:build_payload(payload, event) end
117100
}
118101

102+
-- Since this stream connector sends metrics and since all the metrics of one service are sent as one event
103+
-- the volume of data can be really high if some services contain hundreds of metrics.
104+
-- To avoid sending megabytes in one request, we will use a custom queue size attribute
105+
self.custom_queue_size = 0
119106
-- those sleep counters will avoid log spam and connection spam
120107
self.send_data_sleep_counter = self.sc_common:create_sleep_counter_table({}, 0, 300, 10)
121108
self.init_fail_sleep_counter = self.sc_common:create_sleep_counter_table({}, 0, 300, 10)
@@ -144,15 +131,6 @@ function event_queue:format_accepted_event()
144131
self.format_event[category][element]()
145132
end
146133

147-
-- Add hostgroup
148-
if self.sc_event.event.cache.host.groups then
149-
self.sc_event.event.formated_event["hostgroups:"] = self.sc_event.event.cache.host.groups
150-
end
151-
152-
-- Add ACK & Downtime
153-
self.sc_event.event.formated_event["acknowledge"] = self.sc_event.event.acknowledged
154-
self.sc_event.event.formated_event["downtime"] = self.sc_event.event.scheduled_downtime_depth
155-
156134
self.sc_logger:debug("[event_queue:format_event]: event formatting is finished")
157135
end
158136

@@ -161,37 +139,70 @@ end
161139
function event_queue:format_event_host()
162140
self.sc_logger:debug("[event_queue:format_event_host]: starting format event host.")
163141
local event = self.sc_event.event
164-
self.sc_logger:debug("[event_queue:format_event_host]: call build_metric ")
142+
143+
self.sc_event.event.formated_event = {
144+
event_type = "host",
145+
state = event.state,
146+
state_type = event.state_type,
147+
hostname = event.cache.host.name,
148+
hostaddress = event.cache.host.address,
149+
lastchange = event.last_hard_state_change,
150+
ctime = event.last_check
151+
}
152+
-- Add ACK & Downtime
153+
event.formated_event["acknowledge"] = event.acknowledged
154+
event.formated_event["downtime"] = event.scheduled_downtime_depth
155+
156+
-- Add hostgroup
157+
if event.cache.host.groups then
158+
event.formated_event["hostgroups"] = event.cache.host.groups
159+
end
160+
165161
self.sc_metrics:build_metric(self.format_metric[event.category][event.element])
162+
self:add()
163+
164+
self.sc_logger:debug("[event_queue:format_event_host]: format event host is finished ")
166165
end
167166

168167
--- Formats service events by calling the format_metric() function defined for service status events
169168
--- @return void
170169
function event_queue:format_event_service()
171170
self.sc_logger:debug("[event_queue:format_event_service]: starting format event service.")
172171
local event = self.sc_event.event
173-
self.sc_metrics:build_metric(self.format_metric[event.category][event.element])
174-
self.sc_logger:debug("[event_queue:format_event_service]: format metric service is finished ")
175-
end
176-
177-
--- Prepare a formatted metric event based on a service status event
178-
--- @param metric table A single metric's data
179-
--- @return void
180-
function event_queue:format_metric_host(metric)
181-
self.sc_logger:debug("[event_queue:format_metric_host]: call format metric ")
182-
local event = self.sc_event.event
183172

184173
self.sc_event.event.formated_event = {
185-
event_type = "host",
174+
event_type = "service",
186175
state = event.state,
187176
state_type = event.state_type,
188177
hostname = event.cache.host.name,
189178
hostaddress = event.cache.host.address,
179+
service_description = event.cache.service.description,
190180
lastchange = event.last_hard_state_change,
191181
ctime = event.last_check
192182
}
183+
-- Add ACK & Downtime
184+
event.formated_event["acknowledge"] = event.acknowledged
185+
event.formated_event["downtime"] = event.scheduled_downtime_depth
186+
187+
-- Add hostgroup
188+
if event.cache.host.groups then
189+
event.formated_event["hostgroups"] = event.cache.host.groups
190+
end
191+
192+
self.sc_metrics:build_metric(self.format_metric[event.category][event.element])
193+
self:add()
194+
195+
self.sc_logger:debug("[event_queue:format_event_service]: format event service is finished ")
196+
end
197+
198+
--- Prepare a formatted metric event based on a service status event
199+
--- @param metric table A single metric's data
200+
--- @return void
201+
function event_queue:format_metric_host(metric)
202+
self.sc_logger:debug("[event_queue:format_metric_host]: call format metric ")
193203

194204
self:format_metric_event(metric)
205+
195206
self.sc_logger:debug("[event_queue:format_metric_host]: Finishing")
196207
end
197208

@@ -200,20 +211,9 @@ end
200211
--- @return void
201212
function event_queue:format_metric_service(metric)
202213
self.sc_logger:debug("[event_queue:format_metric_service]: Beginning to format metric ")
203-
local event = self.sc_event.event
204-
205-
self.sc_event.event.formated_event = {
206-
event_type = "service",
207-
state = event.state,
208-
state_type = event.state_type,
209-
hostname = event.cache.host.name,
210-
hostaddress = event.cache.host.address,
211-
service_description = event.cache.service.description,
212-
lastchange = event.last_hard_state_change,
213-
ctime = event.last_check
214-
}
215214

216215
self:format_metric_event(metric)
216+
217217
self.sc_logger:debug("[event_queue:format_metric_service]: Finishing")
218218
end
219219

@@ -222,18 +222,21 @@ end
222222
--- @return void
223223
function event_queue:format_metric_event(metric)
224224
self.sc_logger:debug("[event_queue:format_metric]: start real format metric ")
225-
self.sc_event.event.formated_event["metric_name:" .. tostring(metric.metric_name)] = metric.value
226-
227-
-- add metric instance in tags
225+
local full_metric_name = ''
226+
227+
-- add metric instance
228228
if metric.instance ~= "" then
229-
self.sc_event.event.formated_event["instance"] = metric.instance
229+
full_metric_name = metric.instance .. '_'
230230
end
231-
232-
if metric.subinstance[1] then
233-
self.sc_event.event.formated_event["subinstances"] = metric.subinstance
231+
232+
for _, sub_instance in ipairs(metric.subinstance) do
233+
full_metric_name = full_metric_name .. sub_instance .. '_'
234234
end
235-
236-
self:add()
235+
full_metric_name = full_metric_name .. tostring(metric.metric_name)
236+
237+
self.sc_event.event.formated_event["metric_name:" .. full_metric_name] = metric.value
238+
self.custom_queue_size = self.custom_queue_size + 1
239+
237240
self.sc_logger:debug("[event_queue:format_metric]: end real format metric ")
238241
end
239242

@@ -250,7 +253,7 @@ function event_queue:add()
250253

251254
self.sc_flush.queues[category][element].events[#self.sc_flush.queues[category][element].events + 1] = self.sc_event.event.formated_event
252255

253-
self.sc_logger:info("[event_queue:add]: queue size is now: " .. tostring(#self.sc_flush.queues[category][element].events)
256+
self.sc_logger:info("[event_queue:add]: queue size is now: " .. tostring(self.custom_queue_size)
254257
.. ", max is: " .. tostring(self.sc_params.params.max_buffer_size))
255258
end
256259

@@ -260,11 +263,19 @@ end
260263
--- @return string json encoded string
261264
function event_queue:build_payload(payload, event)
262265
self.sc_logger:debug("[event_queue:build_payload]: Starting to build payload")
266+
local data_to_send = {
267+
sourcetype = self.sc_params.params.splunk_sourcetype,
268+
source = self.sc_params.params.splunk_source,
269+
index = self.sc_params.params.splunk_index,
270+
host = self.sc_params.params.splunk_host,
271+
time = self.sc_event.event.last_check,
272+
event = event
273+
}
263274

264275
if not payload then
265-
payload = { event }
276+
payload = { data_to_send }
266277
else
267-
table.insert(payload, event)
278+
table.insert(payload, data_to_send)
268279
end
269280

270281
self.sc_logger:debug("[event_queue:build_payload]: Finishing to build payload")
@@ -279,16 +290,7 @@ function event_queue:send_data(payload, queue_metadata)
279290
self.sc_logger:debug("[event_queue:send_data]: Starting to send data")
280291

281292
-- until this line, the payload variable contains an array of objects
282-
payload = broker.json_encode(
283-
{
284-
sourcetype = self.sc_params.params.splunk_sourcetype,
285-
source = self.sc_params.params.splunk_source,
286-
index = self.sc_params.params.splunk_index,
287-
host = self.sc_params.params.splunk_host,
288-
time = self.sc_event.event.last_check,
289-
event = payload
290-
}
291-
)
293+
payload = broker.json_encode( payload )
292294
-- now it is a JSON string with the former table encoded under the event attribute
293295

294296
queue_metadata.headers = {
@@ -419,8 +421,9 @@ end
419421
-- flush method is called by broker every now and then (more often when broker has nothing else to do)
420422
function flush()
421423
queue.sc_logger:debug("[flush]: Function starting")
422-
local queues_size = queue.sc_flush:get_queues_size()
423-
424+
local queues_size = queue.custom_queue_size
425+
queue.sc_logger:debug("[flush]: queue size is now: " .. queues_size .. ", max is: " .. queue.sc_params.params.max_buffer_size)
426+
424427
-- nothing to flush
425428
if queues_size == 0 then
426429
queue.sc_logger:debug("[flush]: Function finishing without flushing (queue empty)")
@@ -433,7 +436,7 @@ function flush()
433436
if not queue.sc_flush:flush_all_queues(queue.build_payload_method[1], queue.send_data_method[1]) then
434437
return false
435438
end
436-
439+
queue.custom_queue_size = 0
437440
return true
438441
end
439442

@@ -443,11 +446,10 @@ function flush()
443446
if not queue.sc_flush:flush_all_queues(queue.build_payload_method[1], queue.send_data_method[1]) then
444447
return false
445448
end
446-
449+
queue.custom_queue_size = 0
447450
return true
448451
end
449452
queue.sc_logger:debug("[flush]: Function finishing without flushing")
450453
-- there are events in the queue but they were not ready to be send
451454
return false
452455
end
453-

0 commit comments

Comments
 (0)