logstash-integration-snmp 4.2.2-java → 4.3.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/VERSION +1 -1
- data/docs/input-snmp.asciidoc +55 -0
- data/lib/logstash/inputs/snmp.rb +16 -3
- data/lib/logstash-integration-snmp_jars.rb +1 -1
- data/spec/unit/inputs/snmp_spec.rb +102 -5
- data/vendor/jar-dependencies/org/logstash/integrations/plugin/4.3.1/plugin-4.3.1.jar +0 -0
- metadata +3 -3
- data/vendor/jar-dependencies/org/logstash/integrations/plugin/4.2.2/plugin-4.2.2.jar +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 00b54144b7fb2f7a2504757c195376ea69d30baf878855007afb969f9c6bb372
|
|
4
|
+
data.tar.gz: 6f8f31cdf110ce9a2b16d632efe00ad888e1145d4dbbce739b885f74a618149a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c7262768b0db4a1ccee95e57f979813652860e2ccd3cbc7bde0d3d945216a36d0c6b0a539db5d790be05f0100f9f29713106c1e9acca41be0eebdf0d2d063871
|
|
7
|
+
data.tar.gz: 94c9a90d25ccf4da3008433c9fb45e001402415a060a26d9d9bb8833bae1a8c29a9303b99eccd26854b743d9680aa8dc7c466fc4b42bc28825dc4a9a4e85d365
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## 4.3.1
|
|
2
|
+
- Fix: generate error events with _snmpfailure tag when all SNMP operations fail and the response data is empty (e.g., timeout) [#92](https://github.com/logstash-plugins/logstash-integration-snmp/pull/92)
|
|
3
|
+
|
|
4
|
+
## 4.3.0
|
|
5
|
+
- Handle partial responses and errors gracefully: add `tag_on_failure` (default: `["_snmpfailure"]`) to tag events when SNMP operations fail, and `allow_partial_response` (default: `false`) to preserve partial data from failed `walk`/`table` operations [#91](https://github.com/logstash-plugins/logstash-integration-snmp/pull/91)
|
|
6
|
+
|
|
1
7
|
## 4.2.2
|
|
2
8
|
- Re-packaging the plugin [#86](https://github.com/logstash-plugins/logstash-integration-snmp/pull/86)
|
|
3
9
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.3.1
|
data/docs/input-snmp.asciidoc
CHANGED
|
@@ -75,6 +75,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
|
75
75
|
| <<plugins-{type}s-{plugin}-ecs_compatibility>> |<<string,string>>|No
|
|
76
76
|
| <<plugins-{type}s-{plugin}-get>> |<<array,array>>|No
|
|
77
77
|
| <<plugins-{type}s-{plugin}-hosts>> |<<array,array>>|No
|
|
78
|
+
| <<plugins-{type}s-{plugin}-allow_partial_response>> |<<boolean,boolean>>|No
|
|
78
79
|
| <<plugins-{type}s-{plugin}-interval>> |<<number,number>>|No
|
|
79
80
|
| <<plugins-{type}s-{plugin}-local_engine_id>> |<<string,string>>|No
|
|
80
81
|
| <<plugins-{type}s-{plugin}-mib_paths>> |<<path,path>>|No
|
|
@@ -83,6 +84,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
|
83
84
|
| <<plugins-{type}s-{plugin}-oid_path_length>> |<<number,number>>|No
|
|
84
85
|
| <<plugins-{type}s-{plugin}-oid_root_skip>> |<<number,number>>|No
|
|
85
86
|
| <<plugins-{type}s-{plugin}-poll_hosts_timeout>> |<<number,number>>|No
|
|
87
|
+
| <<plugins-{type}s-{plugin}-tag_on_failure>> |<<array,array>>|No
|
|
86
88
|
| <<plugins-{type}s-{plugin}-walk>> |<<array,array>>|No
|
|
87
89
|
| <<plugins-{type}s-{plugin}-tables>> |<<array,array>>|No
|
|
88
90
|
| <<plugins-{type}s-{plugin}-target>> |<<string,string>>|No
|
|
@@ -308,6 +310,7 @@ Queries the subtree of information starting at the given OID(s).
|
|
|
308
310
|
Example
|
|
309
311
|
[source,ruby]
|
|
310
312
|
-----
|
|
313
|
+
input {
|
|
311
314
|
snmp {
|
|
312
315
|
walk => ["1.3.6.1.2.1.1"]
|
|
313
316
|
hosts => [{host => "udp:127.0.0.1/161" community => "public"}]
|
|
@@ -315,6 +318,58 @@ Example
|
|
|
315
318
|
}
|
|
316
319
|
-----
|
|
317
320
|
|
|
321
|
+
[id="plugins-{type}s-{plugin}-allow_partial_response"]
|
|
322
|
+
===== `allow_partial_response`
|
|
323
|
+
|
|
324
|
+
* Value type is <<boolean,boolean>>
|
|
325
|
+
* Default value is `false`
|
|
326
|
+
|
|
327
|
+
When enabled, the event keeps data from partially failed `walk` or `table` operations. By default, it only includes data from fully successful operations.
|
|
328
|
+
|
|
329
|
+
When a `walk` or `table` traversal encounters an error mid-way through, the SNMP agent may have already returned
|
|
330
|
+
some valid data before the failure. With `allow_partial_response => true`, this data is included in the event.
|
|
331
|
+
The event will still be tagged with <<plugins-{type}s-{plugin}-tag_on_failure>> to indicate that an error occurred.
|
|
332
|
+
|
|
333
|
+
Example
|
|
334
|
+
[source,ruby]
|
|
335
|
+
-----
|
|
336
|
+
input {
|
|
337
|
+
snmp {
|
|
338
|
+
walk => ["1.3.6.1.2.1.2.2"]
|
|
339
|
+
hosts => [{host => "udp:127.0.0.1/161" community => "public"}]
|
|
340
|
+
allow_partial_response => true
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
-----
|
|
344
|
+
|
|
345
|
+
[id="plugins-{type}s-{plugin}-tag_on_failure"]
|
|
346
|
+
===== `tag_on_failure`
|
|
347
|
+
|
|
348
|
+
* Value type is <<array,array>>
|
|
349
|
+
* Default value is `["_snmpfailure"]`
|
|
350
|
+
|
|
351
|
+
Tags the event when one or more SNMP operations fail for a host.
|
|
352
|
+
This can happen due to timeouts, unreachable hosts, or errors during `get`, `walk`, or `table` operations.
|
|
353
|
+
Detailed error information is logged at ERROR level.
|
|
354
|
+
|
|
355
|
+
Example
|
|
356
|
+
[source,ruby]
|
|
357
|
+
-----
|
|
358
|
+
input {
|
|
359
|
+
snmp {
|
|
360
|
+
get => ["1.3.6.1.2.1.1.1.0"]
|
|
361
|
+
hosts => [{host => "udp:127.0.0.1/161" community => "public"}]
|
|
362
|
+
tag_on_failure => ["_snmpfailure"]
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
filter {
|
|
367
|
+
if "_snmpfailure" in [tags] {
|
|
368
|
+
# handle failed or partial SNMP responses
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
-----
|
|
372
|
+
|
|
318
373
|
[id="plugins-{type}s-{plugin}-tables"]
|
|
319
374
|
===== `tables`
|
|
320
375
|
|
data/lib/logstash/inputs/snmp.rb
CHANGED
|
@@ -67,6 +67,13 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
|
67
67
|
# Timeout in milliseconds to execute all hosts configured operations (get, walk, table).
|
|
68
68
|
config :poll_hosts_timeout, :validate => :number
|
|
69
69
|
|
|
70
|
+
# Append values to the `tags` field when one or more SNMP operations fail
|
|
71
|
+
config :tag_on_failure, :validate => :array, :default => ['_snmpfailure']
|
|
72
|
+
|
|
73
|
+
# When enabled, preserves partial data from failed walk/table operations in the event.
|
|
74
|
+
# When disabled, only data from fully successful operations is included.
|
|
75
|
+
config :allow_partial_response, :validate => :boolean, :default => false
|
|
76
|
+
|
|
70
77
|
def initialize(params={})
|
|
71
78
|
super(params)
|
|
72
79
|
|
|
@@ -161,7 +168,11 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
|
161
168
|
definition[:security_level]
|
|
162
169
|
)
|
|
163
170
|
|
|
164
|
-
|
|
171
|
+
if @allow_partial_response
|
|
172
|
+
request = @request_aggregator.create_request_for_partial_result(@client)
|
|
173
|
+
else
|
|
174
|
+
request = @request_aggregator.create_request_for_complete_result(@client)
|
|
175
|
+
end
|
|
165
176
|
in_flight_requests << { request: request, definition: definition }
|
|
166
177
|
|
|
167
178
|
if definition[:get].any?
|
|
@@ -182,14 +193,16 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
|
182
193
|
|
|
183
194
|
in_flight_requests.each do |req|
|
|
184
195
|
definition = req[:definition]
|
|
185
|
-
result_consumer = lambda do |
|
|
186
|
-
|
|
196
|
+
result_consumer = lambda do |request_result|
|
|
197
|
+
result = request_result.data
|
|
198
|
+
if result&.any? || request_result.has_errors
|
|
187
199
|
event = targeted_event_factory.new_event(result)
|
|
188
200
|
event.set(@host_protocol_field, definition[:host_protocol])
|
|
189
201
|
event.set(@host_address_field, definition[:host_address])
|
|
190
202
|
event.set(@host_port_field, definition[:host_port])
|
|
191
203
|
event.set(@host_community_field, definition[:host_community])
|
|
192
204
|
decorate(event)
|
|
205
|
+
@tag_on_failure.each { |tag| event.tag(tag) } if request_result.has_errors
|
|
193
206
|
queue << event
|
|
194
207
|
else
|
|
195
208
|
logger.debug? && logger.debug('No SNMP data retrieved', host: definition[:host_address])
|
|
@@ -4,4 +4,4 @@ require 'jar_dependencies'
|
|
|
4
4
|
require_jar('org.snmp4j', 'snmp4j-log4j', '2.8.11')
|
|
5
5
|
require_jar('org.snmp4j', 'snmp4j', '3.8.0')
|
|
6
6
|
require_jar('org.snakeyaml', 'snakeyaml-engine', '2.7')
|
|
7
|
-
require_jar('org.logstash.integrations', 'plugin', '4.
|
|
7
|
+
require_jar('org.logstash.integrations', 'plugin', '4.3.1')
|
|
@@ -4,6 +4,8 @@ require "logstash/devutils/rspec/spec_helper"
|
|
|
4
4
|
require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
|
|
5
5
|
require_relative '../../../lib/logstash/inputs/snmp'
|
|
6
6
|
|
|
7
|
+
java_import 'org.logstash.snmp.RequestResult'
|
|
8
|
+
|
|
7
9
|
describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
8
10
|
let(:mock_target) { double("org.snmp4j.Target") }
|
|
9
11
|
let(:mock_client) { double("org.logstash.snmp.SnmpClient") }
|
|
@@ -26,7 +28,8 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
26
28
|
expect(mock_client).to receive(:close)
|
|
27
29
|
|
|
28
30
|
allow(plugin).to receive(:create_request_aggregator).and_return(mock_aggregator)
|
|
29
|
-
|
|
31
|
+
allow(mock_aggregator).to receive(:create_request_for_complete_result).and_return(mock_aggregator_request)
|
|
32
|
+
allow(mock_aggregator).to receive(:create_request_for_partial_result).and_return(mock_aggregator_request)
|
|
30
33
|
expect(mock_aggregator).to receive(:await).and_return({})
|
|
31
34
|
expect(mock_aggregator).to receive(:close)
|
|
32
35
|
|
|
@@ -225,7 +228,8 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
225
228
|
allow(mock_client).to receive(:close).at_most(:once)
|
|
226
229
|
|
|
227
230
|
allow(plugin).to receive(:create_request_aggregator).and_return(mock_aggregator)
|
|
228
|
-
|
|
231
|
+
allow(mock_aggregator).to receive(:create_request_for_complete_result).and_return(mock_aggregator_request)
|
|
232
|
+
allow(mock_aggregator).to receive(:create_request_for_partial_result).and_return(mock_aggregator_request)
|
|
229
233
|
expect(mock_aggregator).to receive(:await)
|
|
230
234
|
allow(mock_aggregator).to receive(:close)
|
|
231
235
|
end
|
|
@@ -234,7 +238,7 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
234
238
|
before(:each) do
|
|
235
239
|
expect(mock_aggregator_request).to receive(:get)
|
|
236
240
|
expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
|
|
237
|
-
consumer.call({ 'foo' => 'bar' })
|
|
241
|
+
consumer.call(RequestResult.new({ 'foo' => 'bar' }, false))
|
|
238
242
|
end
|
|
239
243
|
end
|
|
240
244
|
|
|
@@ -262,6 +266,18 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
262
266
|
end
|
|
263
267
|
end
|
|
264
268
|
|
|
269
|
+
context 'should not tag event when no errors' do
|
|
270
|
+
let(:config) { super().merge({ 'get' => ["1.3.6.1.2.1.1.1.0"], 'hosts' => [{ 'host' => "udp:127.0.0.1/161" }] }) }
|
|
271
|
+
|
|
272
|
+
it "does not add tags" do
|
|
273
|
+
plugin.register
|
|
274
|
+
plugin.run(queue)
|
|
275
|
+
event = queue.pop
|
|
276
|
+
|
|
277
|
+
expect(event.get("tags")).to be_nil
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
265
281
|
context 'with custom host field (legacy metadata)' do
|
|
266
282
|
let(:config) do
|
|
267
283
|
super().merge({
|
|
@@ -318,6 +334,86 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
318
334
|
end
|
|
319
335
|
end
|
|
320
336
|
|
|
337
|
+
context 'mocked result with errors' do
|
|
338
|
+
let(:config) do
|
|
339
|
+
super().merge({
|
|
340
|
+
'get' => ['1.3.6.1.2.1.1.1.0'],
|
|
341
|
+
'hosts' => [{ 'host' => 'udp:127.0.0.1/161', 'community' => 'public' }]
|
|
342
|
+
})
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
context 'when result data is not empty' do
|
|
346
|
+
before(:each) do
|
|
347
|
+
expect(mock_aggregator_request).to receive(:get)
|
|
348
|
+
expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
|
|
349
|
+
consumer.call(RequestResult.new({ 'foo' => 'bar' }, true))
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it 'should tag event with default failure tag' do
|
|
354
|
+
plugin.register
|
|
355
|
+
plugin.poll_clients(queue)
|
|
356
|
+
event = queue.pop
|
|
357
|
+
|
|
358
|
+
expect(event.get("foo")).to eq("bar")
|
|
359
|
+
expect(event.get("tags")).to include("_snmpfailure")
|
|
360
|
+
expect(event.get("_snmp_request_errors")).to be_nil
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
context 'when result data is empty' do
|
|
365
|
+
before(:each) do
|
|
366
|
+
expect(mock_aggregator_request).to receive(:get)
|
|
367
|
+
expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
|
|
368
|
+
consumer.call(RequestResult.new({}, true))
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it 'should generate an event with failure tag when all operations fail' do
|
|
373
|
+
plugin.register
|
|
374
|
+
plugin.poll_clients(queue)
|
|
375
|
+
event = queue.pop
|
|
376
|
+
|
|
377
|
+
expect(event).not_to be_nil
|
|
378
|
+
expect(event.get("tags")).to include("_snmpfailure")
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
context 'allow_partial_response option' do
|
|
384
|
+
let(:config) do
|
|
385
|
+
super().merge({
|
|
386
|
+
'get' => ['1.3.6.1.2.1.1.1.0'],
|
|
387
|
+
'hosts' => [{ 'host' => 'udp:127.0.0.1/161', 'community' => 'public' }]
|
|
388
|
+
})
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
before(:each) do
|
|
392
|
+
allow(mock_aggregator_request).to receive(:get)
|
|
393
|
+
allow(mock_aggregator_request).to receive(:get_result_async)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
context 'when set to false (default)' do
|
|
397
|
+
let(:config) { super().merge('allow_partial_response' => false) }
|
|
398
|
+
|
|
399
|
+
it 'uses complete result aggregator' do
|
|
400
|
+
expect(mock_aggregator).to receive(:create_request_for_complete_result).and_return(mock_aggregator_request)
|
|
401
|
+
plugin.register
|
|
402
|
+
plugin.poll_clients(queue)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
context 'when set to true' do
|
|
407
|
+
let(:config) { super().merge('allow_partial_response' => true) }
|
|
408
|
+
|
|
409
|
+
it 'uses partial result aggregator' do
|
|
410
|
+
expect(mock_aggregator).to receive(:create_request_for_partial_result).and_return(mock_aggregator_request)
|
|
411
|
+
plugin.register
|
|
412
|
+
plugin.poll_clients(queue)
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
321
417
|
context 'mocked empty request result' do
|
|
322
418
|
let(:config) do
|
|
323
419
|
super().merge({
|
|
@@ -331,7 +427,7 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
331
427
|
before(:each) do
|
|
332
428
|
expect(mock_aggregator_request).to receive(:get)
|
|
333
429
|
expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
|
|
334
|
-
consumer.call({})
|
|
430
|
+
consumer.call(RequestResult.new({}, false))
|
|
335
431
|
end
|
|
336
432
|
|
|
337
433
|
allow(plugin).to receive(:logger).and_return(logger)
|
|
@@ -482,7 +578,8 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
|
482
578
|
expect(mock_aggregator).to receive(:await)
|
|
483
579
|
allow(mock_aggregator).to receive(:close)
|
|
484
580
|
|
|
485
|
-
|
|
581
|
+
allow(mock_aggregator).to receive(:create_request_for_complete_result).and_return(mock_aggregator_request)
|
|
582
|
+
allow(mock_aggregator).to receive(:create_request_for_partial_result).and_return(mock_aggregator_request)
|
|
486
583
|
expect(mock_aggregator_request).to receive(:get)
|
|
487
584
|
expect(mock_aggregator_request).to receive(:get_result_async)
|
|
488
585
|
end
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: logstash-integration-snmp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.3.1
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Elastic
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-05-20 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: logstash-core-plugin-api
|
|
@@ -468,7 +468,7 @@ files:
|
|
|
468
468
|
- spec/unit/inputs/common_spec.rb
|
|
469
469
|
- spec/unit/inputs/snmp_spec.rb
|
|
470
470
|
- spec/unit/inputs/snmptrap_spec.rb
|
|
471
|
-
- vendor/jar-dependencies/org/logstash/integrations/plugin/4.
|
|
471
|
+
- vendor/jar-dependencies/org/logstash/integrations/plugin/4.3.1/plugin-4.3.1.jar
|
|
472
472
|
- vendor/jar-dependencies/org/snakeyaml/snakeyaml-engine/2.7/snakeyaml-engine-2.7.jar
|
|
473
473
|
- vendor/jar-dependencies/org/snmp4j/snmp4j-log4j/2.8.11/snmp4j-log4j-2.8.11.jar
|
|
474
474
|
- vendor/jar-dependencies/org/snmp4j/snmp4j/3.8.0/snmp4j-3.8.0.jar
|