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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d3ed1e4918623aa0ae361f25307932f551fd20c43ccf0b1129ef92323ba68d2
4
- data.tar.gz: ef6b85b7c9e9006cec7c946da939efe36de89d367cf764c0adac47740adf469f
3
+ metadata.gz: 00b54144b7fb2f7a2504757c195376ea69d30baf878855007afb969f9c6bb372
4
+ data.tar.gz: 6f8f31cdf110ce9a2b16d632efe00ad888e1145d4dbbce739b885f74a618149a
5
5
  SHA512:
6
- metadata.gz: fa65ee4ee74ace48959365b6d34d7e44bc749be894a5e3112a426382e8f1221aafbe611a57b1573ebcf6268d9db63a29cda7bd8c4b551cc07bf6b9b00ef72a1e
7
- data.tar.gz: 8210d1dfe26f75ffd0532e4be42f6bcdac4b8ff83c28c40da5d669b8a8e8f6ac217f87e51bce2018454a0c14b33f8be28bc38665914aaf38e09554a6f55b2793
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.2.2
1
+ 4.3.1
@@ -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
 
@@ -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
- request = @request_aggregator.create_request(@client)
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 |result|
186
- if result&.any?
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.2.2')
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
- expect(mock_aggregator).to receive(:create_request).and_return(mock_aggregator_request)
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
- expect(mock_aggregator).to receive(:create_request).and_return(mock_aggregator_request)
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
- expect(mock_aggregator).to receive(:create_request).and_return(mock_aggregator_request)
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
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.2.2
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-01-31 00:00:00.000000000 Z
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.2.2/plugin-4.2.2.jar
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