logstash-input-snmp 1.2.7 → 1.2.8
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 +3 -0
- data/docs/index.asciidoc +1 -0
- data/lib/logstash/inputs/snmp.rb +50 -4
- data/logstash-input-snmp.gemspec +1 -1
- data/spec/inputs/integration/it_spec.rb +6 -6
- data/spec/inputs/snmp/interval_runner_spec.rb +0 -0
- data/spec/inputs/snmp_spec.rb +90 -0
- data/vendor/jar-dependencies/org/snmp4j/snmp4j/2.5.11/snmp4j-2.5.11.jar +0 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bcb5f73151249317b6f7b36c028a3f863e7d4a88ba6da977fbc88d255355364
|
4
|
+
data.tar.gz: 85ef765af5f93aefb92a8f40d9738101ada3b5173bb9b4b8de3d4ec21a406578
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 423f10e23a58b04a72c47d70beb06053dedc8d07e1ec1e36c835ca783c6791bb6ccd12d701d3e50bd4ebe173185a4240ae21a93c36d7ecdf38bf4e2ae6d58f25
|
7
|
+
data.tar.gz: f452759e6c453d088b002721ae1520b1c22291e16ff609d8f308e57c3e9aa9dc29b008c809a9a6a76e76b00e68c0399fc96b63f23dc066aa403a682f19712f2e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
## 1.2.8
|
2
|
+
- Fixed interval handling to only sleep off the _remainder_ of the interval (if any), and to log a helpful warning when crawling the hosts takes longer than the configured interval [#61](https://github.com/logstash-plugins/logstash-input-snmp/issues/61)
|
3
|
+
|
1
4
|
## 1.2.7
|
2
5
|
- Added integration tests to ensure SNMP server and IPv6 connections [#87](https://github.com/logstash-plugins/logstash-input-snmp/pull/87)
|
3
6
|
|
data/docs/index.asciidoc
CHANGED
@@ -163,6 +163,7 @@ input {
|
|
163
163
|
===== `interval`
|
164
164
|
|
165
165
|
The `interval` option specifies the polling interval in seconds.
|
166
|
+
If polling all configured hosts takes longer than this interval, a warning will be emitted to the logs.
|
166
167
|
|
167
168
|
* Value type is <<number,number>>
|
168
169
|
* Default value is `30`
|
data/lib/logstash/inputs/snmp.rb
CHANGED
@@ -161,9 +161,9 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
161
161
|
end
|
162
162
|
|
163
163
|
def run(queue)
|
164
|
-
# for now a naive single threaded poller which sleeps
|
164
|
+
# for now a naive single threaded poller which sleeps off the remaining interval between
|
165
165
|
# each run. each run polls all the defined hosts for the get and walk options.
|
166
|
-
|
166
|
+
stoppable_interval_runner.every(@interval, "polling hosts") do
|
167
167
|
@client_definitions.each do |definition|
|
168
168
|
result = {}
|
169
169
|
if !definition[:get].empty?
|
@@ -207,11 +207,13 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
207
207
|
queue << event
|
208
208
|
end
|
209
209
|
end
|
210
|
-
|
211
|
-
Stud.stoppable_sleep(@interval) { stop? }
|
212
210
|
end
|
213
211
|
end
|
214
212
|
|
213
|
+
def stoppable_interval_runner
|
214
|
+
StoppableIntervalRunner.new(self)
|
215
|
+
end
|
216
|
+
|
215
217
|
def close
|
216
218
|
@client_definitions.each do |definition|
|
217
219
|
begin
|
@@ -222,6 +224,9 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
222
224
|
end
|
223
225
|
end
|
224
226
|
|
227
|
+
def stop
|
228
|
+
end
|
229
|
+
|
225
230
|
private
|
226
231
|
|
227
232
|
OID_REGEX = /^\.?([0-9\.]+)$/
|
@@ -295,4 +300,45 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
295
300
|
def validate_strip!
|
296
301
|
raise(LogStash::ConfigurationError, "you can not specify both oid_root_skip and oid_path_length") if @oid_root_skip > 0 and @oid_path_length > 0
|
297
302
|
end
|
303
|
+
|
304
|
+
##
|
305
|
+
# The StoppableIntervalRunner is capable of running a block of code at a
|
306
|
+
# repeating interval, while respecting the stop condition of the plugin.
|
307
|
+
class StoppableIntervalRunner
|
308
|
+
##
|
309
|
+
# @param plugin [#logger,#stop?]
|
310
|
+
def initialize(plugin)
|
311
|
+
@plugin = plugin
|
312
|
+
end
|
313
|
+
|
314
|
+
##
|
315
|
+
# Runs the provided block repeatedly using the provided interval.
|
316
|
+
# After executing the block, the remainder of the interval if any is slept off
|
317
|
+
# using an interruptible sleep.
|
318
|
+
# If no time remains, a warning is emitted to the logs.
|
319
|
+
#
|
320
|
+
# @param interval_seconds [Integer,Float]
|
321
|
+
# @param desc [String] (default: "operation"): a description to use when logging
|
322
|
+
# @yield
|
323
|
+
def every(interval_seconds, desc="operation", &block)
|
324
|
+
until @plugin.stop?
|
325
|
+
start_time = Time.now
|
326
|
+
|
327
|
+
yield
|
328
|
+
|
329
|
+
duration_seconds = Time.now - start_time
|
330
|
+
if duration_seconds >= interval_seconds
|
331
|
+
@plugin.logger.warn("#{desc} took longer than the configured interval", :interval_seconds => interval_seconds, :duration_seconds => duration_seconds.round(3))
|
332
|
+
else
|
333
|
+
remaining_interval = interval_seconds - duration_seconds
|
334
|
+
sleep(remaining_interval)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# @api private
|
340
|
+
def sleep(duration)
|
341
|
+
Stud.stoppable_sleep(duration) { @plugin.stop? }
|
342
|
+
end
|
343
|
+
end
|
298
344
|
end
|
data/logstash-input-snmp.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-input-snmp'
|
3
|
-
s.version = '1.2.
|
3
|
+
s.version = '1.2.8'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "SNMP input plugin"
|
6
6
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
@@ -44,12 +44,12 @@ describe LogStash::Inputs::Snmp do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "against single snmp server with snmpv2 and udp", :integration => true do
|
47
|
-
let(:config) { super.merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}]})}
|
47
|
+
let(:config) { super().merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}]})}
|
48
48
|
it_behaves_like "snmp plugin return single event"
|
49
49
|
end
|
50
50
|
|
51
51
|
describe "against single server with snmpv3 and tcp", :integration => true do
|
52
|
-
let(:config) { super.merge({
|
52
|
+
let(:config) { super().merge({
|
53
53
|
"hosts" => [{"host" => "tcp:snmp1/161", "version" => "3"}],
|
54
54
|
"security_name" => "user_1",
|
55
55
|
"auth_protocol" => "sha",
|
@@ -63,7 +63,7 @@ describe LogStash::Inputs::Snmp do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
describe "invalid user against snmpv3 server", :integration => true do
|
66
|
-
let(:config) { super.merge({
|
66
|
+
let(:config) { super().merge({
|
67
67
|
"hosts" => [{"host" => "tcp:snmp1/161", "version" => "3"}],
|
68
68
|
"security_name" => "user_2",
|
69
69
|
"auth_protocol" => "sha",
|
@@ -84,7 +84,7 @@ describe LogStash::Inputs::Snmp do
|
|
84
84
|
end
|
85
85
|
|
86
86
|
describe "single input plugin on single server with snmpv2 and mix of udp and tcp", :integration => true do
|
87
|
-
let(:config) { super.merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}, {"host" => "tcp:snmp1/161", "community" => "public"}]})}
|
87
|
+
let(:config) { super().merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}, {"host" => "tcp:snmp1/161", "community" => "public"}]})}
|
88
88
|
it "should return two events " do
|
89
89
|
plugin.register
|
90
90
|
queue = []
|
@@ -99,7 +99,7 @@ describe LogStash::Inputs::Snmp do
|
|
99
99
|
end
|
100
100
|
|
101
101
|
describe "single input plugin on multiple udp hosts", :integration => true do
|
102
|
-
let(:config) { super.merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}, {"host" => "udp:snmp2/162", "community" => "public"}]})}
|
102
|
+
let(:config) { super().merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}, {"host" => "udp:snmp2/162", "community" => "public"}]})}
|
103
103
|
it "should return two events, one per host" do
|
104
104
|
plugin.register
|
105
105
|
queue = []
|
@@ -189,7 +189,7 @@ describe LogStash::Inputs::Snmp do
|
|
189
189
|
end
|
190
190
|
|
191
191
|
describe "single host with tcp over ipv6", :integration => true do
|
192
|
-
let(:config) { super.merge({"hosts" => [{"host" => "tcp:[2001:3984:3989::161]/161"}]})}
|
192
|
+
let(:config) { super().merge({"hosts" => [{"host" => "tcp:[2001:3984:3989::161]/161"}]})}
|
193
193
|
it_behaves_like "snmp plugin return single event"
|
194
194
|
end
|
195
195
|
|
File without changes
|
data/spec/inputs/snmp_spec.rb
CHANGED
@@ -171,5 +171,95 @@ describe LogStash::Inputs::Snmp do
|
|
171
171
|
expect(event.get("host")).to eq("udp:127.0.0.1/161,public")
|
172
172
|
end
|
173
173
|
end
|
174
|
+
|
175
|
+
context "StoppableIntervalRunner" do
|
176
|
+
let(:stop_holder) { Struct.new(:value).new(false) }
|
177
|
+
|
178
|
+
before(:each) do
|
179
|
+
allow(plugin).to receive(:stop?) { stop_holder.value }
|
180
|
+
end
|
181
|
+
|
182
|
+
let(:plugin) do
|
183
|
+
double("Plugin").tap do |dbl|
|
184
|
+
allow(dbl).to receive(:logger).and_return(double("Logger").as_null_object)
|
185
|
+
allow(dbl).to receive(:stop?) { stop_holder.value }
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
subject(:interval_runner) { LogStash::Inputs::Snmp::StoppableIntervalRunner.new(plugin) }
|
190
|
+
|
191
|
+
context "#every" do
|
192
|
+
context "when the plugin is stopped" do
|
193
|
+
let(:interval_seconds) { 2 }
|
194
|
+
it 'does not yield the block' do
|
195
|
+
stop_holder.value = true
|
196
|
+
expect { |yielder| interval_runner.every(interval_seconds, &yielder) }.to_not yield_control
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context "when the yield takes shorter than the interval" do
|
201
|
+
let(:duration_seconds) { 1 }
|
202
|
+
let(:interval_seconds) { 2 }
|
203
|
+
|
204
|
+
it 'sleeps off the remainder' do
|
205
|
+
allow(interval_runner).to receive(:sleep).and_call_original
|
206
|
+
|
207
|
+
interval_runner.every(interval_seconds) do
|
208
|
+
Kernel::sleep(duration_seconds) # non-stoppable
|
209
|
+
stop_holder.value = true # prevent re-runs
|
210
|
+
end
|
211
|
+
|
212
|
+
expect(interval_runner).to have_received(:sleep).with(a_value_within(0.1).of(1))
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "when the yield takes longer than the interval" do
|
217
|
+
let(:duration_seconds) { 2 }
|
218
|
+
let(:interval_seconds) { 1 }
|
219
|
+
|
220
|
+
it 'logs a warning to the plugin' do
|
221
|
+
allow(interval_runner).to receive(:sleep).and_call_original
|
222
|
+
|
223
|
+
interval_runner.every(interval_seconds) do
|
224
|
+
Kernel::sleep(duration_seconds) # non-stoppable
|
225
|
+
stop_holder.value = true # prevent re-runs
|
226
|
+
end
|
227
|
+
|
228
|
+
expect(interval_runner).to_not have_received(:sleep)
|
229
|
+
|
230
|
+
expect(plugin.logger).to have_received(:warn).with(a_string_including("took longer"), a_hash_including(:interval_seconds => interval_seconds, :duration_seconds => a_value_within(0.1).of(duration_seconds)))
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'runs regularly until the plugin is stopped' do
|
235
|
+
timestamps = []
|
236
|
+
|
237
|
+
thread = Thread.new do
|
238
|
+
interval_runner.every(1) do
|
239
|
+
timestamps << Time.now
|
240
|
+
Kernel::sleep(Random::rand(0.8))
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
Kernel::sleep(5)
|
245
|
+
expect(thread).to be_alive
|
246
|
+
|
247
|
+
stop_holder.value = true
|
248
|
+
Kernel::sleep(1)
|
249
|
+
|
250
|
+
aggregate_failures do
|
251
|
+
expect(thread).to_not be_alive
|
252
|
+
expect(timestamps.count).to be_within(1).of(5)
|
253
|
+
|
254
|
+
timestamps.each_cons(2) do |previous, current|
|
255
|
+
# ensure each start time is very close to 1s after the previous.
|
256
|
+
expect(current - previous).to be_within(0.05).of(1)
|
257
|
+
end
|
258
|
+
|
259
|
+
thread.kill if thread.alive?
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
174
264
|
end
|
175
265
|
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-snmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elasticsearch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -416,8 +416,10 @@ files:
|
|
416
416
|
- spec/fixtures/collision.dic
|
417
417
|
- spec/inputs/integration/it_spec.rb
|
418
418
|
- spec/inputs/snmp/base_client_spec.rb
|
419
|
+
- spec/inputs/snmp/interval_runner_spec.rb
|
419
420
|
- spec/inputs/snmp/mib_spec.rb
|
420
421
|
- spec/inputs/snmp_spec.rb
|
422
|
+
- vendor/jar-dependencies/org/snmp4j/snmp4j/2.5.11/snmp4j-2.5.11.jar
|
421
423
|
- vendor/jar-dependencies/org/snmp4j/snmp4j/2.8.4/snmp4j-2.8.4.jar
|
422
424
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
423
425
|
licenses:
|
@@ -441,8 +443,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
441
443
|
- !ruby/object:Gem::Version
|
442
444
|
version: '0'
|
443
445
|
requirements: []
|
444
|
-
|
445
|
-
rubygems_version: 2.6.13
|
446
|
+
rubygems_version: 3.1.6
|
446
447
|
signing_key:
|
447
448
|
specification_version: 4
|
448
449
|
summary: SNMP input plugin
|
@@ -451,5 +452,6 @@ test_files:
|
|
451
452
|
- spec/fixtures/collision.dic
|
452
453
|
- spec/inputs/integration/it_spec.rb
|
453
454
|
- spec/inputs/snmp/base_client_spec.rb
|
455
|
+
- spec/inputs/snmp/interval_runner_spec.rb
|
454
456
|
- spec/inputs/snmp/mib_spec.rb
|
455
457
|
- spec/inputs/snmp_spec.rb
|