fluent-plugin-elasticsearch 1.9.4 → 5.0.3

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.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  4. data/.github/workflows/issue-auto-closer.yml +12 -0
  5. data/.github/workflows/linux.yml +26 -0
  6. data/.github/workflows/macos.yml +26 -0
  7. data/.github/workflows/windows.yml +26 -0
  8. data/.travis.yml +33 -6
  9. data/CONTRIBUTING.md +24 -0
  10. data/Gemfile +4 -1
  11. data/History.md +445 -1
  12. data/ISSUE_TEMPLATE.md +19 -0
  13. data/README.ElasticsearchGenID.md +116 -0
  14. data/README.ElasticsearchInput.md +293 -0
  15. data/README.Troubleshooting.md +692 -0
  16. data/README.md +1013 -38
  17. data/appveyor.yml +20 -0
  18. data/fluent-plugin-elasticsearch.gemspec +15 -9
  19. data/{Gemfile.v0.12 → gemfiles/Gemfile.elasticsearch.v6} +6 -5
  20. data/lib/fluent/log-ext.rb +38 -0
  21. data/lib/fluent/plugin/default-ilm-policy.json +14 -0
  22. data/lib/fluent/plugin/elasticsearch_constants.rb +13 -0
  23. data/lib/fluent/plugin/elasticsearch_error.rb +5 -0
  24. data/lib/fluent/plugin/elasticsearch_error_handler.rb +129 -0
  25. data/lib/fluent/plugin/elasticsearch_fallback_selector.rb +9 -0
  26. data/lib/fluent/plugin/elasticsearch_index_lifecycle_management.rb +67 -0
  27. data/lib/fluent/plugin/elasticsearch_index_template.rb +186 -12
  28. data/lib/fluent/plugin/elasticsearch_simple_sniffer.rb +10 -0
  29. data/lib/fluent/plugin/elasticsearch_tls.rb +70 -0
  30. data/lib/fluent/plugin/filter_elasticsearch_genid.rb +77 -0
  31. data/lib/fluent/plugin/in_elasticsearch.rb +325 -0
  32. data/lib/fluent/plugin/oj_serializer.rb +22 -0
  33. data/lib/fluent/plugin/out_elasticsearch.rb +1008 -267
  34. data/lib/fluent/plugin/out_elasticsearch_data_stream.rb +218 -0
  35. data/lib/fluent/plugin/out_elasticsearch_dynamic.rb +232 -214
  36. data/test/plugin/test_alias_template.json +9 -0
  37. data/test/plugin/test_elasticsearch_error_handler.rb +646 -0
  38. data/test/plugin/test_elasticsearch_fallback_selector.rb +74 -0
  39. data/test/plugin/test_elasticsearch_index_lifecycle_management.rb +66 -0
  40. data/test/plugin/test_elasticsearch_tls.rb +145 -0
  41. data/test/plugin/test_filter_elasticsearch_genid.rb +215 -0
  42. data/test/plugin/test_in_elasticsearch.rb +459 -0
  43. data/test/plugin/test_index_alias_template.json +11 -0
  44. data/test/plugin/test_index_template.json +25 -0
  45. data/test/plugin/test_oj_serializer.rb +19 -0
  46. data/test/plugin/test_out_elasticsearch.rb +5029 -387
  47. data/test/plugin/test_out_elasticsearch_data_stream.rb +337 -0
  48. data/test/plugin/test_out_elasticsearch_dynamic.rb +681 -208
  49. data/test/test_log-ext.rb +35 -0
  50. metadata +97 -19
@@ -1,17 +1,30 @@
1
- require 'helper'
1
+ require_relative '../helper'
2
2
  require 'date'
3
+ require 'fluent/test/helpers'
4
+ require 'fluent/test/driver/output'
5
+ require 'flexmock/test_unit'
6
+ require 'fluent/plugin/out_elasticsearch_dynamic'
3
7
 
4
8
  class ElasticsearchOutputDynamic < Test::Unit::TestCase
9
+ include FlexMock::TestCase
10
+ include Fluent::Test::Helpers
11
+
5
12
  attr_accessor :index_cmds, :index_command_counts
6
13
 
7
14
  def setup
8
15
  Fluent::Test.setup
9
- require 'fluent/plugin/out_elasticsearch_dynamic'
10
16
  @driver = nil
11
17
  end
12
18
 
13
- def driver(tag='test', conf='')
14
- @driver ||= Fluent::Test::BufferedOutputTestDriver.new(Fluent::ElasticsearchOutputDynamic, tag) {
19
+ def driver(conf='', es_version=5)
20
+ # For request stub to detect compatibility.
21
+ @es_version ||= es_version
22
+ Fluent::Plugin::ElasticsearchOutputDynamic.module_eval(<<-CODE)
23
+ def detect_es_major_version
24
+ #{@es_version}
25
+ end
26
+ CODE
27
+ @driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutputDynamic) {
15
28
  # v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
16
29
  if !defined?(Fluent::Plugin::Output)
17
30
  def format(tag, time, record)
@@ -21,12 +34,18 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
21
34
  }.configure(conf)
22
35
  end
23
36
 
37
+ def default_type_name
38
+ Fluent::Plugin::ElasticsearchOutput::DEFAULT_TYPE_NAME
39
+ end
40
+
24
41
  def sample_record
25
42
  {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}
26
43
  end
27
44
 
28
- def stub_elastic_ping(url="http://localhost:9200")
29
- stub_request(:head, url).to_return(:status => 200, :body => "", :headers => {})
45
+ def nested_sample_record
46
+ {'nested' =>
47
+ {'age' => 26, 'parent_id' => 'parent', 'routing_id' => 'routing', 'request_id' => '42'}
48
+ }
30
49
  end
31
50
 
32
51
  def stub_elastic(url="http://localhost:9200/_bulk")
@@ -39,6 +58,10 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
39
58
  stub_request(:post, url).to_return(:status => [503, "Service Unavailable"])
40
59
  end
41
60
 
61
+ def stub_elastic_timeout(url="http://localhost:9200/_bulk")
62
+ stub_request(:post, url).to_timeout
63
+ end
64
+
42
65
  def stub_elastic_with_store_index_command_counts(url="http://localhost:9200/_bulk")
43
66
  if @index_command_counts == nil
44
67
  @index_command_counts = {}
@@ -51,6 +74,11 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
51
74
  end
52
75
  end
53
76
 
77
+ def assert_logs_include(logs, msg, exp_matches=1)
78
+ matches = logs.grep /#{msg}/
79
+ assert_equal(exp_matches, matches.length, "Logs do not contain '#{msg}' '#{logs}'")
80
+ end
81
+
54
82
  def test_configure
55
83
  config = %{
56
84
  host logs.google.com
@@ -60,14 +88,125 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
60
88
  user john
61
89
  password doe
62
90
  }
63
- instance = driver('test', config).instance
91
+ instance = driver(config).instance
64
92
 
65
93
  conf = instance.dynamic_config
66
94
  assert_equal 'logs.google.com', conf['host']
67
95
  assert_equal "777", conf['port']
96
+ assert_equal :https, instance.scheme
68
97
  assert_equal 'john', instance.user
69
98
  assert_equal 'doe', instance.password
70
99
  assert_equal '/es/', instance.path
100
+ assert_equal Fluent::Plugin::ElasticsearchTLS::DEFAULT_VERSION, instance.ssl_version
101
+ assert_nil instance.ssl_max_version
102
+ assert_nil instance.ssl_min_version
103
+ if Fluent::Plugin::ElasticsearchTLS::USE_TLS_MINMAX_VERSION
104
+ if defined?(OpenSSL::SSL::TLS1_3_VERSION)
105
+ assert_equal({max_version: OpenSSL::SSL::TLS1_3_VERSION, min_version: OpenSSL::SSL::TLS1_2_VERSION},
106
+ instance.ssl_version_options)
107
+ else
108
+ assert_equal({max_version: nil, min_version: OpenSSL::SSL::TLS1_2_VERSION},
109
+ instance.ssl_version_options)
110
+ end
111
+ else
112
+ assert_equal({version: Fluent::Plugin::ElasticsearchTLS::DEFAULT_VERSION},
113
+ instance.ssl_version_options)
114
+ end
115
+ assert_nil instance.client_key
116
+ assert_nil instance.client_cert
117
+ assert_nil instance.client_key_pass
118
+ assert_false instance.with_transporter_log
119
+ assert_equal :"application/json", instance.content_type
120
+ assert_equal :excon, instance.http_backend
121
+ assert_false instance.compression
122
+ assert_equal :no_compression, instance.compression_level
123
+ end
124
+
125
+ test 'configure compression' do
126
+ omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
127
+
128
+ config = %{
129
+ compression_level best_compression
130
+ }
131
+ instance = driver(config).instance
132
+
133
+ assert_equal true, instance.compression
134
+ end
135
+
136
+ test 'check compression strategy' do
137
+ omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
138
+
139
+ config = %{
140
+ compression_level best_speed
141
+ }
142
+ instance = driver(config).instance
143
+
144
+ assert_equal Zlib::BEST_SPEED, instance.compression_strategy
145
+ end
146
+
147
+ test 'check content-encoding header with compression' do
148
+ omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
149
+
150
+ config = %{
151
+ compression_level best_compression
152
+ }
153
+ instance = driver(config).instance
154
+
155
+ assert_equal nil, instance.client.transport.options[:transport_options][:headers]["Content-Encoding"]
156
+
157
+ stub_request(:post, "http://localhost:9200/_bulk").
158
+ to_return(status: 200, body: "", headers: {})
159
+ driver.run(default_tag: 'test') do
160
+ driver.feed(sample_record)
161
+ end
162
+ compressable = instance.compressable_connection
163
+
164
+ assert_equal "gzip", instance.client(nil, compressable).transport.options[:transport_options][:headers]["Content-Encoding"]
165
+ end
166
+
167
+ test 'check compression option is passed to transport' do
168
+ omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
169
+
170
+ config = %{
171
+ compression_level best_compression
172
+ }
173
+ instance = driver(config).instance
174
+
175
+ assert_equal false, instance.client.transport.options[:compression]
176
+
177
+ stub_request(:post, "http://localhost:9200/_bulk").
178
+ to_return(status: 200, body: "", headers: {})
179
+ driver.run(default_tag: 'test') do
180
+ driver.feed(sample_record)
181
+ end
182
+ compressable = instance.compressable_connection
183
+
184
+ assert_equal true, instance.client(nil, compressable).transport.options[:compression]
185
+ end
186
+
187
+ test 'configure Content-Type' do
188
+ config = %{
189
+ content_type application/x-ndjson
190
+ }
191
+ instance = driver(config).instance
192
+ assert_equal :"application/x-ndjson", instance.content_type
193
+ end
194
+
195
+ test 'invalid Content-Type' do
196
+ config = %{
197
+ content_type nonexistent/invalid
198
+ }
199
+ assert_raise(Fluent::ConfigError) {
200
+ driver(config)
201
+ }
202
+ end
203
+
204
+ test 'Detected Elasticsearch 7' do
205
+ config = %{
206
+ type_name changed
207
+ }
208
+ instance = driver(config, 7).instance
209
+ assert_equal '_doc', instance.type_name
71
210
  end
72
211
 
73
212
  def test_defaults
@@ -78,7 +217,7 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
78
217
  user john
79
218
  password doe
80
219
  }
81
- instance = driver('test', config).instance
220
+ instance = driver(config).instance
82
221
 
83
222
  conf = instance.dynamic_config
84
223
  assert_equal "9200", conf['port']
@@ -94,7 +233,7 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
94
233
  path /es/
95
234
  port 123
96
235
  }
97
- instance = driver('test', config).instance
236
+ instance = driver(config).instance
98
237
 
99
238
  assert_equal 3, instance.get_connection_options(nil)[:hosts].length
100
239
  host1, host2, host3 = instance.get_connection_options(nil)[:hosts]
@@ -116,7 +255,7 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
116
255
  user default_user
117
256
  password default_password
118
257
  }
119
- instance = driver('test', config).instance
258
+ instance = driver(config).instance
120
259
 
121
260
  assert_equal 2, instance.get_connection_options(nil)[:hosts].length
122
261
  host1, host2 = instance.get_connection_options(nil)[:hosts]
@@ -135,13 +274,39 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
135
274
  assert_equal '/default_path', host2[:path]
136
275
  end
137
276
 
277
+ def test_hosts_list_with_escape_placeholders
278
+ config = %{
279
+ hosts https://%{j+hn}:%{passw@rd}@host1:443/elastic/,http://host2
280
+ path /default_path
281
+ user default_user
282
+ password default_password
283
+ }
284
+ instance = driver(config).instance
285
+
286
+ assert_equal 2, instance.get_connection_options(nil)[:hosts].length
287
+ host1, host2 = instance.get_connection_options(nil)[:hosts]
288
+
289
+ assert_equal 'host1', host1[:host]
290
+ assert_equal 443, host1[:port]
291
+ assert_equal 'https', host1[:scheme]
292
+ assert_equal 'j%2Bhn', host1[:user]
293
+ assert_equal 'passw%40rd', host1[:password]
294
+ assert_equal '/elastic/', host1[:path]
295
+
296
+ assert_equal 'host2', host2[:host]
297
+ assert_equal 'http', host2[:scheme]
298
+ assert_equal 'default_user', host2[:user]
299
+ assert_equal 'default_password', host2[:password]
300
+ assert_equal '/default_path', host2[:path]
301
+ end
302
+
138
303
  def test_single_host_params_and_defaults
139
304
  config = %{
140
305
  host logs.google.com
141
306
  user john
142
307
  password doe
143
308
  }
144
- instance = driver('test', config).instance
309
+ instance = driver(config).instance
145
310
 
146
311
  assert_equal 1, instance.get_connection_options(nil)[:hosts].length
147
312
  host1 = instance.get_connection_options(nil)[:hosts][0]
@@ -154,74 +319,141 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
154
319
  assert_equal nil, host1[:path]
155
320
  end
156
321
 
322
+ def test_single_host_params_and_defaults_with_escape_placeholders
323
+ config = %{
324
+ host logs.google.com
325
+ user %{j+hn}
326
+ password %{d@e}
327
+ }
328
+ instance = driver(config).instance
329
+
330
+ assert_equal 1, instance.get_connection_options(nil)[:hosts].length
331
+ host1 = instance.get_connection_options(nil)[:hosts][0]
332
+
333
+ assert_equal 'logs.google.com', host1[:host]
334
+ assert_equal 9200, host1[:port]
335
+ assert_equal 'http', host1[:scheme]
336
+ assert_equal 'j%2Bhn', host1[:user]
337
+ assert_equal 'd%40e', host1[:password]
338
+ assert_equal nil, host1[:path]
339
+ end
340
+
157
341
  def test_content_type_header
158
342
  stub_request(:head, "http://localhost:9200/").
159
343
  to_return(:status => 200, :body => "", :headers => {})
160
- elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
161
- with(headers: { "Content-Type" => "application/json" })
162
- driver.emit(sample_record)
163
- driver.run
344
+ if Elasticsearch::VERSION >= "6.0.2"
345
+ elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
346
+ with(headers: { "Content-Type" => "application/x-ndjson" })
347
+ else
348
+ elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
349
+ with(headers: { "Content-Type" => "application/json" })
350
+ end
351
+ driver.run(default_tag: 'test') do
352
+ driver.feed(sample_record)
353
+ end
164
354
  assert_requested(elastic_request)
165
355
  end
166
356
 
167
357
  def test_writes_to_default_index
168
- stub_elastic_ping
169
358
  stub_elastic
170
- driver.emit(sample_record)
171
- driver.run
359
+ driver.run(default_tag: 'test') do
360
+ driver.feed(sample_record)
361
+ end
172
362
  assert_equal('fluentd', index_cmds.first['index']['_index'])
173
363
  end
174
364
 
365
+ # gzip compress data
366
+ def gzip(string, strategy)
367
+ wio = StringIO.new("w")
368
+ w_gz = Zlib::GzipWriter.new(wio, strategy = strategy)
369
+ w_gz.write(string)
370
+ w_gz.close
371
+ wio.string
372
+ end
373
+
374
+ def test_writes_to_default_index_with_compression
375
+ omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
376
+
377
+ config = %[
378
+ compression_level default_compression
379
+ ]
380
+
381
+ bodystr = %({
382
+ "took" : 500,
383
+ "errors" : false,
384
+ "items" : [
385
+ {
386
+ "create": {
387
+ "_index" : "fluentd",
388
+ "_type" : "fluentd"
389
+ }
390
+ }
391
+ ]
392
+ })
393
+
394
+ compressed_body = gzip(bodystr, Zlib::DEFAULT_COMPRESSION)
395
+
396
+ elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
397
+ to_return(:status => 200, :headers => {'Content-Type' => 'Application/json'}, :body => compressed_body)
398
+
399
+ driver(config)
400
+ driver.run(default_tag: 'test') do
401
+ driver.feed(sample_record)
402
+ end
403
+
404
+ assert_requested(elastic_request)
405
+ end
406
+
175
407
  def test_writes_to_default_type
176
- stub_elastic_ping
177
408
  stub_elastic
178
- driver.emit(sample_record)
179
- driver.run
180
- assert_equal('fluentd', index_cmds.first['index']['_type'])
409
+ driver.run(default_tag: 'test') do
410
+ driver.feed(sample_record)
411
+ end
412
+ assert_equal(default_type_name, index_cmds.first['index']['_type'])
181
413
  end
182
414
 
183
- def test_writes_to_speficied_index
415
+ def test_writes_to_specified_index
184
416
  driver.configure("index_name myindex\n")
185
- stub_elastic_ping
186
417
  stub_elastic
187
- driver.emit(sample_record)
188
- driver.run
418
+ driver.run(default_tag: 'test') do
419
+ driver.feed(sample_record)
420
+ end
189
421
  assert_equal('myindex', index_cmds.first['index']['_index'])
190
422
  end
191
423
 
192
- def test_writes_to_speficied_index_uppercase
424
+ def test_writes_to_specified_index_uppercase
193
425
  driver.configure("index_name MyIndex\n")
194
- stub_elastic_ping
195
426
  stub_elastic
196
- driver.emit(sample_record)
197
- driver.run
427
+ driver.run(default_tag: 'test') do
428
+ driver.feed(sample_record)
429
+ end
198
430
  assert_equal('myindex', index_cmds.first['index']['_index'])
199
431
  end
200
432
 
201
- def test_writes_to_speficied_type
433
+ def test_writes_to_specified_type
202
434
  driver.configure("type_name mytype\n")
203
- stub_elastic_ping
204
435
  stub_elastic
205
- driver.emit(sample_record)
206
- driver.run
436
+ driver.run(default_tag: 'test') do
437
+ driver.feed(sample_record)
438
+ end
207
439
  assert_equal('mytype', index_cmds.first['index']['_type'])
208
440
  end
209
441
 
210
- def test_writes_to_speficied_host
442
+ def test_writes_to_specified_host
211
443
  driver.configure("host 192.168.33.50\n")
212
- stub_elastic_ping("http://192.168.33.50:9200")
213
444
  elastic_request = stub_elastic("http://192.168.33.50:9200/_bulk")
