logstash-input-elasticsearch 4.6.1 → 4.6.2

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: f3fee8b4ee34b945816ffa2fe5588fcc6107b5c995aadb311a903863898fdfe2
4
- data.tar.gz: '09644097ce9d8707ca6c629f72a439692b29bf23a0d536135d5fb8c4c9ee057e'
3
+ metadata.gz: 92c58eb709a67922d73d44a13cca7fc933968747feebb0c7afa81c04ea3543d2
4
+ data.tar.gz: 4354af2982b8af23492a8c1f4c063c21ce6e2d1bfc1e082a9de243ab1c575248
5
5
  SHA512:
6
- metadata.gz: c9dae7fc0d75b73a9624be4bd356cbd7019858e32f67542ec61d6114792756655f39acc49b57054a593d0cab32f28a2ed42dbe94856ca1d31d6413e91f68bf2c
7
- data.tar.gz: e25e5fcaf0a3d8871bb3ddea91e1137ec88c380cd790b0e09912be2423f416a89650a23cf5921e816cb92cbfd22a8d57c7476f5f5f800aff420ef745dd55a161
6
+ metadata.gz: ba09a7c97593fb2b32cbd4c1f5c4448af2d6ed10c32908ea98b5d4bd54ec0bf11321ae30c48afa745be27bc6280c8fbac6c3f7e62dfa8d5887142dce04e3d0b3
7
+ data.tar.gz: 86e4b75f7937c4e66a23b5724902d35db23303d297d7d46cfb55092efc14d0141e708b73b2a72ee1f459f27bc4a9ee0f46d337de2b31b9f38675e25286b58778
@@ -1,3 +1,6 @@
1
+ ## 4.6.2
2
+ - Added scroll clearing and better handling of scroll expiration [#128](https://github.com/logstash-plugins/logstash-input-elasticsearch/pull/128)
3
+
1
4
  ## 4.6.1
2
5
  - [DOC] Removed outdated compatibility notice [#124](https://github.com/logstash-plugins/logstash-input-elasticsearch/pull/124)
3
6
 
@@ -204,9 +204,12 @@ class LogStash::Inputs::Elasticsearch < LogStash::Inputs::Base
204
204
 
205
205
  transport_options[:proxy] = @proxy.to_s if @proxy && !@proxy.eql?('')
206
206
 
207
- @client = Elasticsearch::Client.new(:hosts => hosts, :transport_options => transport_options,
208
- :transport_class => ::Elasticsearch::Transport::Transport::HTTP::Manticore,
209
- :ssl => ssl_options)
207
+ @client = Elasticsearch::Client.new(
208
+ :hosts => hosts,
209
+ :transport_options => transport_options,
210
+ :transport_class => ::Elasticsearch::Transport::Transport::HTTP::Manticore,
211
+ :ssl => ssl_options
212
+ )
210
213
  end
211
214
 
212
215
  ##
@@ -266,25 +269,41 @@ class LogStash::Inputs::Elasticsearch < LogStash::Inputs::Base
266
269
  slice_options = @options.merge(:body => LogStash::Json.dump(slice_query) )
267
270
 
268
271
  logger.info("Slice starting", slice_id: slice_id, slices: @slices) unless slice_id.nil?
269
- r = search_request(slice_options)
270
272
 
271
- r['hits']['hits'].each { |hit| push_hit(hit, output_queue) }
272
- logger.debug("Slice progress", slice_id: slice_id, slices: @slices) unless slice_id.nil?
273
-
274
- has_hits = r['hits']['hits'].any?
273
+ scroll_id = nil
274
+ begin
275
+ r = search_request(slice_options)
275
276
 
276
- while has_hits && r['_scroll_id'] && !stop?
277
- r = process_next_scroll(output_queue, r['_scroll_id'])
277
+ r['hits']['hits'].each { |hit| push_hit(hit, output_queue) }
278
278
  logger.debug("Slice progress", slice_id: slice_id, slices: @slices) unless slice_id.nil?
279
- has_hits = r['has_hits']
279
+
280
+ has_hits = r['hits']['hits'].any?
281
+ scroll_id = r['_scroll_id']
282
+
283
+ while has_hits && scroll_id && !stop?
284
+ has_hits, scroll_id = process_next_scroll(output_queue, scroll_id)
285
+ logger.debug("Slice progress", slice_id: slice_id, slices: @slices) if logger.debug? && slice_id
286
+ end
287
+ logger.info("Slice complete", slice_id: slice_id, slices: @slices) unless slice_id.nil?
288
+ ensure
289
+ clear_scroll(scroll_id)
280
290
  end
281
- logger.info("Slice complete", slice_id: slice_id, slices: @slices) unless slice_id.nil?
282
291
  end
283
292
 
293
+ ##
294
+ # @param output_queue [#<<]
295
+ # @param scroll_id [String]: a scroll id to resume
296
+ # @return [Array(Boolean,String)]: a tuple representing whether the response
297
+ #
284
298
  def process_next_scroll(output_queue, scroll_id)
285
299
  r = scroll_request(scroll_id)
286
300
  r['hits']['hits'].each { |hit| push_hit(hit, output_queue) }
287
- {'has_hits' => r['hits']['hits'].any?, '_scroll_id' => r['_scroll_id']}
301
+ [r['hits']['hits'].any?, r['_scroll_id']]
302
+ rescue => e
303
+ # this will typically be triggered by a scroll timeout
304
+ logger.error("Scroll request error, aborting scroll", error: e.inspect)
305
+ # return no hits and original scroll_id so we can try to clear it
306
+ [false, scroll_id]
288
307
  end
289
308
 
290
309
  def push_hit(hit, output_queue)
@@ -313,16 +332,21 @@ class LogStash::Inputs::Elasticsearch < LogStash::Inputs::Base
313
332
  output_queue << event
314
333
  end
315
334
 
335
+ def clear_scroll(scroll_id)
336
+ @client.clear_scroll(scroll_id: scroll_id) if scroll_id
337
+ rescue => e
338
+ # ignore & log any clear_scroll errors
339
+ logger.warn("Ignoring clear_scroll exception", message: e.message)
340
+ end
341
+
316
342
  def scroll_request scroll_id
317
- client.scroll(:body => { :scroll_id => scroll_id }, :scroll => @scroll)
343
+ @client.scroll(:body => { :scroll_id => scroll_id }, :scroll => @scroll)
318
344
  end
319
345
 
320
346
  def search_request(options)
321
- client.search(options)
347
+ @client.search(options)
322
348
  end
323
349
 
324
- attr_reader :client
325
-
326
350
  def hosts_default?(hosts)
327
351
  hosts.nil? || ( hosts.is_a?(Array) && hosts.empty? )
328
352
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-elasticsearch'
4
- s.version = '4.6.1'
4
+ s.version = '4.6.2'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Reads query results from an Elasticsearch cluster"
7
7
  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"
@@ -8,9 +8,13 @@ require "stud/temporary"
8
8
  require "time"
9
9
  require "date"
10
10
 
11
- describe LogStash::Inputs::Elasticsearch do
11
+ class LogStash::Inputs::TestableElasticsearch < LogStash::Inputs::Elasticsearch
12
+ attr_reader :client
13
+ end
14
+
15
+ describe LogStash::Inputs::TestableElasticsearch do
12
16
 
13
- let(:plugin) { LogStash::Inputs::Elasticsearch.new(config) }
17
+ let(:plugin) { LogStash::Inputs::TestableElasticsearch.new(config) }
14
18
  let(:queue) { Queue.new }
15
19
 
16
20
  it_behaves_like "an interruptible input plugin" do
@@ -32,6 +36,7 @@ describe LogStash::Inputs::Elasticsearch do
32
36
  }
33
37
  allow(esclient).to receive(:search) { { "hits" => { "hits" => [hit] } } }
34
38
  allow(esclient).to receive(:scroll) { { "hits" => { "hits" => [hit] } } }
39
+ allow(esclient).to receive(:clear_scroll).and_return(nil)
35
40
  end
36
41
  end
37
42
 
@@ -76,6 +81,7 @@ describe LogStash::Inputs::Elasticsearch do
76
81
  expect(Elasticsearch::Client).to receive(:new).with(any_args).and_return(client)
77
82
  expect(client).to receive(:search).with(any_args).and_return(response)
78
83
  expect(client).to receive(:scroll).with({ :body => { :scroll_id => "cXVlcnlUaGVuRmV0Y2g" }, :scroll=> "1m" }).and_return(scroll_reponse)
84
+ expect(client).to receive(:clear_scroll).and_return(nil)
79
85
 
80
86
  event = input(config) do |pipeline, queue|
81
87
  queue.pop
@@ -257,6 +263,8 @@ describe LogStash::Inputs::Elasticsearch do
257
263
  expect(Elasticsearch::Client).to receive(:new).with(any_args).and_return(client)
258
264
  plugin.register
259
265
 
266
+ expect(client).to receive(:clear_scroll).and_return(nil)
267
+
260
268
  # SLICE0 is a three-page scroll in which the last page is empty
261
269
  slice0_query = LogStash::Json.dump(query.merge('slice' => { 'id' => 0, 'max' => 2}))
262
270
  expect(client).to receive(:search).with(hash_including(:body => slice0_query)).and_return(slice0_response0)
@@ -360,6 +368,7 @@ describe LogStash::Inputs::Elasticsearch do
360
368
  expect(Elasticsearch::Client).to receive(:new).with(any_args).and_return(client)
361
369
  expect(client).to receive(:search).with(any_args).and_return(response)
362
370
  allow(client).to receive(:scroll).with({ :body => {:scroll_id => "cXVlcnlUaGVuRmV0Y2g"}, :scroll => "1m" }).and_return(scroll_reponse)
371
+ allow(client).to receive(:clear_scroll).and_return(nil)
363
372
  end
364
373
 
365
374
  context 'when defining docinfo' do
@@ -405,6 +414,7 @@ describe LogStash::Inputs::Elasticsearch do
405
414
  "docinfo_target" => 'metadata_with_string'
406
415
  } }
407
416
  it 'thows an exception if the `docinfo_target` exist but is not of type hash' do
417
+ expect(client).not_to receive(:clear_scroll)
408
418
  plugin.register
409
419
  expect { plugin.run([]) }.to raise_error(Exception, /incompatible event/)
410
420
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.1
4
+ version: 4.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-08 00:00:00.000000000 Z
11
+ date: 2020-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement