fluent-plugin-elasticsearch 2.9.2 → 2.10.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
  SHA256:
3
- metadata.gz: c6294313d2bbda7a0933074c22b9d94db7d0a6ae7e7518210a0b56fa6a5ae2a2
4
- data.tar.gz: a94f6a5ce9d4e79c3280d512cb8acd9174aac263179f09f18088f50f6a1f9a62
3
+ metadata.gz: f778421b8290ea1db16ad57f1c0be9a35e656d201e5b52c502ae9301c60a67c3
4
+ data.tar.gz: 7e72d88f792ac7a959faa393e91fcc08917ada672860730352219b5d26b167b4
5
5
  SHA512:
6
- metadata.gz: d0184d1b690d6c9118bcb419e6904411b61dd8cac289f59e78ba554fbe3c953ac7b697b5271a491fbcf5b391d5691a7c3982288ed10bf6b9e1eca54a705450cb
7
- data.tar.gz: e0efbbd71009eaa75e8372677fbd169a54f1d143b2ce12df112c075af8b523a18650472ea6c4692267ca39cb48f30204d81dbd556bc18187d2c31a7c515ee4a8
6
+ metadata.gz: 8222728bf41a377029aa620f94f7d773529d4dbae47081158022c49b8ebb08aed224d93208db1d4933663ea5226decd1e99096c9890a0f59a58d22e8aca9d5ae
7
+ data.tar.gz: fe857ad374b96cfc4eeedb02642fc1bebfb4da43f0cba397789db9f74a6df6704ffb1c57b65524b00866e4b540c97130c387f6252bbf35fa1215d95c7f3c1f1a
data/History.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  ### [Unreleased]
4
4
 
5
+ ### 2.10.0
6
+ - Uplift Merge pull request #405 from jcantrill/sanitize_bulk (#414)
7
+
5
8
  ### 2.9.2
6
9
  - Uplift Merge pull request #410 from richm/v0.12-consistent-errors-and-tests (#411)