214
- driver.emit(sample_record)
215
- driver.run
445
+ driver.run(default_tag: 'test') do
446
+ driver.feed(sample_record)
447
+ end
216
448
  assert_requested(elastic_request)
217
449
  end
218
450
 
219
- def test_writes_to_speficied_port
451
+ def test_writes_to_specified_port
220
452
  driver.configure("port 9201\n")
221
- stub_elastic_ping("http://localhost:9201")
222
453
  elastic_request = stub_elastic("http://localhost:9201/_bulk")
223
- driver.emit(sample_record)
224
- driver.run
454
+ driver.run(default_tag: 'test') do
455
+ driver.feed(sample_record)
456
+ end
225
457
  assert_requested(elastic_request)
226
458
  end
227
459
 
@@ -233,16 +465,14 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
233
465
 
234
466
  hosts.each do |host_info|
235
467
  host, port = host_info
236
- stub_elastic_ping("http://#{host}:#{port}")
237
468
  stub_elastic_with_store_index_command_counts("http://#{host}:#{port}/_bulk")
238
469
  end
239
470
 
240
- 1000.times do
241
- driver.emit(sample_record.merge('age'=>rand(100)))
471
+ driver.run(default_tag: 'test') do
472
+ 1000.times do
473
+ driver.feed(sample_record.merge('age'=>rand(100)))
474
+ end
242
475
  end
243
-
244
- driver.run
245
-
246
476
  # @note: we cannot make multi chunks with options (flush_interval, buffer_chunk_limit)
247
477
  # it's Fluentd test driver's constraint
248
478
  # so @index_command_counts.size is always 1
@@ -256,81 +486,129 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
256
486
  assert_equal(2000, total)
257
487
  end
258
488
 
