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.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/workflows/issue-auto-closer.yml +12 -0
- data/.github/workflows/linux.yml +26 -0
- data/.github/workflows/macos.yml +26 -0
- data/.github/workflows/windows.yml +26 -0
- data/.travis.yml +33 -6
- data/CONTRIBUTING.md +24 -0
- data/Gemfile +4 -1
- data/History.md +445 -1
- data/ISSUE_TEMPLATE.md +19 -0
- data/README.ElasticsearchGenID.md +116 -0
- data/README.ElasticsearchInput.md +293 -0
- data/README.Troubleshooting.md +692 -0
- data/README.md +1013 -38
- data/appveyor.yml +20 -0
- data/fluent-plugin-elasticsearch.gemspec +15 -9
- data/{Gemfile.v0.12 → gemfiles/Gemfile.elasticsearch.v6} +6 -5
- data/lib/fluent/log-ext.rb +38 -0
- data/lib/fluent/plugin/default-ilm-policy.json +14 -0
- data/lib/fluent/plugin/elasticsearch_constants.rb +13 -0
- data/lib/fluent/plugin/elasticsearch_error.rb +5 -0
- data/lib/fluent/plugin/elasticsearch_error_handler.rb +129 -0
- data/lib/fluent/plugin/elasticsearch_fallback_selector.rb +9 -0
- data/lib/fluent/plugin/elasticsearch_index_lifecycle_management.rb +67 -0
- data/lib/fluent/plugin/elasticsearch_index_template.rb +186 -12
- data/lib/fluent/plugin/elasticsearch_simple_sniffer.rb +10 -0
- data/lib/fluent/plugin/elasticsearch_tls.rb +70 -0
- data/lib/fluent/plugin/filter_elasticsearch_genid.rb +77 -0
- data/lib/fluent/plugin/in_elasticsearch.rb +325 -0
- data/lib/fluent/plugin/oj_serializer.rb +22 -0
- data/lib/fluent/plugin/out_elasticsearch.rb +1008 -267
- data/lib/fluent/plugin/out_elasticsearch_data_stream.rb +218 -0
- data/lib/fluent/plugin/out_elasticsearch_dynamic.rb +232 -214
- data/test/plugin/test_alias_template.json +9 -0
- data/test/plugin/test_elasticsearch_error_handler.rb +646 -0
- data/test/plugin/test_elasticsearch_fallback_selector.rb +74 -0
- data/test/plugin/test_elasticsearch_index_lifecycle_management.rb +66 -0
- data/test/plugin/test_elasticsearch_tls.rb +145 -0
- data/test/plugin/test_filter_elasticsearch_genid.rb +215 -0
- data/test/plugin/test_in_elasticsearch.rb +459 -0
- data/test/plugin/test_index_alias_template.json +11 -0
- data/test/plugin/test_index_template.json +25 -0
- data/test/plugin/test_oj_serializer.rb +19 -0
- data/test/plugin/test_out_elasticsearch.rb +5029 -387
- data/test/plugin/test_out_elasticsearch_data_stream.rb +337 -0
- data/test/plugin/test_out_elasticsearch_dynamic.rb +681 -208
- data/test/test_log-ext.rb +35 -0
- metadata +97 -19
@@ -1,17 +1,30 @@
|
|
1
|
-
|
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(
|
14
|
-
|
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
|
29
|
-
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
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.
|
171
|
-
|
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.
|
179
|
-
|
180
|
-
|
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
|
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.
|
188
|
-
|
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
|
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.
|
197
|
-
|
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
|
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.
|
206
|
-
|
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
|
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.
|
215
|
-
|
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
|
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.
|
224
|
-
|
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
|
-
|
241
|
-
|
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.
|
263
|
-
|
264
|
-
|
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.
|
272
|
-
|
273
|
-
|
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.
|
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.
|
285
|
-
|
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.
|
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.
|
297
|
-
|
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.
|
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.
|
309
|
-
|
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.
|
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.
|
321
|
-
|
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.
|
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.
|
333
|
-
|
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.
|
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.
|
346
|
-
|
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.
|
354
|
-
|
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
|
-
|
363
|
-
driver.
|
364
|
-
|
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']
|
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).
|
374
|
-
driver.
|
375
|
-
|
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']
|
678
|
+
assert_equal(ts, index_cmds[1]['@timestamp'])
|
378
679
|
end
|
379
680
|
|
380
|
-
def
|
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).
|
386
|
-
driver.
|
387
|
-
|
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']
|
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).
|
399
|
-
driver.
|
400
|
-
|
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.
|
408
|
-
|
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
|
414
|
-
stub_elastic_ping
|
752
|
+
driver.configure("include_tag_key true\n")
|
415
753
|
stub_elastic
|
416
|
-
driver.
|
417
|
-
|
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']
|
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.
|
427
|
-
|
428
|
-
|
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.
|
436
|
-
|
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.
|
444
|
-
|
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.
|
453
|
-
|
454
|
-
|
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.
|
462
|
-
|
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.
|
470
|
-
|
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
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
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.
|
488
|
-
|
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.
|
496
|
-
|
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.
|
505
|
-
|
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.
|
515
|
-
|
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
|
-
|
524
|
-
|
525
|
-
|
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
|
530
|
-
|
966
|
+
def test_request_forever
|
967
|
+
omit("retry_forever test is unstable.") if ENV["CI"]
|
968
|
+
|
531
969
|
stub_elastic
|
532
|
-
driver.
|
533
|
-
|
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
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
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
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
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(
|
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(
|
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(
|
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
|
-
|
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(
|
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(
|
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(
|
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.
|
608
|
-
|
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.
|
617
|
-
|
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.
|
626
|
-
|
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.
|
636
|
-
|
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.
|
647
|
-
|
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.
|
658
|
-
|
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
|