7
10
  - Add correct link for include_timestamp (#408)
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'fluent-plugin-elasticsearch'
6
- s.version = '2.9.2'
6
+ s.version = '2.10.0'
7
7
  s.authors = ['diogo', 'pitr']
8
8
  s.email = ['pitr.vern@gmail.com', 'me@diogoterror.com']
9
9
  s.description = %q{Elasticsearch output plugin for Fluent event collector}
@@ -1,23 +1,41 @@
1
+ require 'fluent/event'
1
2
  require_relative 'elasticsearch_constants'
2
3
 
3
4
  class Fluent::Plugin::ElasticsearchErrorHandler
4
5
  include Fluent::Plugin::ElasticsearchConstants
5
6
 
6
- attr_accessor :records, :bulk_message_count
7
- class BulkIndexQueueFull < StandardError; end
8
- class ElasticsearchOutOfMemory < StandardError; end
7
+ attr_accessor :bulk_message_count
9
8
  class ElasticsearchVersionMismatch < StandardError; end
10
- class UnrecognizedElasticsearchError < StandardError; end
11
9
  class ElasticsearchError < StandardError; end
12
- def initialize(plugin, records = 0, bulk_message_count = 0)
10
+
11
+ def initialize(plugin)
13
12
  @plugin = plugin
14
- @records = records
15
- @bulk_message_count = bulk_message_count
16
13
  end
17
14
 
18
- def handle_error(response)
15
+ def handle_error(response, tag, chunk, bulk_message_count, extracted_values)
16
+ items = response['items']
17
+ if items.nil? || !items.is_a?(Array)
18
+ raise ElasticsearchVersionMismatch, "The response format was unrecognized: #{response}"
19
+ end
20
+ if bulk_message_count != items.length
21
+ raise ElasticsearchError, "The number of records submitted #{bulk_message_count} do not match the number returned #{items.length}. Unable to process bulk response."
22
+ end
23
+ retry_stream = Fluent::MultiEventStream.new
19
24
  stats = Hash.new(0)
20
- response['items'].each do |item|
25
+ meta = {}
26
+ header = {}
27
+ chunk.msgpack_each do |time, rawrecord|
28
+ bulk_message = ''
29
+ next unless rawrecord.is_a? Hash
30
+ begin
31
+ # we need a deep copy for process_message to alter
32
+ processrecord = Marshal.load(Marshal.dump(rawrecord))
33
+ @plugin.process_message(tag, meta, header, time, processrecord, bulk_message, extracted_values)
34
+ rescue => e
35
+ stats[:bad_chunk_record] += 1
36
+ next
37
+ end
38
+ item = items.shift
21
39
  if item.has_key?(@plugin.write_operation)
22
40
  write_operation = @plugin.write_operation
23
41
  elsif INDEX_OP == @plugin.write_operation && item.has_key?(CREATE_OP)
@@ -41,13 +59,19 @@ class Fluent::Plugin::ElasticsearchErrorHandler
41
59
  stats[:successes] += 1
42
60
  when CREATE_OP == write_operation && 409 == status
43
61
  stats[:duplicates] += 1
62
+ when 400 == status
63
+ stats[:bad_argument] += 1
64
+ @plugin.router.emit_error_event(tag, time, rawrecord, '400 - Rejected by Elasticsearch')
44
65
  else
45
66
  if item[write_operation].has_key?('error') && item[write_operation]['error'].has_key?('type')
46
67
  type = item[write_operation]['error']['type']
68
+ stats[type] += 1
69
+ retry_stream.add(time, rawrecord)
47
70
  else
48
71
  # When we don't have a type field, something changed in the API
49
72
  # expected return values (ES 2.x)
50
73
  stats[:errors_bad_resp] += 1
74
+ @plugin.router.emit_error_event(tag, time, rawrecord, "#{status} - No error type provided in the response")
51
75
  next
52
76
  end
53
77
  stats[type] += 1
@@ -58,19 +82,6 @@ class Fluent::Plugin::ElasticsearchErrorHandler
58
82
  stats.each_pair { |key, value| msg << "#{value} #{key}" }
59
83
  @plugin.log.debug msg.join(', ')
60
84
  end
61
- case
62
- when stats[:errors_bad_resp] > 0
63
- @plugin.log.on_debug { @plugin.log.debug("Unable to parse response from elasticsearch, likely an API version mismatch: #{response}") }
64
- raise ElasticsearchVersionMismatch, "Unable to parse error response from Elasticsearch, likely an API version mismatch. Add '@log_level debug' to your config to see the full response"
65
- when stats[:successes] + stats[:duplicates] == bulk_message_count
66
- @plugin.log.info("retry succeeded - successes=#{stats[:successes]} duplicates=#{stats[:duplicates]}")
67
- when stats['es_rejected_execution_exception'] > 0
68
- raise BulkIndexQueueFull, 'Bulk index queue is full, retrying'
69
- when stats['out_of_memory_error'] > 0
70
- raise ElasticsearchOutOfMemory, 'Elasticsearch has exhausted its heap, retrying'
71
- else
72
- @plugin.log.on_debug { @plugin.log.debug("Elasticsearch errors returned, retrying: #{response}") }
73
- raise ElasticsearchError, "Elasticsearch returned errors, retrying. Add '@log_level debug' to your config to see the full response"
74
- end
85
+ raise Fluent::Plugin::ElasticsearchOutput::RetryStreamError.new(retry_stream) unless retry_stream.empty?
75
86
  end
76
87
  end
@@ -10,6 +10,7 @@ rescue LoadError
10
10
  end
11
11
 
12
12
  require 'fluent/plugin/output'
13
+ require 'fluent/event'
13
14
  require_relative 'elasticsearch_constants'
14
15
  require_relative 'elasticsearch_error_handler'
15
16
  require_relative 'elasticsearch_index_template'
@@ -18,6 +19,16 @@ module Fluent::Plugin
18
19
  class ElasticsearchOutput < Output
19
20
  class ConnectionFailure < StandardError; end
20
21
 
22
+ # RetryStreamError privides a stream to be
23
+ # put back in the pipeline for cases where a bulk request
24
+ # failed (e.g some records succeed while others failed)
25
+ class RetryStreamError < StandardError
26
+ attr_reader :retry_stream
27
+ def initialize(retry_stream)
28
+ @retry_stream = retry_stream
29
+ end
30
+ end
31
+
21
32
  helpers :event_emitter, :compat_parameters, :record_accessor
22
33
 
23
34
  Fluent::Plugin.register_output('elasticsearch', self)
@@ -375,26 +386,26 @@ EOC
375
386
  end
376
387
 
377
388
  def write(chunk)
389
+ bulk_message_count = 0
378
390
  bulk_message = ''
379
391
  header = {}
380
392
  meta = {}
381
393
 
382
394
  tag = chunk.metadata.tag
383
395
  extracted_values = expand_placeholders(chunk.metadata)
384
- @error = Fluent::Plugin::ElasticsearchErrorHandler.new(self)
385
396
  @last_seen_major_version = detect_es_major_version rescue DEFAULT_ELASTICSEARCH_VERSION
386
397
 
387
398
  chunk.msgpack_each do |time, record|
388
- @error.records += 1
389
399
  next unless record.is_a? Hash
390
-
391
400
  begin
392
401
  process_message(tag, meta, header, time, record, bulk_message, extracted_values)
402
+ bulk_message_count += 1
393
403
  rescue => e
394
404
  router.emit_error_event(tag, time, record, e)
395
405
  end
396
406
  end
397
- send_bulk(bulk_message) unless bulk_message.empty?
407
+
408
+ send_bulk(bulk_message, tag, chunk, bulk_message_count, extracted_values) unless bulk_message.empty?
398
409
  bulk_message.clear
399
410
  end
400
411
 
@@ -479,7 +490,6 @@ EOC
479
490
  end
480
491
 
481
492
  append_record_to_messages(@write_operation, meta, header, record, bulk_message)
482
- @error.bulk_message_count += 1
483
493
  end
484
494
 
485
495
  # returns [parent, child_key] of child described by path array in record's tree
@@ -489,11 +499,18 @@ EOC
489
499
  [parent_object, path[-1]]
490
500
  end
491
501
 
492
- def send_bulk(data)
502
+ # send_bulk given a specific bulk request, the original tag,
503
+ # chunk, and bulk_message_count
504
+ def send_bulk(data, tag, chunk, bulk_message_count, extracted_values)
493
505
  retries = 0
494
506
  begin
495
507
  response = client.bulk body: data
496
- @error.handle_error(response) if response['errors']
508
+ if response['errors']
509
+ error = Fluent::Plugin::ElasticsearchErrorHandler.new(self)
510
+ error.handle_error(response, tag, chunk, bulk_message_count, extracted_values)
511
+ end
512
+ rescue RetryStreamError => e
513
+ router.emit_stream(tag, e.retry_stream)
497
514
  rescue *client.transport.host_unreachable_exceptions => e
498
515
  if retries < 2
499
516
  retries += 1
@@ -1,4 +1,5 @@
1
1
  require 'helper'
2
+ require 'fluent/plugin/out_elasticsearch'
2
3
  require 'fluent/plugin/elasticsearch_error_handler'
3
4
  require 'json'
4
5
 
@@ -6,10 +7,35 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
6
7
 
7
8
  class TestPlugin
8
9
  attr_reader :log
9
- attr_reader :write_operation
10
+ attr_reader :write_operation, :error_events
10
11
  def initialize(log)
11
12
  @log = log
12
13
  @write_operation = 'index'
14
+ @error_events = Fluent::MultiEventStream.new
15
+ end
16
+
17
+ def router
18
+ self
19
+ end
20
+
21
+ def emit_error_event(tag, time, record, e)
22
+ @error_events.add(time, record)
23
+ end
24
+
25
+ def process_message(tag, meta, header, time, record, bulk_message, extracted_values)
26
+ if record.has_key?('raise') && record['raise']
27
+ raise Exception('process_message')
28
+ end
29
+ end
30
+ end
31
+
32
+ class MockChunk
33
+ def initialize(records)
34
+ @records = records
35
+ @index = 0
36
+ end
37
+ def msgpack_each
38
+ @records.each { |item| yield(item[:time],item[:record]) }
13
39
  end
14
40
  end
15
41
 
@@ -27,7 +53,8 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
27
53
  JSON.parse(value)
28
54
  end
29
55
 
30
- def test_errors
56
+ def test_dlq_400_responses
57
+ records = [{time: 123, record: {"foo" => "bar"}}]
31
58
  response = parse_response(%({
32
59
  "took" : 0,
33
60
  "errors" : true,
@@ -35,148 +62,45 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
35
62
  {
36
63
  "create" : {
37
64
  "_index" : "foo",
38
- "_type" : "bar",
39
- "_id" : "abc",
40
- "status" : 500,
41
- "error" : {
42
- "type" : "some unrecognized type",
43
- "reason":"unrecognized error"
44
- }
45
- }
46
- },
47
- {
48
- "create" : {
49
- "_index" : "foo",
50
- "_type" : "bar",
51
- "_id" : "abc",
52
- "status" : 500,
53
- "error" : {
54
- "type" : "some unrecognized type",
55
- "reason":"unrecognized error"
56
- }
57
- }
58
- },
59
- {
60
- "create" : {
61
- "_index" : "foo",
62
- "_type" : "bar",
63
- "_id" : "abc",
64
- "status" : 201
65
- }
66
- },
67
- {
68
- "create" : {
69
- "_index" : "foo",
70
- "_type" : "bar",
71
- "_id" : "abc",
72
- "status" : 409
73
- }
74
- },
75
- {
76
- "create" : {
77
- "_index" : "foo",
78
- "_type" : "bar",
79
- "_id" : "abc",
80
65
  "status" : 400,
81
- "error" : {
82
- "type" : "some unrecognized type",
66
+ "_type" : "bar",
83
67
  "reason":"unrecognized error"
84
68
  }
85
- }
86
69
  }
87
70
  ]
88
- }))
89
-
90
- assert_raise Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError do
91
- @handler.handle_error(response)
92
- end
93
-
71
+ }))
72
+ chunk = MockChunk.new(records)
73
+ dummy_extracted_values = []
74
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
75
+ assert_equal(1, @plugin.error_events.instance_variable_get(:@time_array).size)
94
76
  end