489
+ def test_nested_record_with_flattening_on
490
+ driver.configure("flatten_hashes true
491
+ flatten_hashes_separator |")
492
+
493
+ original_hash = {"foo" => {"bar" => "baz"}, "people" => [
494
+ {"age" => "25", "height" => "1ft"},
495
+ {"age" => "30", "height" => "2ft"}
496
+ ]}
497
+
498
+ expected_output = {"foo|bar"=>"baz", "people" => [
499
+ {"age" => "25", "height" => "1ft"},
500
+ {"age" => "30", "height" => "2ft"}
501
+ ]}
502
+
503
+ stub_elastic
504
+ driver.run(default_tag: 'test') do
505
+ driver.feed(original_hash)
506
+ end
507
+ assert_equal expected_output, index_cmds[1]
508
+ end
509
+
510
+ def test_nested_record_with_flattening_off
511
+ # flattening off by default
512
+
513
+ original_hash = {"foo" => {"bar" => "baz"}}
514
+ expected_output = {"foo" => {"bar" => "baz"}}
515
+
516
+ stub_elastic
517
+ driver.run(default_tag: 'test') do
518
+ driver.feed(original_hash)
519
+ end
520
+ assert_equal expected_output, index_cmds[1]
521
+ end
522
+
259
523
  def test_makes_bulk_request
260
- stub_elastic_ping
261
524
  stub_elastic
262
- driver.emit(sample_record)
263
- driver.emit(sample_record.merge('age' => 27))
264
- driver.run
525
+ driver.run(default_tag: 'test') do
526
+ driver.feed(sample_record)
527
+ driver.feed(sample_record.merge('age' => 27))
528
+ end
265
529
  assert_equal(4, index_cmds.count)
266
530
  end
267
531
 
268
532
  def test_all_records_are_preserved_in_bulk
269
- stub_elastic_ping
270
533
  stub_elastic
271
- driver.emit(sample_record)
272
- driver.emit(sample_record.merge('age' => 27))
273
- driver.run
534
+ driver.run(default_tag: 'test') do
535
+ driver.feed(sample_record)
536
+ driver.feed(sample_record.merge('age' => 27))
537
+ end
274
538
  assert_equal(26, index_cmds[1]['age'])
275
539
  assert_equal(27, index_cmds[3]['age'])
276
540
  end
277
541
 
278
542
  def test_writes_to_logstash_index
279
543
  driver.configure("logstash_format true\n")
280
- time = Time.parse Date.today.to_s
544
+ time = Time.parse Date.today.iso8601
281
545
  logstash_index = "logstash-#{time.getutc.strftime("%Y.%m.%d")}"
282
- stub_elastic_ping
283
546
  stub_elastic
284
- driver.emit(sample_record, time.to_i)
285
- driver.run
547
+ driver.run(default_tag: 'test') do
548
+ driver.feed(time.to_i, sample_record)
549
+ end
286
550
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
287
551
  end
288
552
 
289
553
  def test_writes_to_logstash_utc_index
290
554
  driver.configure("logstash_format true
291
555
  utc_index false")
292
- time = Time.parse Date.today.to_s
556
+ time = Time.parse Date.today.iso8601
293
557
  utc_index = "logstash-#{time.strftime("%Y.%m.%d")}"
294
- stub_elastic_ping
295
558
  stub_elastic
296
- driver.emit(sample_record, time.to_i)
297
- driver.run
559
+ driver.run(default_tag: 'test') do
560
+ driver.feed(time.to_i, sample_record)
561
+ end
298
562
  assert_equal(utc_index, index_cmds.first['index']['_index'])
299
563
  end
300
564
 
301
565
  def test_writes_to_logstash_index_with_specified_prefix
302
566
  driver.configure("logstash_format true
303
567
  logstash_prefix myprefix")
304
- time = Time.parse Date.today.to_s
568
+ time = Time.parse Date.today.iso8601
305
569
  logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
306
- stub_elastic_ping
307
570
  stub_elastic
308
- driver.emit(sample_record, time.to_i)
309
- driver.run
571
+ driver.run(default_tag: 'test') do
572
+ driver.feed(time.to_i, sample_record)
573
+ end
574
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
575
+ end
576
+
577
+ def test_writes_to_logstash_index_with_specified_prefix_and_separator
578
+ separator = '_'
579
+ driver.configure("logstash_format true
580
+ logstash_prefix_separator #{separator}
581
+ logstash_prefix myprefix")
582
+ time = Time.parse Date.today.iso8601
583
+ logstash_index = "myprefix#{separator}#{time.getutc.strftime("%Y.%m.%d")}"
584
+ stub_elastic
585
+ driver.run(default_tag: 'test') do
586
+ driver.feed(time.to_i, sample_record)
587
+ end
310
588
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
311
589
  end
312
590
 
313
591
  def test_writes_to_logstash_index_with_specified_prefix_uppercase
314
592
  driver.configure("logstash_format true
315
593
  logstash_prefix MyPrefix")
316
- time = Time.parse Date.today.to_s
594
+ time = Time.parse Date.today.iso8601
317
595
  logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
318
- stub_elastic_ping
319
596
  stub_elastic
320
- driver.emit(sample_record, time.to_i)
321
- driver.run
597
+ driver.run(default_tag: 'test') do
598
+ driver.feed(time.to_i, sample_record)
599
+ end
322
600
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
323
601
  end
324
602
 
325
603
  def test_writes_to_logstash_index_with_specified_dateformat
326
604
  driver.configure("logstash_format true
327
605
  logstash_dateformat %Y.%m")
328
- time = Time.parse Date.today.to_s
606
+ time = Time.parse Date.today.iso8601
329
607
  logstash_index = "logstash-#{time.getutc.strftime("%Y.%m")}"
330
- stub_elastic_ping
331
608
  stub_elastic
332
- driver.emit(sample_record, time.to_i)
333
- driver.run
609
+ driver.run(default_tag: 'test') do
610
+ driver.feed(time.to_i, sample_record)
611
+ end
334
612
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
335
613
  end
336
614
 
@@ -338,302 +616,484 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
338
616
  driver.configure("logstash_format true
339
617
  logstash_prefix myprefix
340
618
  logstash_dateformat %Y.%m")
341
- time = Time.parse Date.today.to_s
619
+ time = Time.parse Date.today.iso8601
342
620
  logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m")}"
343
- stub_elastic_ping
344
621
  stub_elastic
345
- driver.emit(sample_record, time.to_i)
346
- driver.run
622
+ driver.run(default_tag: 'test') do
623
+ driver.feed(time.to_i, sample_record)
624
+ end
347
625
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
348
626
  end
349
627
 
350
628
  def test_doesnt_add_logstash_timestamp_by_default
351
- stub_elastic_ping
352
629
  stub_elastic
353
- driver.emit(sample_record)
354
- driver.run
630
+ driver.run(default_tag: 'test') do
631
+ driver.feed(sample_record)
632
+ end
355
633
  assert_nil(index_cmds[1]['@timestamp'])
356
634
  end
357
635
 
358
636
  def test_adds_logstash_timestamp_when_configured
359
637
  driver.configure("logstash_format true\n")
360
- stub_elastic_ping
361
638
  stub_elastic
362
- ts = DateTime.now.to_s
363
- driver.emit(sample_record)
364
- driver.run
639
+ time = Fluent::EventTime.new(Time.now.to_i, 123456789)
640
+ driver.run(default_tag: 'test') do
641
+ driver.feed(time, sample_record)
642
+ end
365
643
  assert(index_cmds[1].has_key? '@timestamp')
366
- assert_equal(index_cmds[1]['@timestamp'], ts)
644
+ assert_equal(Time.at(time).iso8601(9), index_cmds[1]['@timestamp'])
645
+ end
646
+
647
+ def test_uses_subsecond_precision_when_configured
648
+ driver.configure("logstash_format true
649
+ time_precision 3\n")
650
+ stub_elastic
651
+ time = Fluent::EventTime.new(Time.now.to_i, 123456789)
652
+ driver.run(default_tag: 'test') do
653
+ driver.feed(time, sample_record)
654
+ end
655
+ assert(index_cmds[1].has_key? '@timestamp')
656
+ assert_equal(Time.at(time).iso8601(3), index_cmds[1]['@timestamp'])
367
657
  end
368
658
 
369
659
  def test_uses_custom_timestamp_when_included_in_record
660
+ driver.configure("include_timestamp true\n")
661
+ stub_elastic
662
+ ts = DateTime.new(2001,2,3).iso8601
663
+ driver.run(default_tag: 'test') do
664
+ driver.feed(sample_record.merge!('@timestamp' => ts))
665
+ end
666
+ assert(index_cmds[1].has_key? '@timestamp')
667
+ assert_equal(ts, index_cmds[1]['@timestamp'])
668
+ end
669
+
670
+ def test_uses_custom_timestamp_when_included_in_record_logstash
370
671
  driver.configure("logstash_format true\n")
371
- stub_elastic_ping
372
672
  stub_elastic
373
- ts = DateTime.new(2001,2,3).to_s
374
- driver.emit(sample_record.merge!('@timestamp' => ts))
375
- driver.run
673
+ ts = DateTime.new(2001,2,3).iso8601
674
+ driver.run(default_tag: 'test') do
675
+ driver.feed(sample_record.merge!('@timestamp' => ts))
676
+ end
376
677
  assert(index_cmds[1].has_key? '@timestamp')
377
- assert_equal(index_cmds[1]['@timestamp'], ts)
678
+ assert_equal(ts, index_cmds[1]['@timestamp'])
378
679
  end
379
680
 
380
- def test_uses_custom_time_key
681
+ def test_uses_custom_time_key_logstash
381
682
  driver.configure("logstash_format true
382
683
  time_key vtm\n")
383
- stub_elastic_ping
384
684
  stub_elastic
385
- ts = DateTime.new(2001,2,3).to_s
386
- driver.emit(sample_record.merge!('vtm' => ts))
387
- driver.run
685
+ ts = DateTime.new(2001,2,3).iso8601
686
+ driver.run(default_tag: 'test') do
687
+ driver.feed(sample_record.merge!('vtm' => ts))
688
+ end
689
+ assert(index_cmds[1].has_key? '@timestamp')
690
+ assert_equal(ts, index_cmds[1]['@timestamp'])
691
+ end
692
+
693
+ def test_uses_custom_time_key_timestamp
694
+ driver.configure("include_timestamp true
695
+ time_key vtm\n")
696
+ stub_elastic
697
+ ts = DateTime.new(2001,2,3).iso8601
698
+ driver.run(default_tag: 'test') do
699
+ driver.feed(sample_record.merge!('vtm' => ts))
700
+ end
701
+ assert(index_cmds[1].has_key? '@timestamp')
702
+ assert_equal(ts, index_cmds[1]['@timestamp'])
703
+ end
704
+
705
+ def test_uses_custom_time_key_timestamp_custom_index
706
+ driver.configure("include_timestamp true
707
+ index_name test
708
+ time_key vtm\n")
709
+ stub_elastic
710
+ ts = DateTime.new(2001,2,3).iso8601
711
+ driver.run(default_tag: 'test') do
712
+ driver.feed(sample_record.merge!('vtm' => ts))
713
+ end
388
714
  assert(index_cmds[1].has_key? '@timestamp')
389
- assert_equal(index_cmds[1]['@timestamp'], ts)
715
+ assert_equal(ts, index_cmds[1]['@timestamp'])
716
+ assert_equal('test', index_cmds.first['index']['_index'])
390
717
  end
391
718
 
392
719
  def test_uses_custom_time_key_exclude_timestamp
720
+ driver.configure("include_timestamp true
721
+ time_key vtm
722
+ time_key_exclude_timestamp true\n")
723
+ stub_elastic
724
+ ts = DateTime.new(2001,2,3).iso8601
725
+ driver.run(default_tag: 'test') do
726
+ driver.feed(sample_record.merge!('vtm' => ts))
727
+ end
728
+ assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
729
+ end
730
+
731
+ def test_uses_custom_time_key_exclude_timestamp_logstash
393
732
  driver.configure("logstash_format true
394
733
  time_key vtm
395
734
  time_key_exclude_timestamp true\n")
396
- stub_elastic_ping
397
735
  stub_elastic
398
- ts = DateTime.new(2001,2,3).to_s
399
- driver.emit(sample_record.merge!('vtm' => ts))
400
- driver.run
736
+ ts = DateTime.new(2001,2,3).iso8601
737
+ driver.run(default_tag: 'test') do
738
+ driver.feed(sample_record.merge!('vtm' => ts))
739
+ end
401
740
  assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
402
741
  end
403
742
 
404
743
  def test_doesnt_add_tag_key_by_default
405
- stub_elastic_ping
406
744
  stub_elastic
407
- driver.emit(sample_record)
408
- driver.run
745
+ driver.run(default_tag: 'test') do
746
+ driver.feed(sample_record)
747
+ end
409
748
  assert_nil(index_cmds[1]['tag'])
410
749
  end
411
750
 
412
751
  def test_adds_tag_key_when_configured
413
- driver('mytag').configure("include_tag_key true\n")
414
- stub_elastic_ping
752
+ driver.configure("include_tag_key true\n")
415
753
  stub_elastic
416
- driver.emit(sample_record)
417
- driver.run
754
+ driver.run(default_tag: 'mytag') do
755
+ driver.feed(sample_record)
756
+ end
418
757
  assert(index_cmds[1].has_key?('tag'))
419
- assert_equal(index_cmds[1]['tag'], 'mytag')
758
+ assert_equal('mytag', index_cmds[1]['tag'])
420
759
  end
421
760
 
422
761
  def test_adds_id_key_when_configured
423
762
  driver.configure("id_key request_id\n")
424
- stub_elastic_ping
425
763
  stub_elastic
426
- driver.emit(sample_record)
427
- driver.run
428
- assert_equal(index_cmds[0]['index']['_id'], '42')
764
+ driver.run(default_tag: 'test') do
765
+ driver.feed(sample_record)
766
+ end
767
+ assert_equal('42', index_cmds[0]['index']['_id'])
768
+ end
769
+
770
+ class NestedIdKeyTest < self
771
+ def test_adds_nested_id_key_with_dot
772
+ driver.configure("id_key nested.request_id\n")
773
+ stub_elastic
774
+ driver.run(default_tag: 'test') do
775
+ driver.feed(nested_sample_record)
776
+ end
777
+ assert_equal('42', index_cmds[0]['index']['_id'])
778
+ end
779
+
780
+ def test_adds_nested_id_key_with_dollar_dot
781
+ driver.configure("id_key $.nested.request_id\n")
782
+ stub_elastic
783
+ driver.run(default_tag: 'test') do
784
+ driver.feed(nested_sample_record)
785
+ end
786
+ assert_equal('42', index_cmds[0]['index']['_id'])
787
+ end
788
+
789
+ def test_adds_nested_id_key_with_bracket
790
+ driver.configure("id_key $['nested']['request_id']\n")
791
+ stub_elastic
792
+ driver.run(default_tag: 'test') do
793
+ driver.feed(nested_sample_record)
794
+ end
795
+ assert_equal('42', index_cmds[0]['index']['_id'])
796
+ end
429
797
  end
430
798
 
431
799
  def test_doesnt_add_id_key_if_missing_when_configured
432
800
  driver.configure("id_key another_request_id\n")
433
- stub_elastic_ping
434
801
  stub_elastic
435
- driver.emit(sample_record)
436
- driver.run
802
+ driver.run(default_tag: 'test') do
803
+ driver.feed(sample_record)
804
+ end
437
805
  assert(!index_cmds[0]['index'].has_key?('_id'))
438
806
  end
439
807
 
440
808
  def test_adds_id_key_when_not_configured
441
- stub_elastic_ping
442
809
  stub_elastic
443
- driver.emit(sample_record)
444
- driver.run
810
+ driver.run(default_tag: 'test') do
811
+ driver.feed(sample_record)
812
+ end
445
813
  assert(!index_cmds[0]['index'].has_key?('_id'))
446
814
  end
447
815
 
448
816
  def test_adds_parent_key_when_configured
449
817
  driver.configure("parent_key parent_id\n")
450
- stub_elastic_ping
451
818
  stub_elastic
452
- driver.emit(sample_record)
453
- driver.run
454
- assert_equal(index_cmds[0]['index']['_parent'], 'parent')
819
+ driver.run(default_tag: 'test') do
820
+ driver.feed(sample_record)
821
+ end
822
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
823
+ end
824
+
825
+ class NestedParentKeyTest < self
826
+ def test_adds_nested_parent_key_with_dot
827
+ driver.configure("parent_key nested.parent_id\n")
828
+ stub_elastic
829
+ driver.run(default_tag: 'test') do
830
+ driver.feed(nested_sample_record)
831
+ end
832
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
833
+ end
834
+
835
+ def test_adds_nested_parent_key_with_dollar_dot
836
+ driver.configure("parent_key $.nested.parent_id\n")
837
+ stub_elastic
838
+ driver.run(default_tag: 'test') do
839
+ driver.feed(nested_sample_record)
840
+ end
841
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
842
+ end
843
+
844
+ def test_adds_nested_parent_key_with_bracket
845
+ driver.configure("parent_key $['nested']['parent_id']\n")
846
+ stub_elastic
847
+ driver.run(default_tag: 'test') do
848
+ driver.feed(nested_sample_record)
849
+ end
850
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
851
+ end
455
852
  end
456
853
 
457
854
  def test_doesnt_add_parent_key_if_missing_when_configured
458
855
  driver.configure("parent_key another_parent_id\n")
459
- stub_elastic_ping
460
856
  stub_elastic
461
- driver.emit(sample_record)
462
- driver.run
857
+ driver.run(default_tag: 'test') do
858
+ driver.feed(sample_record)
859
+ end
463
860
  assert(!index_cmds[0]['index'].has_key?('_parent'))
464
861
  end
465
862
 
466
863
  def test_adds_parent_key_when_not_configured
467
- stub_elastic_ping
468
864
  stub_elastic
469
- driver.emit(sample_record)
470
- driver.run
865
+ driver.run(default_tag: 'test') do
866
+ driver.feed(sample_record)
867
+ end
471
868
  assert(!index_cmds[0]['index'].has_key?('_parent'))
472
869
  end
473
870
 
474
- def test_adds_routing_key_when_configured
475
- driver.configure("routing_key routing_id\n")
476
- stub_elastic_ping
477
- stub_elastic
478
- driver.emit(sample_record)
479
- driver.run
480
- assert_equal(index_cmds[0]['index']['_routing'], 'routing')
871
+ class AddsRoutingKeyWhenConfiguredTest < self
872
+ def test_es6
873
+ driver("routing_key routing_id\n", 6)
874
+ stub_elastic
875
+ driver.run(default_tag: 'test') do
876
+ driver.feed(sample_record)
877
+ end
878
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
879
+ end
880
+
881
+ def test_es7
882
+ driver("routing_key routing_id\n", 7)
883
+ stub_elastic
884
+ driver.run(default_tag: 'test') do
885
+ driver.feed(sample_record)
886
+ end
887
+ assert_equal('routing', index_cmds[0]['index']['routing'])
888
+ end
889
+ end
890
+
891
+ class NestedRoutingKeyTest < self
892
+ def test_adds_nested_routing_key_with_dot
893
+ driver.configure("routing_key nested.routing_id\n")
894
+ stub_elastic
895
+ driver.run(default_tag: 'test') do
896
+ driver.feed(nested_sample_record)
897
+ end
898
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
899
+ end
900
+
901
+ def test_adds_nested_routing_key_with_dollar_dot
902
+ driver.configure("routing_key $.nested.routing_id\n")
903
+ stub_elastic
904
+ driver.run(default_tag: 'test') do
905
+ driver.feed(nested_sample_record)
906
+ end
907
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
908
+ end
909
+
910
+ def test_adds_nested_routing_key_with_bracket
911
+ driver.configure("routing_key $['nested']['routing_id']\n")
912
+ stub_elastic
913
+ driver.run(default_tag: 'test') do
914
+ driver.feed(nested_sample_record)
915
+ end
916
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
917
+ end
481
918
  end
482
919
 
483
920
  def test_doesnt_add_routing_key_if_missing_when_configured
484
921
  driver.configure("routing_key another_routing_id\n")
485
- stub_elastic_ping
486
922
  stub_elastic
487
- driver.emit(sample_record)
488
- driver.run
923
+ driver.run(default_tag: 'test') do
924
+ driver.feed(sample_record)
925
+ end
489
926
  assert(!index_cmds[0]['index'].has_key?('_routing'))
490
927
  end
491
928
 
492
929
  def test_adds_routing_key_when_not_configured
493
- stub_elastic_ping
494
930
  stub_elastic
495
- driver.emit(sample_record)
496
- driver.run
931
+ driver.run(default_tag: 'test') do
932
+ driver.feed(sample_record)
933
+ end
497
934
  assert(!index_cmds[0]['index'].has_key?('_routing'))
498
935
  end
499
936
 
500
937
  def test_remove_one_key
501
938
  driver.configure("remove_keys key1\n")
502
- stub_elastic_ping
503
939
  stub_elastic
504
- driver.emit(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
505
- driver.run
940
+ driver.run(default_tag: 'test') do
941
+ driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
942
+ end
506
943
  assert(!index_cmds[1].has_key?('key1'))
507
944
  assert(index_cmds[1].has_key?('key2'))
508
945
  end
509
946
 
510
947
  def test_remove_multi_keys
511
948
  driver.configure("remove_keys key1, key2\n")
512
- stub_elastic_ping
513
949
  stub_elastic
514
- driver.emit(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
515
- driver.run
950
+ driver.run(default_tag: 'test') do
951
+ driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
952
+ end
516
953
  assert(!index_cmds[1].has_key?('key1'))
517
954
  assert(!index_cmds[1].has_key?('key2'))
518
955
  end
519
956
 
520
957
  def test_request_error
521
- stub_elastic_ping
522
958
  stub_elastic_unavailable
523
- driver.emit(sample_record)
524
- assert_raise(Elasticsearch::Transport::Transport::Errors::ServiceUnavailable) {
525
- driver.run
959
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
960
+ driver.run(default_tag: 'test', shutdown: false) do
961
+ driver.feed(sample_record)
962
+ end
526
963
  }
527
964
  end
528
965
 
529
- def test_garbage_record_error
530
- stub_elastic_ping
966
+ def test_request_forever
967
+ omit("retry_forever test is unstable.") if ENV["CI"]
968
+
531
969
  stub_elastic
532
- driver.emit("some garbage string")
533
- driver.run
970
+ driver.configure(Fluent::Config::Element.new(
971
+ 'ROOT', '', {
972
+ '@type' => 'elasticsearch',
973
+ }, [
974
+ Fluent::Config::Element.new('buffer', '', {
975
+ 'retry_forever' => true
976
+ }, [])
977
+ ]
978
+ ))
979
+ stub_elastic_timeout
980
+ assert_raise(Timeout::Error) {
981
+ driver.run(default_tag: 'test', timeout: 10, force_flush_retry: true) do
982
+ driver.feed(sample_record)
983
+ end
984
+ }
534
985
  end
535
986
 
536
- def test_connection_failed_retry
537
- connection_resets = 0
538
-
539
- stub_elastic_ping(url="http://localhost:9200").with do |req|
540
- connection_resets += 1
987
+ def test_tag_parts_index_error_event
988
+ stub_elastic
989
+ driver.configure("logstash_prefix ${tag_parts[1]}\n")
990
+ flexmock(driver.instance.router).should_receive(:emit_error_event)
991
+ .with('test', Fluent::EventTime, Hash, TypeError).once
992
+ driver.run(default_tag: 'test') do
993
+ driver.feed(sample_record)
541
994
  end
995
+ end
996
+
997
+ def test_connection_failed
998
+ connection_resets = 0
542
999
 
543
1000
  stub_request(:post, "http://localhost:9200/_bulk").with do |req|
1001
+ connection_resets += 1
544
1002
  raise Faraday::ConnectionFailed, "Test message"
545
1003
  end
546
1004
 
547
- driver.emit(sample_record)
548
-
549
- assert_raise(Fluent::ElasticsearchOutput::ConnectionFailure) {
550
- driver.run
1005
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
1006
+ driver.run(default_tag: 'test', shutdown: false) do
1007
+ driver.feed(sample_record)
1008
+ end
551
1009
  }
552
- assert_equal(connection_resets, 3)
1010
+ assert_equal(1, connection_resets)
553
1011
  end
554
1012
 
555
1013
  def test_reconnect_on_error_enabled
556
1014
  connection_resets = 0
557
1015
 
558
- stub_elastic_ping(url="http://localhost:9200").with do |req|
559
- connection_resets += 1
560
- end
561
-
562
1016
  stub_request(:post, "http://localhost:9200/_bulk").with do |req|
1017
+ connection_resets += 1
563
1018
  raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
564
1019
  end
565
-
1020
+
566
1021
  driver.configure("reconnect_on_error true\n")
567
- driver.emit(sample_record)
568
1022
 
569
- assert_raise(ZeroDivisionError) {
570
- driver.run
1023
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
1024
+ driver.run(default_tag: 'test', shutdown: false) do
1025
+ driver.feed(sample_record)
1026
+ end
571
1027
  }
572
1028
 
573
- assert_raise(ZeroDivisionError) {
574
- driver.run
1029
+ assert_raise(Timeout::Error) {
1030
+ driver.run(default_tag: 'test', shutdown: false) do
1031
+ driver.feed(sample_record)
1032
+ end
575
1033
  }
576
- assert_equal(connection_resets, 2)
1034
+ # FIXME: Consider keywords arguments in #run and how to test this later.
1035
+ # Because v0.14 test driver does not have 1 to 1 correspondence between #run and #flush in tests.
1036
+ assert_equal(1, connection_resets)
577
1037
  end
578
1038
 
579
1039
  def test_reconnect_on_error_disabled
580
1040
  connection_resets = 0
581
1041
 
582
- stub_elastic_ping(url="http://localhost:9200").with do |req|
583
- connection_resets += 1
584
- end
585
-
586
1042
  stub_request(:post, "http://localhost:9200/_bulk").with do |req|
1043
+ connection_resets += 1
587
1044
  raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
588
1045
  end
589
-
1046
+
590
1047
  driver.configure("reconnect_on_error false\n")
591
- driver.emit(sample_record)
592
1048
 
593
- assert_raise(ZeroDivisionError) {
594
- driver.run
1049
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
1050
+ driver.run(default_tag: 'test', shutdown: false) do
1051
+ driver.feed(sample_record)
1052
+ end
595
1053
  }
596
1054
 
597
- assert_raise(ZeroDivisionError) {
598
- driver.run
1055
+ assert_raise(Timeout::Error) {
1056
+ driver.run(default_tag: 'test', shutdown: false) do
1057
+ driver.feed(sample_record)
1058
+ end
599
1059
  }
600
- assert_equal(connection_resets, 1)
1060
+ assert_equal(1, connection_resets)
601
1061
  end
602
1062
 
603
1063
  def test_update_should_not_write_if_theres_no_id
604
1064
  driver.configure("write_operation update\n")
605
- stub_elastic_ping
606
1065
  stub_elastic
607
- driver.emit(sample_record)
608
- driver.run
1066
+ driver.run(default_tag: 'test') do
1067
+ driver.feed(sample_record)
1068
+ end
609
1069
  assert_nil(index_cmds)
610
1070
  end
611
1071
 
612
1072
  def test_upsert_should_not_write_if_theres_no_id
613
1073
  driver.configure("write_operation upsert\n")
614
- stub_elastic_ping
615
1074
  stub_elastic
616
- driver.emit(sample_record)
617
- driver.run
1075
+ driver.run(default_tag: 'test') do
1076
+ driver.feed(sample_record)
1077
+ end
618
1078
  assert_nil(index_cmds)
619
1079
  end
620
1080
 
621
1081
  def test_create_should_not_write_if_theres_no_id
622
1082
  driver.configure("write_operation create\n")
623
- stub_elastic_ping
624
1083
  stub_elastic
625
- driver.emit(sample_record)
626
- driver.run
1084
+ driver.run(default_tag: 'test') do
1085
+ driver.feed(sample_record)
1086
+ end
627
1087
  assert_nil(index_cmds)
628
1088
  end
629
1089
 
630
1090
  def test_update_should_write_update_op_and_doc_as_upsert_is_false
631
1091
  driver.configure("write_operation update
632
1092
  id_key request_id")
633
- stub_elastic_ping
634
1093
  stub_elastic
635
- driver.emit(sample_record)
636
- driver.run
1094
+ driver.run(default_tag: 'test') do
1095
+ driver.feed(sample_record)
1096
+ end
637
1097
  assert(index_cmds[0].has_key?("update"))
638
1098
  assert(!index_cmds[1]["doc_as_upsert"])
639
1099
  end
@@ -641,10 +1101,10 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
641
1101
  def test_upsert_should_write_update_op_and_doc_as_upsert_is_true
642
1102
  driver.configure("write_operation upsert
643
1103
  id_key request_id")
644
- stub_elastic_ping
645
1104
  stub_elastic
646
- driver.emit(sample_record)
647
- driver.run
1105
+ driver.run(default_tag: 'test') do
1106
+ driver.feed(sample_record)
1107
+ end
648
1108
  assert(index_cmds[0].has_key?("update"))
649
1109
  assert(index_cmds[1]["doc_as_upsert"])
650
1110
  end
@@ -652,10 +1112,23 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
652
1112
  def test_create_should_write_create_op
653
1113
  driver.configure("write_operation create
654
1114
  id_key request_id")
655
- stub_elastic_ping
656
1115
  stub_elastic
657
- driver.emit(sample_record)
658
- driver.run
1116
+ driver.run(default_tag: 'test') do
1117
+ driver.feed(sample_record)
1118
+ end
659
1119
  assert(index_cmds[0].has_key?("create"))
660
1120
  end
1121
+
1122
+ def test_include_index_in_url
1123
+ stub_elastic('http://localhost:9200/logstash-2018.01.01/_bulk')
1124
+
1125
+ driver.configure("index_name logstash-2018.01.01
1126
+ include_index_in_url true")
1127
+ driver.run(default_tag: 'test') do
1128
+ driver.feed(sample_record)
1129
+ end
1130
+
1131
+ assert_equal(2, index_cmds.length)
1132
+ assert_equal(nil, index_cmds.first['index']['_index'])
1133
+ end
661
1134
  end