logstash-integration-snmp 4.2.1-java → 4.3.0-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: cecd93452a9a34d8ad060c721c7ea1b9106dbecdeabb090c568becc03b9bec4f
4
- data.tar.gz: 725f8aa1e8a320185ddcefbbb8958bc162af759f01336e4403850c7d7f666cc3
3
+ metadata.gz: 83e4f7e4d6dbba653ef3de8662d2d8d0c78fa5b690482d39a276061ac9c6889c
4
+ data.tar.gz: 4454382e046d542df2f34aadc5d41586f5c9e813fe560782e10f7ef42212a4ec
5
5
  SHA512:
6
- metadata.gz: de59aff428d4f345b09eb69e21b94ee00e905ab9ebddb32956e99f953aaefa5ce80c004e4824bbc511543af2cd9236cbfa799c9ea490cadb7e073fb6253a408a
7
- data.tar.gz: 203c22dc767aefa06ed42bdaa835f5d9e64f376ed95bc7d92652d77ead2e7d0b61b1cf2eeca2efcc00544a61189b13503bca86668bae0494199717f4a181b476
6
+ metadata.gz: 2dcc0cc28a4fad102391877207ff623c49851de0539123e9b9b58fb76449714cb31e655628c63c535089a6c26961be7cf33eb508aa9c80a4214b99a7524bb89f
7
+ data.tar.gz: a077b38b4357d6882a181ea95df1a87b205e284f7903d8f3b342b7a383b17e5c596a0e060ed9feeba37404f536de436c86d2597e7d7f33faed6217a632e8ca4e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 4.3.0
2
+ - 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)
3
+
4
+ ## 4.2.2
5
+ - Re-packaging the plugin [#86](https://github.com/logstash-plugins/logstash-integration-snmp/pull/86)
6
+
1
7
  ## 4.2.1
2
8
  - Upgrade log4j dependency [#85](https://github.com/logstash-plugins/logstash-integration-snmp/pull/85)
3
9
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.2.1
1
+ 4.3.0
@@ -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,7 +193,8 @@ 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|
196
+ result_consumer = lambda do |request_result|
197
+ result = request_result.data
186
198
  if result&.any?
187
199
  event = targeted_event_factory.new_event(result)
188
200
  event.set(@host_protocol_field, definition[:host_protocol])
@@ -190,6 +202,7 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
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])
@@ -1,7 +1,7 @@
1
1
  # AUTOGENERATED BY THE GRADLE SCRIPT. DO NOT EDIT.
2
2
 
3
3
  require 'jar_dependencies'
4
- require_jar('org.snmp4j', 'snmp4j', '3.8.0')
5
4
  require_jar('org.snmp4j', 'snmp4j-log4j', '2.8.11')
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.1')
7
+ require_jar('org.logstash.integrations', 'plugin', '4.3.0')
@@ -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,75 @@ 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
+ before(:each) do
346
+ expect(mock_aggregator_request).to receive(:get)
347
+ expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
348
+ consumer.call(RequestResult.new({ 'foo' => 'bar' }, true))
349
+ end
350
+ end
351
+
352
+ it 'should tag event with default failure tag' do
353
+ plugin.register
354
+ plugin.poll_clients(queue)
355
+ event = queue.pop
356
+
357
+ expect(event.get("foo")).to eq("bar")
358
+ expect(event.get("tags")).to include("_snmpfailure")
359
+ expect(event.get("_snmp_request_errors")).to be_nil
360
+ end
361
+ end
362
+
363
+ context 'allow_partial_response option' do
364
+ let(:config) do
365
+ super().merge({
366
+ 'get' => ['1.3.6.1.2.1.1.1.0'],
367
+ 'hosts' => [{ 'host' => 'udp:127.0.0.1/161', 'community' => 'public' }],
368
+ 'allow_partial_response' => allow_partial_response_value
369
+ })
370
+ end
371
+
372
+ before(:each) do
373
+ expect(mock_aggregator_request).to receive(:get)
374
+ expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
375
+ consumer.call(RequestResult.new({ 'partial' => 'data' }, true))
376
+ end
377
+ end
378
+
379
+ context 'when set to false (default)' do
380
+ let(:allow_partial_response_value) { false }
381
+
382
+ it 'tags event and preserves data from successful operations' do
383
+ plugin.register
384
+ plugin.poll_clients(queue)
385
+ event = queue.pop
386
+
387
+ expect(event.get("partial")).to eq("data")
388
+ expect(event.get("tags")).to include("_snmpfailure")
389
+ end
390
+ end
391
+
392
+ context 'when set to true' do
393
+ let(:allow_partial_response_value) { true }
394
+
395
+ it 'tags event and preserves data including partial results' do
396
+ plugin.register
397
+ plugin.poll_clients(queue)
398
+ event = queue.pop
399
+
400
+ expect(event.get("partial")).to eq("data")
401
+ expect(event.get("tags")).to include("_snmpfailure")
402
+ end
403
+ end
404
+ end
405
+
321
406
  context 'mocked empty request result' do
322
407
  let(:config) do
323
408
  super().merge({
@@ -331,7 +416,7 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
331
416
  before(:each) do
332
417
  expect(mock_aggregator_request).to receive(:get)
333
418
  expect(mock_aggregator_request).to receive(:get_result_async) do |consumer|
334
- consumer.call({})
419
+ consumer.call(RequestResult.new({}, false))
335
420
  end
336
421
 
337
422
  allow(plugin).to receive(:logger).and_return(logger)
@@ -482,7 +567,8 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
482
567
  expect(mock_aggregator).to receive(:await)
483
568
  allow(mock_aggregator).to receive(:close)
484
569
 
485
- expect(mock_aggregator).to receive(:create_request).and_return(mock_aggregator_request)
570
+ allow(mock_aggregator).to receive(:create_request_for_complete_result).and_return(mock_aggregator_request)
571
+ allow(mock_aggregator).to receive(:create_request_for_partial_result).and_return(mock_aggregator_request)
486
572
  expect(mock_aggregator_request).to receive(:get)
487
573
  expect(mock_aggregator_request).to receive(:get_result_async)
488
574
  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.1
4
+ version: 4.3.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-01-16 00:00:00.000000000 Z
10
+ date: 2026-05-19 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.1/plugin-4.2.1.jar
471
+ - vendor/jar-dependencies/org/logstash/integrations/plugin/4.3.0/plugin-4.3.0.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