95
77
 
96
- def test_elasticsearch_version_mismatch_raises_error
97
- response = parse_response(%(
98
- {
99
- "took" : 0,
100
- "errors" : true,
101
- "items" : [
102
- {
103
- "create" : {
104
- "_index" : "foo",
105
- "_type" : "bar",
106
- "_id" : "abc",
107
- "status" : 500,
108
- "error" : {
109
- "reason":"some error to cause version mismatch"
110
- }
111
- }
112
- }
113
- ]
114
- }
115
- ))
116
-
117
- assert_raise Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchVersionMismatch do
118
- @handler.handle_error(response)
78
+ def test_retry_error
79
+ records = []
80
+ error_records = Hash.new(false)
81
+ error_records.merge!({0=>true, 4=>true, 9=>true})
82
+ 10.times do |i|
83
+ records << {time: 12345, record: {"message"=>"record #{i}","_id"=>i,"raise"=>error_records[i]}}
119
84
  end
85
+ chunk = MockChunk.new(records)
120
86
 
121
- end
122
-
123
- def test_retry_with_successes_and_duplicates
124
- response = parse_response(%(
125
- {
126
- "took" : 0,
127
- "errors" : true,
128
- "items" : [
129
- {
130
- "create" : {
131
- "_index" : "foo",
132
- "_type" : "bar",
133
- "_id" : "abc",
134
- "status" : 409,
135
- "error" : {
136
- "reason":"duplicate ID"
137
- }
138
- }
139
- },
140
- {
141
- "create" : {
142
- "_index" : "foo",
143
- "_type" : "bar",
144
- "_id" : "abc",
145
- "status" : 201
146
- }
147
- }
148
- ]
149
- }
150
- ))
151
-
152
- @plugin.instance_variable_set(:@write_operation, 'create')
153
- @handler.instance_variable_set(:@bulk_message_count, 2)
154
- @handler.handle_error(response)
155
- assert_match /retry succeeded - successes=1 duplicates=1/, @log.out.logs[0]
156
- end
157
-
158
- def test_bulk_rejection_errors
159
87
  response = parse_response(%({
160
- "took" : 0,
88
+ "took" : 1,
161
89
  "errors" : true,
162
90
  "items" : [
163
91
  {
164
92
  "create" : {
165
93
  "_index" : "foo",
166
94
  "_type" : "bar",
167
- "_id" : "abc",
168
- "status" : 500,
169
- "error" : {
170
- "type" : "some unrecognized type",
171
- "reason":"unrecognized error"
172
- }
95
+ "_id" : "1",
96
+ "status" : 201
173
97
  }
174
98
  },
175
99
  {
176
100
  "create" : {
177
101
  "_index" : "foo",
178
102
  "_type" : "bar",
179
- "_id" : "abc",
103
+ "_id" : "2",
180
104
  "status" : 500,
181
105
  "error" : {
182
106
  "type" : "some unrecognized type",
@@ -188,50 +112,39 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
188
112
  "create" : {
189
113
  "_index" : "foo",
190
114
  "_type" : "bar",
191
- "_id" : "abc",
192
- "status" : 201
115
+ "_id" : "3",
116
+ "status" : 409
193
117
  }
194
118
  },
195
119
  {
196
120
  "create" : {
197
121
  "_index" : "foo",
198
122
  "_type" : "bar",
199
- "_id" : "abc",
200
- "status" : 409
123
+ "_id" : "5",
124
+ "status" : 500,
125
+ "error" : {
126
+ "reason":"unrecognized error - no type field"
127
+ }
201
128
  }
202
129
  },
203
130
  {
204
131
  "create" : {
205
132
  "_index" : "foo",
206
133
  "_type" : "bar",
207
- "_id" : "abc",
134
+ "_id" : "6",
208
135
  "status" : 429,
209
136
  "error" : {
210
137
  "type" : "es_rejected_execution_exception",
211
- "reason":"Elasticsearch could not process bulk index request"
138
+ "reason":"unable to fulfill request at this time, try again later"
212
139
  }
213
140
  }
214
- }
215
- ]
216
- }))
217
-
218
- assert_raise Fluent::Plugin::ElasticsearchErrorHandler::BulkIndexQueueFull do
219
- @handler.handle_error(response)
220
- end
221
-
222
- end
223
-
224
- def test_out_of_memory_errors
225
- response = parse_response(%({
226
- "took" : 0,
227
- "errors" : true,
228
- "items" : [
141
+ },
229
142
  {
230
143
  "create" : {
231
144
  "_index" : "foo",
232
145
  "_type" : "bar",
233
- "_id" : "abc",
234
- "status" : 500,
146
+ "_id" : "7",
147
+ "status" : 400,
235
148
  "error" : {
236
149
  "type" : "some unrecognized type",
237
150
  "reason":"unrecognized error"
@@ -242,48 +155,36 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
242
155
  "create" : {
243
156
  "_index" : "foo",
244
157
  "_type" : "bar",
245
- "_id" : "abc",
158
+ "_id" : "8",
246
159
  "status" : 500,
247
160
  "error" : {
248
161
  "type" : "some unrecognized type",
249
162
  "reason":"unrecognized error"
250
163
  }
251
164
  }
252
- },
253
- {
254
- "create" : {
255
- "_index" : "foo",
256
- "_type" : "bar",
257
- "_id" : "abc",
258
- "status" : 201
259
- }
260
- },
261
- {
262
- "create" : {
263
- "_index" : "foo",
264
- "_type" : "bar",
265
- "_id" : "abc",
266
- "status" : 409
267
- }
268
- },
269
- {
270
- "create" : {
271
- "_index" : "foo",
272
- "_type" : "bar",
273
- "_id" : "abc",
274
- "status" : 400,
275
- "error" : {
276
- "type" : "out_of_memory_error",
277
- "reason":"Elasticsearch exhausted its heap"
278
- }
279
- }
280
165
  }
281
166
  ]
282
167
  }))
283
168
 
284
- assert_raise Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchOutOfMemory do
285
- @handler.handle_error(response)
169
+ begin
170
+ failed = false
171
+ dummy_extracted_values = []
172
+ @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values)
173
+ rescue Fluent::Plugin::ElasticsearchOutput::RetryStreamError=>e
174
+ failed = true
175
+ records = [].tap do |records|
176
+ e.retry_stream.each {|time, record| records << record}
177
+ end
178
+ assert_equal 3, records.length
179
+ assert_equal 2, records[0]['_id']
180
+ assert_equal 6, records[1]['_id']
181
+ assert_equal 8, records[2]['_id']
182
+ errors = @plugin.error_events.collect {|time, record| record}
183
+ assert_equal 2, errors.length
184
+ assert_equal 5, errors[0]['_id']
185
+ assert_equal 7, errors[1]['_id']
286
186
  end
187
+ assert_true failed
287
188
 
288
189
  end
289
190
 
@@ -170,33 +170,6 @@ class ElasticsearchOutput < Test::Unit::TestCase
170
170
  stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 500, error), :headers => { 'Content-Type' => 'json' } } })
