logstash-input-http_poller 3.0.3 → 3.1.0
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 +11 -2
- data/lib/logstash/inputs/http_poller.rb +58 -7
- data/logstash-input-http_poller.gemspec +3 -1
- data/spec/inputs/http_poller_spec.rb +172 -6
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe8e760b955fa42eefe9e32efb1d22a45a5df599
|
4
|
+
data.tar.gz: 78892043c7636c6ae2390f0a0434049f2c0746a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 981963c7a77ca4ee065efea7dce6cfcef8764e58cca1c168275da196bf9f8255ec34af2ad52fc9051d019faf7820628fb41c37744ee492107f46e9f20f818ae8
|
7
|
+
data.tar.gz: f1db89d4d1a1a44dd750c0348e95b95875844af1a815efb4f9f8bb8e56084d45aa119cd433fb83f0ab775df8e54313783dac51d0997d7c8a6ec1a6f544362fb4
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,24 @@
|
|
1
|
+
## 3.1.0
|
2
|
+
- Use rufus-scheduler for more flexible scheduling. Many thanks to [@hummingV](https://github.com/hummingV) for this contribution. ([#58](https://github.com/logstash-plugins/logstash-input-http_poller/pull/58))
|
3
|
+
|
1
4
|
## 3.0.3
|
2
5
|
- Require logstash-mixin-http_client 4.0.3 which fixes error messaging around key/trust-stores when no password supplied
|
6
|
+
|
3
7
|
## 3.0.2
|
4
8
|
- Relax constraint on logstash-core-plugin-api to >= 1.60 <= 2.99
|
9
|
+
|
5
10
|
## 3.0.1
|
6
11
|
- Republish all the gems under jruby.
|
12
|
+
|
7
13
|
## 3.0.0
|
8
14
|
- Update the plugin to the version 2.0 of the plugin api, this change is required for Logstash 5.0 compatibility. See https://github.com/elastic/logstash/issues/5141
|
9
|
-
|
15
|
+
|
16
|
+
## 2.0.5
|
10
17
|
- Depend on logstash-core-plugin-api instead of logstash-core, removing the need to mass update plugins on major releases of logstash
|
11
|
-
|
18
|
+
|
19
|
+
## 2.0.4
|
12
20
|
- New dependency requirements for logstash-core for the 5.0 release
|
21
|
+
|
13
22
|
## 2.0.2
|
14
23
|
- Bump http_client mixin to use better stale check for keepalives
|
15
24
|
|
@@ -4,6 +4,7 @@ require "logstash/namespace"
|
|
4
4
|
require "logstash/plugin_mixins/http_client"
|
5
5
|
require "socket" # for Socket.gethostname
|
6
6
|
require "manticore"
|
7
|
+
require "rufus/scheduler"
|
7
8
|
|
8
9
|
# This Logstash input plugin allows you to call an HTTP API, decode the output of it into event(s), and
|
9
10
|
# send them on their merry way. The idea behind this plugins came from a need to read springboot
|
@@ -33,7 +34,8 @@ require "manticore"
|
|
33
34
|
# }
|
34
35
|
# }
|
35
36
|
# request_timeout => 60
|
36
|
-
#
|
37
|
+
# # Supports "cron", "every", "at" and "in" schedules by rufus scheduler
|
38
|
+
# schedule => { cron => "* * * * * UTC"}
|
37
39
|
# codec => "json"
|
38
40
|
# # A hash of request metadata info (timing, response headers, etc.) will be sent here
|
39
41
|
# metadata_target => "http_poller_metadata"
|
@@ -51,9 +53,10 @@ require "manticore"
|
|
51
53
|
#
|
52
54
|
# If you have a self signed cert you will need to convert your server's certificate to a valid# `.jks` or `.p12` file. An easy way to do it is to run the following one-liner, substituting your server's URL for the placeholder `MYURL` and `MYPORT`.
|
53
55
|
#
|
54
|
-
|
56
|
+
# [source,ruby]
|
57
|
+
# ----------------------------------
|
55
58
|
# openssl s_client -showcerts -connect MYURL:MYPORT </dev/null 2>/dev/null|openssl x509 -outform PEM > downloaded_cert.pem; keytool -import -alias test -file downloaded_cert.pem -keystore downloaded_truststore.jks
|
56
|
-
|
59
|
+
# ----------------------------------
|
57
60
|
#
|
58
61
|
# The above snippet will create two files `downloaded_cert.pem` and `downloaded_truststore.jks`. You will be prompted to set a password for the `jks` file during this process. To configure logstash use a config like the one that follows.
|
59
62
|
#
|
@@ -70,9 +73,9 @@ require "manticore"
|
|
70
73
|
# interval => 30
|
71
74
|
# }
|
72
75
|
#}
|
76
|
+
# ----------------------------------
|
73
77
|
#
|
74
78
|
|
75
|
-
|
76
79
|
class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
|
77
80
|
include LogStash::PluginMixins::HttpClient
|
78
81
|
|
@@ -85,7 +88,20 @@ class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
|
|
85
88
|
config :urls, :validate => :hash, :required => true
|
86
89
|
|
87
90
|
# How often (in seconds) the urls will be called
|
88
|
-
|
91
|
+
# DEPRECATED. Use 'schedule' option instead.
|
92
|
+
# If both interval and schedule options are specified, interval
|
93
|
+
# option takes higher precedence
|
94
|
+
config :interval, :validate => :number, :deprecated => true
|
95
|
+
|
96
|
+
# Schedule of when to periodically poll from the urls
|
97
|
+
# Format: A hash with
|
98
|
+
# + key: "cron" | "every" | "in" | "at"
|
99
|
+
# + value: string
|
100
|
+
# Examples:
|
101
|
+
# a) { "every" => "1h" }
|
102
|
+
# b) { "cron" => "* * * * * UTC" }
|
103
|
+
# See: rufus/scheduler for details about different schedule options and value string format
|
104
|
+
config :schedule, :validate => :hash
|
89
105
|
|
90
106
|
# Define the target field for placing the received data. If this setting is omitted, the data will be stored at the root (top level) of the event.
|
91
107
|
config :target, :validate => :string
|
@@ -96,17 +112,19 @@ class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
|
|
96
112
|
config :metadata_target, :validate => :string, :default => '@metadata'
|
97
113
|
|
98
114
|
public
|
115
|
+
Schedule_types = %w(cron every at in)
|
99
116
|
def register
|
100
117
|
@host = Socket.gethostname.force_encoding(Encoding::UTF_8)
|
101
118
|
|
102
119
|
@logger.info("Registering http_poller Input", :type => @type,
|
103
|
-
:urls => @urls, :interval => @interval, :timeout => @timeout)
|
120
|
+
:urls => @urls, :interval => @interval, :schedule => @schedule, :timeout => @timeout)
|
104
121
|
|
105
122
|
setup_requests!
|
106
123
|
end
|
107
124
|
|
108
125
|
def stop
|
109
126
|
Stud.stop!(@interval_thread) if @interval_thread
|
127
|
+
@scheduler.stop if @scheduler
|
110
128
|
end
|
111
129
|
|
112
130
|
private
|
@@ -159,13 +177,46 @@ class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
|
|
159
177
|
|
160
178
|
public
|
161
179
|
def run(queue)
|
180
|
+
#interval or schedule must be provided. Must be exclusively either one. Not neither. Not both.
|
181
|
+
raise LogStash::ConfigurationError, "Invalid config. Neither interval nor schedule was specified." \
|
182
|
+
unless @interval || @schedule
|
183
|
+
raise LogStash::ConfigurationError, "Invalid config. Specify only interval or schedule. Not both." \
|
184
|
+
if @interval && @schedule
|
185
|
+
|
186
|
+
if @interval
|
187
|
+
setup_interval(queue)
|
188
|
+
elsif @schedule
|
189
|
+
setup_schedule(queue)
|
190
|
+
else
|
191
|
+
#should not reach here
|
192
|
+
raise LogStash::ConfigurationError, "Invalid config. Neither interval nor schedule was specified."
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
def setup_interval(queue)
|
162
198
|
@interval_thread = Thread.current
|
163
199
|
Stud.interval(@interval) do
|
164
200
|
run_once(queue)
|
165
201
|
end
|
166
202
|
end
|
167
203
|
|
168
|
-
|
204
|
+
def setup_schedule(queue)
|
205
|
+
#schedule hash must contain exactly one of the allowed keys
|
206
|
+
msg_invalid_schedule = "Invalid config. schedule hash must contain " +
|
207
|
+
"exactly one of the following keys - cron, at, every or in"
|
208
|
+
raise Logstash::ConfigurationError, msg_invalid_schedule if @schedule.keys.length !=1
|
209
|
+
schedule_type = @schedule.keys.first
|
210
|
+
schedule_value = @schedule[schedule_type]
|
211
|
+
raise LogStash::ConfigurationError, msg_invalid_schedule unless Schedule_types.include?(schedule_type)
|
212
|
+
|
213
|
+
@scheduler = Rufus::Scheduler.new(:max_work_threads => 1)
|
214
|
+
#as of v3.0.9, :first_in => :now doesn't work. Use the following workaround instead
|
215
|
+
opts = schedule_type == "every" ? { :first_in => 0.01 } : {}
|
216
|
+
@scheduler.send(schedule_type, schedule_value, opts) { run_once(queue) }
|
217
|
+
@scheduler.join
|
218
|
+
end
|
219
|
+
|
169
220
|
def run_once(queue)
|
170
221
|
@requests.each do |name, request|
|
171
222
|
request_async(queue, name, request)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-input-http_poller'
|
3
|
-
s.version = '3.0
|
3
|
+
s.version = '3.1.0'
|
4
4
|
s.licenses = ['Apache License (2.0)']
|
5
5
|
s.summary = "Poll HTTP endpoints with Logstash."
|
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"
|
@@ -22,8 +22,10 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_runtime_dependency 'logstash-codec-plain'
|
23
23
|
s.add_runtime_dependency 'logstash-mixin-http_client', ">= 2.2.4", "< 5.0.0"
|
24
24
|
s.add_runtime_dependency 'stud', "~> 0.0.22"
|
25
|
+
s.add_runtime_dependency 'rufus-scheduler', "~>3.0.9"
|
25
26
|
|
26
27
|
s.add_development_dependency 'logstash-codec-json'
|
27
28
|
s.add_development_dependency 'logstash-devutils'
|
28
29
|
s.add_development_dependency 'flores'
|
30
|
+
s.add_development_dependency 'timecop'
|
29
31
|
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
require "logstash/devutils/rspec/spec_helper"
|
2
2
|
require 'logstash/inputs/http_poller'
|
3
3
|
require 'flores/random'
|
4
|
+
require "timecop"
|
4
5
|
|
5
6
|
describe LogStash::Inputs::HTTP_Poller do
|
6
7
|
let(:metadata_target) { "_http_poller_metadata" }
|
7
8
|
let(:queue) { Queue.new }
|
8
|
-
let(:
|
9
|
+
let(:default_schedule) {
|
10
|
+
{ "cron" => "* * * * * UTC" }
|
11
|
+
}
|
9
12
|
let(:default_name) { "url1 " }
|
10
13
|
let(:default_url) { "http://localhost:1827" }
|
11
14
|
let(:default_urls) {
|
@@ -15,7 +18,7 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
15
18
|
}
|
16
19
|
let(:default_opts) {
|
17
20
|
{
|
18
|
-
"
|
21
|
+
"schedule" => default_schedule,
|
19
22
|
"urls" => default_urls,
|
20
23
|
"codec" => "json",
|
21
24
|
"metadata_target" => metadata_target
|
@@ -31,9 +34,13 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
31
34
|
end
|
32
35
|
|
33
36
|
describe "#run" do
|
34
|
-
it "should
|
35
|
-
|
36
|
-
|
37
|
+
it "should setup a scheduler" do
|
38
|
+
runner = Thread.new do
|
39
|
+
subject.run(double("queue"))
|
40
|
+
expect(subject.instance_variable_get("@scheduler")).to be_a_kind_of(Rufus::Scheduler)
|
41
|
+
end
|
42
|
+
runner.kill
|
43
|
+
runner.join
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
@@ -151,6 +158,163 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
151
158
|
end
|
152
159
|
end
|
153
160
|
|
161
|
+
describe "scheduler configuration" do
|
162
|
+
context "given an interval" do
|
163
|
+
let(:opts) {
|
164
|
+
{
|
165
|
+
"interval" => 2,
|
166
|
+
"urls" => default_urls,
|
167
|
+
"codec" => "json",
|
168
|
+
"metadata_target" => metadata_target
|
169
|
+
}
|
170
|
+
}
|
171
|
+
it "should run once in each interval" do
|
172
|
+
instance = klass.new(opts)
|
173
|
+
instance.register
|
174
|
+
queue = Queue.new
|
175
|
+
runner = Thread.new do
|
176
|
+
instance.run(queue)
|
177
|
+
end
|
178
|
+
#T 0123456
|
179
|
+
#events x x x x
|
180
|
+
#expects 3 events at T=5
|
181
|
+
sleep 5
|
182
|
+
instance.stop
|
183
|
+
runner.kill
|
184
|
+
runner.join
|
185
|
+
expect(queue.size).to eq(3)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "given both interval and schedule options" do
|
190
|
+
let(:opts) {
|
191
|
+
{
|
192
|
+
"interval" => 1,
|
193
|
+
"schedule" => { "every" => "5s" },
|
194
|
+
"urls" => default_urls,
|
195
|
+
"codec" => "json",
|
196
|
+
"metadata_target" => metadata_target
|
197
|
+
}
|
198
|
+
}
|
199
|
+
it "should raise ConfigurationError" do
|
200
|
+
instance = klass.new(opts)
|
201
|
+
instance.register
|
202
|
+
queue = Queue.new
|
203
|
+
runner = Thread.new do
|
204
|
+
expect{instance.run(queue)}.to raise_error(LogStash::ConfigurationError)
|
205
|
+
end
|
206
|
+
instance.stop
|
207
|
+
runner.kill
|
208
|
+
runner.join
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context "given 'cron' expression" do
|
213
|
+
let(:opts) {
|
214
|
+
{
|
215
|
+
"schedule" => { "cron" => "* * * * * UTC" },
|
216
|
+
"urls" => default_urls,
|
217
|
+
"codec" => "json",
|
218
|
+
"metadata_target" => metadata_target
|
219
|
+
}
|
220
|
+
}
|
221
|
+
it "should run at the schedule" do
|
222
|
+
instance = klass.new(opts)
|
223
|
+
instance.register
|
224
|
+
Timecop.travel(Time.new(2000,1,1,0,0,0,'+00:00'))
|
225
|
+
Timecop.scale(60)
|
226
|
+
queue = Queue.new
|
227
|
+
runner = Thread.new do
|
228
|
+
instance.run(queue)
|
229
|
+
end
|
230
|
+
sleep 3
|
231
|
+
instance.stop
|
232
|
+
runner.kill
|
233
|
+
runner.join
|
234
|
+
expect(queue.size).to eq(2)
|
235
|
+
Timecop.return
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context "given 'at' expression" do
|
240
|
+
let(:opts) {
|
241
|
+
{
|
242
|
+
"schedule" => { "at" => "2000-01-01 00:05:00 +0000"},
|
243
|
+
"urls" => default_urls,
|
244
|
+
"codec" => "json",
|
245
|
+
"metadata_target" => metadata_target
|
246
|
+
}
|
247
|
+
}
|
248
|
+
it "should run at the schedule" do
|
249
|
+
instance = klass.new(opts)
|
250
|
+
instance.register
|
251
|
+
Timecop.travel(Time.new(2000,1,1,0,0,0,'+00:00'))
|
252
|
+
Timecop.scale(60 * 5)
|
253
|
+
queue = Queue.new
|
254
|
+
runner = Thread.new do
|
255
|
+
instance.run(queue)
|
256
|
+
end
|
257
|
+
sleep 2
|
258
|
+
instance.stop
|
259
|
+
runner.kill
|
260
|
+
runner.join
|
261
|
+
expect(queue.size).to eq(1)
|
262
|
+
Timecop.return
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "given 'every' expression" do
|
267
|
+
let(:opts) {
|
268
|
+
{
|
269
|
+
"schedule" => { "every" => "2s"},
|
270
|
+
"urls" => default_urls,
|
271
|
+
"codec" => "json",
|
272
|
+
"metadata_target" => metadata_target
|
273
|
+
}
|
274
|
+
}
|
275
|
+
it "should run at the schedule" do
|
276
|
+
instance = klass.new(opts)
|
277
|
+
instance.register
|
278
|
+
queue = Queue.new
|
279
|
+
runner = Thread.new do
|
280
|
+
instance.run(queue)
|
281
|
+
end
|
282
|
+
#T 0123456
|
283
|
+
#events x x x x
|
284
|
+
#expects 3 events at T=5
|
285
|
+
sleep 5
|
286
|
+
instance.stop
|
287
|
+
runner.kill
|
288
|
+
runner.join
|
289
|
+
expect(queue.size).to eq(3)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "given 'in' expression" do
|
294
|
+
let(:opts) {
|
295
|
+
{
|
296
|
+
"schedule" => { "in" => "2s"},
|
297
|
+
"urls" => default_urls,
|
298
|
+
"codec" => "json",
|
299
|
+
"metadata_target" => metadata_target
|
300
|
+
}
|
301
|
+
}
|
302
|
+
it "should run at the schedule" do
|
303
|
+
instance = klass.new(opts)
|
304
|
+
instance.register
|
305
|
+
queue = Queue.new
|
306
|
+
runner = Thread.new do
|
307
|
+
instance.run(queue)
|
308
|
+
end
|
309
|
+
sleep 3
|
310
|
+
instance.stop
|
311
|
+
runner.kill
|
312
|
+
runner.join
|
313
|
+
expect(queue.size).to eq(1)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
154
318
|
describe "events" do
|
155
319
|
shared_examples("matching metadata") {
|
156
320
|
let(:metadata) { event.get(metadata_target) }
|
@@ -292,7 +456,9 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
292
456
|
}
|
293
457
|
let(:opts) {
|
294
458
|
{
|
295
|
-
"
|
459
|
+
"schedule" => {
|
460
|
+
"cron" => "* * * * * UTC"
|
461
|
+
},
|
296
462
|
"urls" => {
|
297
463
|
default_name => url
|
298
464
|
},
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-http_poller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-08-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,6 +79,20 @@ dependencies:
|
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: 0.0.22
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 3.0.9
|
88
|
+
name: rufus-scheduler
|
89
|
+
prerelease: false
|
90
|
+
type: :runtime
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 3.0.9
|
82
96
|
- !ruby/object:Gem::Dependency
|
83
97
|
requirement: !ruby/object:Gem::Requirement
|
84
98
|
requirements:
|
@@ -121,6 +135,20 @@ dependencies:
|
|
121
135
|
- - ">="
|
122
136
|
- !ruby/object:Gem::Version
|
123
137
|
version: '0'
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
name: timecop
|
145
|
+
prerelease: false
|
146
|
+
type: :development
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
124
152
|
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
|
125
153
|
email: info@elastic.co
|
126
154
|
executables: []
|