logstash-input-http_poller 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 10e023a2848c2a827b18e11fc0db42dd6d257d70
4
- data.tar.gz: a014c52d6aa4509e877f064c214ed8e5dac2e803
3
+ metadata.gz: 791035a6079e584fae5b891675e5e17225405a70
4
+ data.tar.gz: 8286793c8788fc5af3c0d90ee10f613d49933e25
5
5
  SHA512:
6
- metadata.gz: d85efa4810a99e15900b5387266c93ed81b58bdd11e0e89059bfb3aee2358524cc888ebcecef3c5bbf6151103004e46306482683d36d3ada0a68d618211ac1f0
7
- data.tar.gz: 822a8f6881d29c803dc7328188c25cedbb456230312cbf61e520913f8db32c30cac7ef532b6fa494637fcd741b9b5e22861600f06ff5012502f234350c0cee81
6
+ metadata.gz: 95894f281b1440dd9c07bdf4790a2bf3017791c9c1f038a14b735637cb7a9b28db992c4e30898f29b37bbd158b51bc61ed159ad2d7fdbf5d2b68a45fac8303c3
7
+ data.tar.gz: 2b93713dad3146739aaed0a0b7ba838381d8e7b46ef9fa9a2a217e83d40b063d9ce4a04221c9d5697542aab77960572e8bbe7274776a1d416d30b8035b0b0be7
data/README.md CHANGED
@@ -63,7 +63,12 @@ gem "logstash-filter-awesome", :path => "/your/local/logstash-filter-awesome"
63
63
  ```
64
64
  - Install plugin
65
65
  ```sh
66
+ # Logstash 2.3 and higher
67
+ bin/logstash-plugin install --no-verify
68
+
69
+ # Prior to Logstash 2.3
66
70
  bin/plugin install --no-verify
71
+
67
72
  ```
68
73
  - Run Logstash with your plugin
69
74
  ```sh
@@ -81,7 +86,12 @@ gem build logstash-filter-awesome.gemspec
81
86
  ```
82
87
  - Install the plugin from the Logstash home
83
88
  ```sh
84
- bin/plugin install /your/local/plugin/logstash-filter-awesome.gem
89
+ # Logstash 2.3 and higher
90
+ bin/logstash-plugin install --no-verify
91
+
92
+ # Prior to Logstash 2.3
93
+ bin/plugin install --no-verify
94
+
85
95
  ```
86
96
  - Start Logstash and proceed to test the plugin
87
97
 
@@ -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
- # interval => 60
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"
@@ -59,7 +61,20 @@ class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
59
61
  config :urls, :validate => :hash, :required => true
60
62
 
61
63
  # How often (in seconds) the urls will be called
62
- config :interval, :validate => :number, :required => true
64
+ # DEPRECATED. Use 'schedule' option instead.
65
+ # If both interval and schedule options are specified, interval
66
+ # option takes higher precedence
67
+ config :interval, :validate => :number, :deprecated => true
68
+
69
+ # Schedule of when to periodically poll from the urls
70
+ # Format: A hash with
71
+ # + key: "cron" | "every" | "in" | "at"
72
+ # + value: string
73
+ # Examples:
74
+ # a) { "every" => "1h" }
75
+ # b) { "cron" => "* * * * * UTC" }
76
+ # See: rufus/scheduler for details about different schedule options and value string format
77
+ config :schedule, :validate => :hash
63
78
 
64
79
  # 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.
65
80
  config :target, :validate => :string
@@ -70,17 +85,19 @@ class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
70
85
  config :metadata_target, :validate => :string, :default => '@metadata'
71
86
 
72
87
  public
88
+ Schedule_types = %w(cron every at in)
73
89
  def register
74
90
  @host = Socket.gethostname.force_encoding(Encoding::UTF_8)
75
91
 
76
92
  @logger.info("Registering http_poller Input", :type => @type,
77
- :urls => @urls, :interval => @interval, :timeout => @timeout)
93
+ :urls => @urls, :interval => @interval, :schedule => @schedule, :timeout => @timeout)
78
94
 
79
95
  setup_requests!
80
96
  end
81
97
 
82
98
  def stop
83
99
  Stud.stop!(@interval_thread) if @interval_thread
100
+ @scheduler.stop if @scheduler
84
101
  end
85
102
 
86
103
  private
@@ -133,13 +150,46 @@ class LogStash::Inputs::HTTP_Poller < LogStash::Inputs::Base
133
150
 
134
151
  public
135
152
  def run(queue)
153
+ #interval or schedule must be provided. Must be exclusively either one. Not neither. Not both.
154
+ raise LogStash::ConfigurationError, "Invalid config. Neither interval nor schedule was specified." \
155
+ unless @interval || @schedule
156
+ raise LogStash::ConfigurationError, "Invalid config. Specify only interval or schedule. Not both." \
157
+ if @interval && @schedule
158
+
159
+ if @interval
160
+ setup_interval(queue)
161
+ elsif @schedule
162
+ setup_schedule(queue)
163
+ else
164
+ #should not reach here
165
+ raise LogStash::ConfigurationError, "Invalid config. Neither interval nor schedule was specified."
166
+ end
167
+ end
168
+
169
+ private
170
+ def setup_interval(queue)
136
171
  @interval_thread = Thread.current
137
172
  Stud.interval(@interval) do
138
173
  run_once(queue)
139
174
  end
140
175
  end
141
176
 
142
- private
177
+ def setup_schedule(queue)
178
+ #schedule hash must contain exactly one of the allowed keys
179
+ msg_invalid_schedule = "Invalid config. schedule hash must contain " +
180
+ "exactly one of the following keys - cron, at, every or in"
181
+ raise Logstash::ConfigurationError, msg_invalid_schedule if @schedule.keys.length !=1
182
+ schedule_type = @schedule.keys.first
183
+ schedule_value = @schedule[schedule_type]
184
+ raise LogStash::ConfigurationError, msg_invalid_schedule unless Schedule_types.include?(schedule_type)
185
+
186
+ @scheduler = Rufus::Scheduler.new(:max_work_threads => 1)
187
+ #as of v3.0.9, :first_in => :now doesn't work. Use the following workaround instead
188
+ opts = schedule_type == "every" ? { :first_in => 0.01 } : {}
189
+ @scheduler.send(schedule_type, schedule_value, opts) { run_once(queue) }
190
+ @scheduler.join
191
+ end
192
+
143
193
  def run_once(queue)
144
194
  @requests.each do |name, request|
145
195
  request_async(queue, name, request)
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-input-http_poller'
3
- s.version = '2.0.6'
3
+ s.version = '2.1.0'
4
4
  s.licenses = ['Apache License (2.0)']
5
5
  s.summary = "Poll HTTP endpoints with Logstash."
6
- s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program."
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"
7
7
  s.authors = [ "Elastic", "andrewvc"]
8
8
  s.email = 'info@elastic.co'
9
9
  s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
@@ -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", "< 3.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(:default_interval) { 5 }
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
- "interval" => default_interval,
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 run at the specified interval" do
35
- expect(Stud).to receive(:interval).with(default_interval).once
36
- subject.run(double("queue"))
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[metadata_target] }
@@ -292,7 +456,9 @@ describe LogStash::Inputs::HTTP_Poller do
292
456
  }
293
457
  let(:opts) {
294
458
  {
295
- "interval" => default_interval,
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: 2.0.6
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
@@ -9,113 +9,141 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-11 00:00:00.000000000 Z
12
+ date: 2016-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
15
20
  name: logstash-core-plugin-api
21
+ prerelease: false
22
+ type: :runtime
16
23
  version_requirements: !ruby/object:Gem::Requirement
17
24
  requirements:
18
- - - ~>
25
+ - - "~>"
19
26
  - !ruby/object:Gem::Version
20
27
  version: '1.0'
28
+ - !ruby/object:Gem::Dependency
21
29
  requirement: !ruby/object:Gem::Requirement
22
30
  requirements:
23
- - - ~>
31
+ - - ">="
24
32
  - !ruby/object:Gem::Version
25
- version: '1.0'
33
+ version: '0'
34
+ name: logstash-codec-plain
26
35
  prerelease: false
27
36
  type: :runtime
28
- - !ruby/object:Gem::Dependency
29
- name: logstash-codec-plain
30
37
  version_requirements: !ruby/object:Gem::Requirement
31
38
  requirements:
32
- - - '>='
39
+ - - ">="
33
40
  - !ruby/object:Gem::Version
34
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
35
43
  requirement: !ruby/object:Gem::Requirement
36
44
  requirements:
37
- - - '>='
45
+ - - ">="
38
46
  - !ruby/object:Gem::Version
39
- version: '0'
47
+ version: 2.2.4
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: 3.0.0
51
+ name: logstash-mixin-http_client
40
52
  prerelease: false
41
53
  type: :runtime
42
- - !ruby/object:Gem::Dependency
43
- name: logstash-mixin-http_client
44
54
  version_requirements: !ruby/object:Gem::Requirement
45
55
  requirements:
46
- - - '>='
56
+ - - ">="
47
57
  - !ruby/object:Gem::Version
48
58
  version: 2.2.4
49
- - - <
59
+ - - "<"
50
60
  - !ruby/object:Gem::Version
51
61
  version: 3.0.0
62
+ - !ruby/object:Gem::Dependency
52
63
  requirement: !ruby/object:Gem::Requirement
53
64
  requirements:
54
- - - '>='
55
- - !ruby/object:Gem::Version
56
- version: 2.2.4
57
- - - <
65
+ - - "~>"
58
66
  - !ruby/object:Gem::Version
59
- version: 3.0.0
67
+ version: 0.0.22
68
+ name: stud
60
69
  prerelease: false
61
70
  type: :runtime
62
- - !ruby/object:Gem::Dependency
63
- name: stud
64
71
  version_requirements: !ruby/object:Gem::Requirement
65
72
  requirements:
66
- - - ~>
73
+ - - "~>"
67
74
  - !ruby/object:Gem::Version
68
75
  version: 0.0.22
76
+ - !ruby/object:Gem::Dependency
69
77
  requirement: !ruby/object:Gem::Requirement
70
78
  requirements:
71
- - - ~>
79
+ - - "~>"
72
80
  - !ruby/object:Gem::Version
73
- version: 0.0.22
81
+ version: 3.0.9
82
+ name: rufus-scheduler
74
83
  prerelease: false
75
84
  type: :runtime
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.0.9
76
90
  - !ruby/object:Gem::Dependency
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
77
96
  name: logstash-codec-json
97
+ prerelease: false
98
+ type: :development
78
99
  version_requirements: !ruby/object:Gem::Requirement
79
100
  requirements:
80
- - - '>='
101
+ - - ">="
81
102
  - !ruby/object:Gem::Version
82
103
  version: '0'
104
+ - !ruby/object:Gem::Dependency
83
105
  requirement: !ruby/object:Gem::Requirement
84
106
  requirements:
85
- - - '>='
107
+ - - ">="
86
108
  - !ruby/object:Gem::Version
87
109
  version: '0'
110
+ name: logstash-devutils
88
111
  prerelease: false
89
112
  type: :development
90
- - !ruby/object:Gem::Dependency
91
- name: logstash-devutils
92
113
  version_requirements: !ruby/object:Gem::Requirement
93
114
  requirements:
94
- - - '>='
115
+ - - ">="
95
116
  - !ruby/object:Gem::Version
96
117
  version: '0'
118
+ - !ruby/object:Gem::Dependency
97
119
  requirement: !ruby/object:Gem::Requirement
98
120
  requirements:
99
- - - '>='
121
+ - - ">="
100
122
  - !ruby/object:Gem::Version
101
123
  version: '0'
124
+ name: flores
102
125
  prerelease: false
103
126
  type: :development
104
- - !ruby/object:Gem::Dependency
105
- name: flores
106
127
  version_requirements: !ruby/object:Gem::Requirement
107
128
  requirements:
108
- - - '>='
129
+ - - ">="
109
130
  - !ruby/object:Gem::Version
110
131
  version: '0'
132
+ - !ruby/object:Gem::Dependency
111
133
  requirement: !ruby/object:Gem::Requirement
112
134
  requirements:
113
- - - '>='
135
+ - - ">="
114
136
  - !ruby/object:Gem::Version
115
137
  version: '0'
138
+ name: timecop
116
139
  prerelease: false
117
140
  type: :development
118
- description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program.
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ 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
119
147
  email: info@elastic.co
120
148
  executables: []
121
149
  extensions: []
@@ -141,12 +169,12 @@ require_paths:
141
169
  - lib
142
170
  required_ruby_version: !ruby/object:Gem::Requirement
143
171
  requirements:
144
- - - '>='
172
+ - - ">="
145
173
  - !ruby/object:Gem::Version
146
174
  version: '0'
147
175
  required_rubygems_version: !ruby/object:Gem::Requirement
148
176
  requirements:
149
- - - '>='
177
+ - - ">="
150
178
  - !ruby/object:Gem::Version
151
179
  version: '0'
152
180
  requirements: []