171
171
  end
172
172
 
173
- def stub_elastic_unrecognized_error(url="http://localhost:9200/_bulk")
174
- error = {
175
- "status" => 500,
176
- "type" => "some-other-type",
177
- "reason" => "some-other-reason"
178
- }
179
- stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 504, error), :headers => { 'Content-Type' => 'json' } } })
180
- end
181
-
182
- def stub_elastic_version_mismatch(url="http://localhost:9200/_bulk")
183
- error = {
184
- "status" => 500,
185
- "category" => "some-other-type",
186
- "reason" => "some-other-reason"
187
- }
188
- stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 500, error), :headers => { 'Content-Type' => 'json' } } })
189
- end
190
-
191
- def stub_elastic_index_to_create(url="http://localhost:9200/_bulk")
192
- error = {
193
- "category" => "some-other-type",
194
- "reason" => "some-other-reason",
195
- "type" => "some-other-type"
196
- }
197
- stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 0, 500, error), :headers => { 'Content-Type' => 'json' } } })
198
- end
199
-
200
173
  def stub_elastic_unexpected_response_op(url="http://localhost:9200/_bulk")
201
174
  error = {
202
175
  "category" => "some-other-type",
@@ -1748,51 +1721,70 @@ class ElasticsearchOutput < Test::Unit::TestCase
1748
1721
 
1749
1722
  def test_bulk_error
1750
1723
  stub_elastic_ping
1751
- stub_elastic_bulk_error
1752
-
1753
- assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError) {
1754
- driver.run(default_tag: 'test', shutdown: false) do
1755
- driver.feed(sample_record)
1756
- driver.feed(sample_record)
1757
- driver.feed(sample_record)
1758
- end
1759
- }
1760
- end
1761
-
1762
- def test_bulk_error_version_mismatch
1763
- stub_elastic_ping
1764
- stub_elastic_version_mismatch
1765
-
1766
- assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchVersionMismatch) {
1767
- driver.run(default_tag: 'test', shutdown: false) do
1768
- driver.feed(sample_record)
1769
- driver.feed(sample_record)
1770
- driver.feed(sample_record)
1771
- end
1772
- }
1773
- end
1774
-
1775
- def test_bulk_index_into_a_create
1776
- stub_elastic_ping
1777
- stub_elastic_index_to_create
1778
-
1779
- assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError) {
1780
- driver.run(default_tag: 'test', shutdown: false) do
1781
- driver.feed(sample_record)
1782
- end
1783
- }
1784
- assert(index_cmds[0].has_key?("create"))
1785
- end
1786
-
1787
- def test_bulk_unexpected_response_op
1788
- stub_elastic_ping
1789
- stub_elastic_unexpected_response_op
1790
-
1791
- assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchVersionMismatch) {
1792
- driver.run(default_tag: 'test', shutdown: false) do
1793
- driver.feed(sample_record)
1794
- end
1795
- }
1724
+ stub_request(:post, 'http://localhost:9200/_bulk')
1725
+ .to_return(lambda do |req|
1726
+ { :status => 200,
1727
+ :headers => { 'Content-Type' => 'json' },
1728
+ :body => %({
1729
+ "took" : 1,
1730
+ "errors" : true,
1731
+ "items" : [
1732
+ {
1733
+ "create" : {
1734
+ "_index" : "foo",
1735
+ "_type" : "bar",
1736
+ "_id" : "abc",
1737
+ "status" : 500,
1738
+ "error" : {
1739
+ "type" : "some unrecognized type",
1740
+ "reason":"some error to cause version mismatch"
1741
+ }
1742
+ }
1743
+ },
1744
+ {
1745
+ "create" : {
1746
+ "_index" : "foo",
1747
+ "_type" : "bar",
1748
+ "_id" : "abc",
1749
+ "status" : 201
1750
+ }
1751
+ },
1752
+ {
1753
+ "create" : {
1754
+ "_index" : "foo",
1755
+ "_type" : "bar",
1756
+ "_id" : "abc",
1757
+ "status" : 500,
1758
+ "error" : {
1759
+ "type" : "some unrecognized type",
1760
+ "reason":"some error to cause version mismatch"
1761
+ }
1762
+ }
1763
+ },
1764
+ {
1765
+ "create" : {
1766
+ "_index" : "foo",
1767
+ "_type" : "bar",
1768
+ "_id" : "abc",
1769
+ "_id" : "abc",
1770
+ "status" : 409
1771
+ }
1772
+ }
1773
+ ]
1774
+ })
1775
+ }
1776
+ end)
1777
+
1778
+ driver.run(default_tag: 'test') do
1779
+ driver.feed(1, sample_record)
1780
+ driver.feed(2, sample_record)
1781
+ driver.feed(3, sample_record)
1782
+ driver.feed(4, sample_record)
1783
+ end
1784
+
1785
+ expect = [['test', 1, sample_record],
1786
+ ['test', 3, sample_record]]
1787
+ assert_equal expect, driver.events
1796
1788
  end
1797
1789
 
1798
1790
  def test_update_should_not_write_if_theres_no_id
@@ -1979,4 +1971,5 @@ class ElasticsearchOutput < Test::Unit::TestCase
1979
1971
  end
1980
1972
  assert(index_cmds[0].has_key?("create"))
1981
1973
  end
1974
+
1982
1975
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.2
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - diogo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-04-24 00:00:00.000000000 Z
12
+ date: 2018-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd