logstash-output-elasticsearch 10.8.6-java → 11.0.3-java
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 +4 -4
- data/CHANGELOG.md +17 -0
- data/docs/index.asciidoc +132 -22
- data/lib/logstash/outputs/elasticsearch.rb +125 -64
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +233 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +9 -7
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +49 -62
- data/lib/logstash/outputs/elasticsearch/ilm.rb +13 -45
- data/lib/logstash/outputs/elasticsearch/license_checker.rb +26 -23
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +4 -6
- data/lib/logstash/outputs/elasticsearch/templates/ecs-v1/elasticsearch-8x.json +1 -0
- data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +157 -153
- data/lib/logstash/plugin_mixins/elasticsearch/common.rb +71 -58
- data/logstash-output-elasticsearch.gemspec +3 -3
- data/spec/es_spec_helper.rb +7 -12
- data/spec/fixtures/_nodes/{5x_6x.json → 6x.json} +5 -5
- data/spec/integration/outputs/compressed_indexing_spec.rb +47 -46
- data/spec/integration/outputs/data_stream_spec.rb +61 -0
- data/spec/integration/outputs/delete_spec.rb +49 -51
- data/spec/integration/outputs/ilm_spec.rb +236 -248
- data/spec/integration/outputs/index_spec.rb +5 -2
- data/spec/integration/outputs/index_version_spec.rb +78 -82
- data/spec/integration/outputs/ingest_pipeline_spec.rb +58 -58
- data/spec/integration/outputs/painless_update_spec.rb +74 -164
- data/spec/integration/outputs/parent_spec.rb +67 -75
- data/spec/integration/outputs/retry_spec.rb +6 -6
- data/spec/integration/outputs/sniffer_spec.rb +15 -54
- data/spec/integration/outputs/templates_spec.rb +79 -81
- data/spec/integration/outputs/update_spec.rb +99 -101
- data/spec/spec_helper.rb +10 -0
- data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +528 -0
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +1 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +36 -29
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +2 -3
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +10 -12
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +1 -2
- data/spec/unit/outputs/elasticsearch_spec.rb +176 -41
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +1 -2
- data/spec/unit/outputs/error_whitelist_spec.rb +3 -2
- data/spec/unit/outputs/license_check_spec.rb +0 -16
- metadata +29 -36
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-2x.json +0 -95
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-5x.json +0 -46
- data/spec/fixtures/_nodes/2x_1x.json +0 -27
- data/spec/fixtures/scripts/groovy/scripted_update.groovy +0 -2
- data/spec/fixtures/scripts/groovy/scripted_update_nested.groovy +0 -2
- data/spec/fixtures/scripts/groovy/scripted_upsert.groovy +0 -2
- data/spec/integration/outputs/groovy_update_spec.rb +0 -150
- data/spec/integration/outputs/templates_5x_spec.rb +0 -98
@@ -1,6 +1,6 @@
|
|
1
1
|
require "logstash/devutils/rspec/spec_helper"
|
2
2
|
require "logstash/outputs/elasticsearch/http_client"
|
3
|
-
require
|
3
|
+
require 'cabin'
|
4
4
|
|
5
5
|
describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
6
6
|
let(:logger) { Cabin::Channel.get }
|
@@ -8,15 +8,12 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
8
8
|
let(:initial_urls) { [::LogStash::Util::SafeURI.new("http://localhost:9200")] }
|
9
9
|
let(:options) { {:resurrect_delay => 2, :url_normalizer => proc {|u| u}} } # Shorten the delay a bit to speed up tests
|
10
10
|
let(:es_node_versions) { [ "0.0.0" ] }
|
11
|
-
let(:
|
12
|
-
let(:valid_license) { true }
|
11
|
+
let(:license_status) { 'active' }
|
13
12
|
|
14
13
|
subject { described_class.new(logger, adapter, initial_urls, options) }
|
15
14
|
|
16
15
|
let(:manticore_double) { double("manticore a") }
|
17
16
|
before(:each) do
|
18
|
-
stub_const('LogStash::OSS', oss)
|
19
|
-
|
20
17
|
response_double = double("manticore response").as_null_object
|
21
18
|
# Allow healtchecks
|
22
19
|
allow(manticore_double).to receive(:head).with(any_args).and_return(response_double)
|
@@ -26,8 +23,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
26
23
|
allow(::Manticore::Client).to receive(:new).and_return(manticore_double)
|
27
24
|
|
28
25
|
allow(subject).to receive(:get_es_version).with(any_args).and_return(*es_node_versions)
|
29
|
-
allow(subject.license_checker).to receive(:
|
30
|
-
allow(subject.license_checker).to receive(:valid_es_license?).and_return(valid_license)
|
26
|
+
allow(subject.license_checker).to receive(:license_status).and_return(license_status)
|
31
27
|
end
|
32
28
|
|
33
29
|
after do
|
@@ -279,35 +275,46 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
279
275
|
allow(subject).to receive(:health_check_request)
|
280
276
|
end
|
281
277
|
|
282
|
-
context "
|
283
|
-
let(:
|
278
|
+
context "if ES doesn't return a valid license" do
|
279
|
+
let(:license_status) { nil }
|
284
280
|
|
285
|
-
|
286
|
-
|
281
|
+
it "marks the url as dead" do
|
282
|
+
subject.update_initial_urls
|
283
|
+
expect(subject.alive_urls_count).to eq(0)
|
284
|
+
end
|
287
285
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
286
|
+
it "logs a warning" do
|
287
|
+
expect(subject.license_checker).to receive(:warn_no_license).once.and_call_original
|
288
|
+
subject.update_initial_urls
|
289
|
+
end
|
290
|
+
end
|
292
291
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
292
|
+
context "if ES returns a valid license" do
|
293
|
+
let(:license_status) { 'active' }
|
294
|
+
|
295
|
+
it "marks the url as active" do
|
296
|
+
subject.update_initial_urls
|
297
|
+
expect(subject.alive_urls_count).to eq(1)
|
297
298
|
end
|
298
299
|
|
299
|
-
|
300
|
-
|
300
|
+
it "does not log a warning" do
|
301
|
+
expect(subject.license_checker).to_not receive(:warn_no_license)
|
302
|
+
expect(subject.license_checker).to_not receive(:warn_invalid_license)
|
303
|
+
subject.update_initial_urls
|
304
|
+
end
|
305
|
+
end
|
301
306
|
|
302
|
-
|
303
|
-
|
304
|
-
expect(subject.alive_urls_count).to eq(1)
|
305
|
-
end
|
307
|
+
context "if ES returns an invalid license" do
|
308
|
+
let(:license_status) { 'invalid' }
|
306
309
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
310
|
+
it "marks the url as active" do
|
311
|
+
subject.update_initial_urls
|
312
|
+
expect(subject.alive_urls_count).to eq(1)
|
313
|
+
end
|
314
|
+
|
315
|
+
it "logs a warning" do
|
316
|
+
expect(subject.license_checker).to receive(:warn_invalid_license).and_call_original
|
317
|
+
subject.update_initial_urls
|
311
318
|
end
|
312
319
|
end
|
313
320
|
end
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require_relative "../../../../spec/
|
2
|
-
require "logstash/devutils/rspec/spec_helper"
|
1
|
+
require_relative "../../../../spec/spec_helper"
|
3
2
|
require "logstash/outputs/elasticsearch/http_client"
|
4
|
-
require "
|
3
|
+
require "cabin"
|
5
4
|
|
6
5
|
describe LogStash::Outputs::ElasticSearch::HttpClient do
|
7
6
|
let(:ssl) { nil }
|
@@ -1,24 +1,22 @@
|
|
1
1
|
require "logstash/devutils/rspec/spec_helper"
|
2
|
-
require "logstash/outputs/elasticsearch/
|
3
|
-
require "java"
|
4
|
-
require "json"
|
2
|
+
require "logstash/outputs/elasticsearch/template_manager"
|
5
3
|
|
6
4
|
describe LogStash::Outputs::ElasticSearch::TemplateManager do
|
7
5
|
|
8
6
|
describe ".default_template_path" do
|
9
|
-
context "elasticsearch
|
10
|
-
it "chooses the
|
11
|
-
expect(described_class.default_template_path(
|
7
|
+
context "elasticsearch 6.x" do
|
8
|
+
it "chooses the 6x template" do
|
9
|
+
expect(described_class.default_template_path(6)).to end_with("/templates/ecs-disabled/elasticsearch-6x.json")
|
12
10
|
end
|
13
11
|
end
|
14
|
-
context "elasticsearch
|
15
|
-
it "chooses the
|
16
|
-
expect(described_class.default_template_path(
|
12
|
+
context "elasticsearch 7.x" do
|
13
|
+
it "chooses the 7x template" do
|
14
|
+
expect(described_class.default_template_path(7)).to end_with("/templates/ecs-disabled/elasticsearch-7x.json")
|
17
15
|
end
|
18
16
|
end
|
19
|
-
context "elasticsearch
|
20
|
-
it "chooses the
|
21
|
-
expect(described_class.default_template_path(
|
17
|
+
context "elasticsearch 8.x" do
|
18
|
+
it "chooses the 8x template" do
|
19
|
+
expect(described_class.default_template_path(8)).to end_with("/templates/ecs-disabled/elasticsearch-8x.json")
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
@@ -1,27 +1,40 @@
|
|
1
|
-
require_relative "../../../spec/
|
1
|
+
require_relative "../../../spec/spec_helper"
|
2
2
|
require "base64"
|
3
3
|
require "flores/random"
|
4
|
+
require 'concurrent/atomic/count_down_latch'
|
4
5
|
require "logstash/outputs/elasticsearch"
|
5
6
|
|
6
7
|
describe LogStash::Outputs::ElasticSearch do
|
7
8
|
subject(:elasticsearch_output_instance) { described_class.new(options) }
|
8
9
|
let(:options) { {} }
|
9
|
-
let(:maximum_seen_major_version) { [
|
10
|
+
let(:maximum_seen_major_version) { [6,7,8].sample }
|
10
11
|
|
11
12
|
let(:do_register) { true }
|
12
13
|
|
14
|
+
let(:stub_http_client_pool!) do
|
15
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:start)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:after_successful_connection_thread_mock) do
|
19
|
+
double('after_successful_connection_thread', value: true)
|
20
|
+
end
|
21
|
+
|
13
22
|
before(:each) do
|
14
23
|
if do_register
|
15
|
-
|
16
|
-
|
24
|
+
stub_http_client_pool!
|
25
|
+
|
26
|
+
allow(subject).to receive(:finish_register) # stub-out thread completion (to avoid error log entries)
|
27
|
+
|
28
|
+
# emulate 'successful' ES connection on the same thread
|
29
|
+
allow(subject).to receive(:after_successful_connection) { |&block| block.call }.
|
30
|
+
and_return after_successful_connection_thread_mock
|
31
|
+
allow(subject).to receive(:stop_after_successful_connection_thread)
|
32
|
+
|
33
|
+
subject.register
|
17
34
|
|
18
|
-
# Rspec mocks can't handle background threads, so... we can't use any
|
19
|
-
allow(subject.client.pool).to receive(:start_resurrectionist)
|
20
|
-
allow(subject.client.pool).to receive(:start_sniffer)
|
21
|
-
allow(subject.client.pool).to receive(:healthcheck!)
|
22
35
|
allow(subject.client).to receive(:maximum_seen_major_version).at_least(:once).and_return(maximum_seen_major_version)
|
23
36
|
allow(subject.client).to receive(:get_xpack_info)
|
24
|
-
|
37
|
+
|
25
38
|
subject.client.pool.adapter.manticore.respond_with(:body => "{}")
|
26
39
|
end
|
27
40
|
end
|
@@ -44,6 +57,12 @@ describe LogStash::Outputs::ElasticSearch do
|
|
44
57
|
let(:manticore_urls) { subject.client.pool.urls }
|
45
58
|
let(:manticore_url) { manticore_urls.first }
|
46
59
|
|
60
|
+
let(:stub_http_client_pool!) do
|
61
|
+
[:start_resurrectionist, :start_sniffer, :healthcheck!].each do |method|
|
62
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(method)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
47
66
|
describe "getting a document type" do
|
48
67
|
context "if document_type isn't set" do
|
49
68
|
let(:options) { super().merge("document_type" => nil)}
|
@@ -60,13 +79,6 @@ describe LogStash::Outputs::ElasticSearch do
|
|
60
79
|
expect(subject.send(:get_event_type, LogStash::Event.new("type" => "foo"))).to eql("doc")
|
61
80
|
end
|
62
81
|
end
|
63
|
-
|
64
|
-
context "for < 6.0 elasticsearch clusters" do
|
65
|
-
let(:maximum_seen_major_version) { 5 }
|
66
|
-
it "should get the type from the event" do
|
67
|
-
expect(subject.send(:get_event_type, LogStash::Event.new("type" => "foo"))).to eql("foo")
|
68
|
-
end
|
69
|
-
end
|
70
82
|
end
|
71
83
|
|
72
84
|
context "with 'document type set'" do
|
@@ -253,8 +265,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
253
265
|
before do
|
254
266
|
allow(subject).to receive(:retrying_submit).with(anything)
|
255
267
|
events.each_with_index do |e,i|
|
256
|
-
|
257
|
-
allow(subject).to receive(:event_action_tuple).with(e).and_return(et)
|
268
|
+
allow(subject).to receive(:event_action_tuple).with(e).and_return(events_tuples[i])
|
258
269
|
end
|
259
270
|
subject.multi_receive(events)
|
260
271
|
end
|
@@ -325,7 +336,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
325
336
|
}
|
326
337
|
}]
|
327
338
|
}
|
328
|
-
|
339
|
+
end
|
329
340
|
|
330
341
|
before(:each) do
|
331
342
|
allow(subject.client).to receive(:bulk_send).with(instance_of(StringIO), instance_of(Array)) do |stream, actions|
|
@@ -345,7 +356,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
345
356
|
|
346
357
|
it "should log specific error message" do
|
347
358
|
expect(subject.logger).to receive(:error).with(/Encountered an unexpected error/i,
|
348
|
-
hash_including(:
|
359
|
+
hash_including(:message => 'Sent 2 documents but Elasticsearch returned 3 responses (likely a bug with _bulk endpoint)'))
|
349
360
|
|
350
361
|
subject.multi_receive(events)
|
351
362
|
end
|
@@ -402,7 +413,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
402
413
|
|
403
414
|
before do
|
404
415
|
# Expect a timeout to be logged.
|
405
|
-
expect(subject.logger).to receive(:error).with(/Attempted to send a bulk request
|
416
|
+
expect(subject.logger).to receive(:error).with(/Attempted to send a bulk request/i, anything).at_least(:once)
|
406
417
|
expect(subject.client).to receive(:bulk).at_least(:twice).and_call_original
|
407
418
|
end
|
408
419
|
|
@@ -416,13 +427,14 @@ describe LogStash::Outputs::ElasticSearch do
|
|
416
427
|
end
|
417
428
|
|
418
429
|
describe "the action option" do
|
430
|
+
|
419
431
|
context "with a sprintf action" do
|
420
432
|
let(:options) { {"action" => "%{myactionfield}" } }
|
421
433
|
|
422
434
|
let(:event) { LogStash::Event.new("myactionfield" => "update", "message" => "blah") }
|
423
435
|
|
424
436
|
it "should interpolate the requested action value when creating an event_action_tuple" do
|
425
|
-
expect(subject.event_action_tuple
|
437
|
+
expect(subject.send(:event_action_tuple, event).first).to eql("update")
|
426
438
|
end
|
427
439
|
end
|
428
440
|
|
@@ -432,7 +444,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
432
444
|
let(:event) { LogStash::Event.new("myactionfield" => "update", "message" => "blah") }
|
433
445
|
|
434
446
|
it "should obtain specific action's params from event_action_tuple" do
|
435
|
-
expect(subject.event_action_tuple
|
447
|
+
expect(subject.send(:event_action_tuple, event)[1]).to include(:_upsert)
|
436
448
|
end
|
437
449
|
end
|
438
450
|
|
@@ -440,6 +452,8 @@ describe LogStash::Outputs::ElasticSearch do
|
|
440
452
|
let(:options) { {"action" => "SOME Garbaaage"} }
|
441
453
|
let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
|
442
454
|
|
455
|
+
before { allow(subject).to receive(:finish_register) }
|
456
|
+
|
443
457
|
it "should raise a configuration error" do
|
444
458
|
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
445
459
|
end
|
@@ -447,13 +461,14 @@ describe LogStash::Outputs::ElasticSearch do
|
|
447
461
|
end
|
448
462
|
|
449
463
|
describe "the pipeline option" do
|
464
|
+
|
450
465
|
context "with a sprintf and set pipeline" do
|
451
466
|
let(:options) { {"pipeline" => "%{pipeline}" } }
|
452
467
|
|
453
468
|
let(:event) { LogStash::Event.new("pipeline" => "my-ingest-pipeline") }
|
454
469
|
|
455
470
|
it "should interpolate the pipeline value and set it" do
|
456
|
-
expect(subject.event_action_tuple
|
471
|
+
expect(subject.send(:event_action_tuple, event)[1]).to include(:pipeline => "my-ingest-pipeline")
|
457
472
|
end
|
458
473
|
end
|
459
474
|
|
@@ -463,7 +478,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
463
478
|
let(:event) { LogStash::Event.new("pipeline" => "") }
|
464
479
|
|
465
480
|
it "should interpolate the pipeline value but not set it because it is empty" do
|
466
|
-
expect(subject.event_action_tuple
|
481
|
+
expect(subject.send(:event_action_tuple, event)[1]).not_to include(:pipeline)
|
467
482
|
end
|
468
483
|
end
|
469
484
|
end
|
@@ -505,8 +520,8 @@ describe LogStash::Outputs::ElasticSearch do
|
|
505
520
|
|
506
521
|
it "should not set the retry_on_conflict parameter when creating an event_action_tuple" do
|
507
522
|
allow(subject.client).to receive(:maximum_seen_major_version).and_return(maximum_seen_major_version)
|
508
|
-
action, params, event_data = subject.event_action_tuple
|
509
|
-
expect(params).not_to include({subject.retry_on_conflict_action_name => num_retries})
|
523
|
+
action, params, event_data = subject.send(:event_action_tuple, event)
|
524
|
+
expect(params).not_to include({subject.send(:retry_on_conflict_action_name) => num_retries})
|
510
525
|
end
|
511
526
|
end
|
512
527
|
|
@@ -514,8 +529,8 @@ describe LogStash::Outputs::ElasticSearch do
|
|
514
529
|
let(:options) { super().merge("action" => "update", "retry_on_conflict" => num_retries, "document_id" => 1) }
|
515
530
|
|
516
531
|
it "should set the retry_on_conflict parameter when creating an event_action_tuple" do
|
517
|
-
action, params, event_data = subject.event_action_tuple
|
518
|
-
expect(params).to include({subject.retry_on_conflict_action_name => num_retries})
|
532
|
+
action, params, event_data = subject.send(:event_action_tuple, event)
|
533
|
+
expect(params).to include({subject.send(:retry_on_conflict_action_name) => num_retries})
|
519
534
|
end
|
520
535
|
end
|
521
536
|
|
@@ -523,8 +538,8 @@ describe LogStash::Outputs::ElasticSearch do
|
|
523
538
|
let(:options) { super().merge("action" => "%{myactionfield}", "retry_on_conflict" => num_retries, "document_id" => 1) }
|
524
539
|
|
525
540
|
it "should set the retry_on_conflict parameter when creating an event_action_tuple" do
|
526
|
-
action, params, event_data = subject.event_action_tuple
|
527
|
-
expect(params).to include({subject.retry_on_conflict_action_name => num_retries})
|
541
|
+
action, params, event_data = subject.send(:event_action_tuple, event)
|
542
|
+
expect(params).to include({subject.send(:retry_on_conflict_action_name) => num_retries})
|
528
543
|
expect(action).to eq("update")
|
529
544
|
end
|
530
545
|
end
|
@@ -554,6 +569,8 @@ describe LogStash::Outputs::ElasticSearch do
|
|
554
569
|
let(:do_register) { false }
|
555
570
|
|
556
571
|
before :each do
|
572
|
+
allow(subject).to receive(:finish_register)
|
573
|
+
|
557
574
|
allow(::Manticore::Client).to receive(:new).with(any_args).and_call_original
|
558
575
|
end
|
559
576
|
|
@@ -577,6 +594,12 @@ describe LogStash::Outputs::ElasticSearch do
|
|
577
594
|
let(:custom_parameters_hash) { { "id" => 1, "name" => "logstash" } }
|
578
595
|
let(:custom_parameters_query) { custom_parameters_hash.map {|k,v| "#{k}=#{v}" }.join("&") }
|
579
596
|
|
597
|
+
let(:stub_http_client_pool!) do
|
598
|
+
[:start_resurrectionist, :start_sniffer, :healthcheck!].each do |method|
|
599
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(method)
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
580
603
|
context "using non-url hosts" do
|
581
604
|
|
582
605
|
let(:options) {
|
@@ -741,9 +764,9 @@ describe LogStash::Outputs::ElasticSearch do
|
|
741
764
|
|
742
765
|
context 'when getting any other exception' do
|
743
766
|
it 'should log at WARN level' do
|
744
|
-
|
745
|
-
subject.instance_variable_set(:@logger,
|
746
|
-
expect(
|
767
|
+
logger = double("logger").as_null_object
|
768
|
+
subject.instance_variable_set(:@logger, logger)
|
769
|
+
expect(logger).to receive(:warn).with(/Could not index/, hash_including(:status, :action, :response))
|
747
770
|
mock_response = { 'index' => { 'error' => { 'type' => 'illegal_argument_exception' } } }
|
748
771
|
subject.handle_dlq_status("Could not index event to Elasticsearch.",
|
749
772
|
[:action, :params, :event], :some_status, mock_response)
|
@@ -752,9 +775,9 @@ describe LogStash::Outputs::ElasticSearch do
|
|
752
775
|
|
753
776
|
context 'when the response does not include [error]' do
|
754
777
|
it 'should not fail, but just log a warning' do
|
755
|
-
|
756
|
-
subject.instance_variable_set(:@logger,
|
757
|
-
expect(
|
778
|
+
logger = double("logger").as_null_object
|
779
|
+
subject.instance_variable_set(:@logger, logger)
|
780
|
+
expect(logger).to receive(:warn).with(/Could not index/, hash_including(:status, :action, :response))
|
758
781
|
mock_response = { 'index' => {} }
|
759
782
|
expect do
|
760
783
|
subject.handle_dlq_status("Could not index event to Elasticsearch.",
|
@@ -774,16 +797,59 @@ describe LogStash::Outputs::ElasticSearch do
|
|
774
797
|
# We should still log when sending to the DLQ.
|
775
798
|
# This shall be solved by another issue, however: logstash-output-elasticsearch#772
|
776
799
|
it 'should send the event to the DLQ instead, and not log' do
|
777
|
-
|
800
|
+
event = LogStash::Event.new("foo" => "bar")
|
801
|
+
expect(dlq_writer).to receive(:write).once.with(event, /Could not index/)
|
778
802
|
mock_response = { 'index' => { 'error' => { 'type' => 'illegal_argument_exception' } } }
|
779
|
-
|
780
|
-
|
803
|
+
action = LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, event)
|
804
|
+
subject.handle_dlq_status("Could not index event to Elasticsearch.", action, 404, mock_response)
|
781
805
|
end
|
782
806
|
end
|
807
|
+
|
808
|
+
context 'with response status 400' do
|
809
|
+
|
810
|
+
let(:options) { super().merge 'document_id' => '%{foo}' }
|
811
|
+
|
812
|
+
let(:events) { [ LogStash::Event.new("foo" => "bar") ] }
|
813
|
+
|
814
|
+
let(:dlq_writer) { subject.instance_variable_get(:@dlq_writer) }
|
815
|
+
|
816
|
+
let(:bulk_response) do
|
817
|
+
{
|
818
|
+
"took"=>1, "ingest_took"=>11, "errors"=>true, "items"=>
|
819
|
+
[{
|
820
|
+
"index"=>{"_index"=>"bar", "_type"=>"_doc", "_id"=>'bar', "status"=>400,
|
821
|
+
"error"=>{"type" => "illegal_argument_exception", "reason" => "TEST" }
|
822
|
+
}
|
823
|
+
}]
|
824
|
+
}
|
825
|
+
end
|
826
|
+
|
827
|
+
before(:each) do
|
828
|
+
allow(subject.client).to receive(:bulk_send).and_return(bulk_response)
|
829
|
+
end
|
830
|
+
|
831
|
+
it "should write event to DLQ" do
|
832
|
+
expect(dlq_writer).to receive(:write).and_wrap_original do |method, *args|
|
833
|
+
expect( args.size ).to eql 2
|
834
|
+
|
835
|
+
event, reason = *args
|
836
|
+
expect( event ).to be_a LogStash::Event
|
837
|
+
expect( event ).to be events.first
|
838
|
+
expect( reason ).to start_with 'Could not index event to Elasticsearch. status: 400, action: ["index"'
|
839
|
+
expect( reason ).to match /_id=>"bar".*"foo"=>"bar".*response:.*"reason"=>"TEST"/
|
840
|
+
|
841
|
+
method.call(*args) # won't hurt to call LogStash::Util::DummyDeadLetterQueueWriter
|
842
|
+
end.once
|
843
|
+
|
844
|
+
event_action_tuples = subject.map_events(events)
|
845
|
+
subject.send(:submit, event_action_tuples)
|
846
|
+
end
|
847
|
+
|
848
|
+
end if LOGSTASH_VERSION > '7.0'
|
783
849
|
end
|
784
850
|
|
785
851
|
describe "custom headers" do
|
786
|
-
let(:manticore_options) { subject.client.pool.adapter.manticore.instance_variable_get(:@options) }
|
852
|
+
let(:manticore_options) { subject.client.pool.adapter.manticore.instance_variable_get(:@options) }
|
787
853
|
|
788
854
|
context "when set" do
|
789
855
|
let(:headers) { { "X-Thing" => "Test" } }
|
@@ -856,6 +922,75 @@ describe LogStash::Outputs::ElasticSearch do
|
|
856
922
|
end
|
857
923
|
end
|
858
924
|
|
925
|
+
describe "post-register ES setup" do
|
926
|
+
let(:do_register) { false }
|
927
|
+
let(:es_version) { '7.10.0' } # DS default on LS 8.x
|
928
|
+
let(:options) { { 'hosts' => '127.0.0.1:9999' } }
|
929
|
+
let(:logger) { subject.logger }
|
930
|
+
|
931
|
+
before do
|
932
|
+
allow(logger).to receive(:error) # expect tracking
|
933
|
+
|
934
|
+
allow(subject).to receive(:last_es_version).and_return es_version
|
935
|
+
# make successful_connection? return true:
|
936
|
+
allow(subject).to receive(:maximum_seen_major_version).and_return Integer(es_version.split('.').first)
|
937
|
+
allow(subject).to receive(:stop_after_successful_connection_thread)
|
938
|
+
end
|
939
|
+
|
940
|
+
it "logs inability to retrieve uuid" do
|
941
|
+
allow(subject).to receive(:install_template)
|
942
|
+
allow(subject).to receive(:ilm_in_use?).and_return nil
|
943
|
+
subject.register
|
944
|
+
subject.send :wait_for_successful_connection
|
945
|
+
|
946
|
+
expect(logger).to have_received(:error).with(/Unable to retrieve Elasticsearch cluster uuid/i, anything)
|
947
|
+
end if LOGSTASH_VERSION >= '7.0.0'
|
948
|
+
|
949
|
+
it "logs template install failure" do
|
950
|
+
allow(subject).to receive(:discover_cluster_uuid)
|
951
|
+
allow(subject).to receive(:ilm_in_use?).and_return nil
|
952
|
+
subject.register
|
953
|
+
subject.send :wait_for_successful_connection
|
954
|
+
|
955
|
+
expect(logger).to have_received(:error).with(/Failed to install template/i, anything)
|
956
|
+
end
|
957
|
+
|
958
|
+
context 'error raised' do
|
959
|
+
|
960
|
+
let(:es_version) { '7.8.0' }
|
961
|
+
let(:options) { super().merge('data_stream' => 'true') }
|
962
|
+
let(:latch) { Concurrent::CountDownLatch.new }
|
963
|
+
|
964
|
+
before do
|
965
|
+
allow(subject).to receive(:install_template)
|
966
|
+
allow(subject).to receive(:discover_cluster_uuid)
|
967
|
+
allow(subject).to receive(:ilm_in_use?).and_return nil
|
968
|
+
# executes from the after_successful_connection thread :
|
969
|
+
allow(subject).to receive(:finish_register) { latch.wait }.and_call_original
|
970
|
+
subject.register
|
971
|
+
end
|
972
|
+
|
973
|
+
it 'keeps logging on multi_receive' do
|
974
|
+
allow(subject).to receive(:retrying_submit)
|
975
|
+
latch.count_down; sleep(1.0)
|
976
|
+
|
977
|
+
expect_logged_error = lambda do |count|
|
978
|
+
expect(logger).to have_received(:error).with(
|
979
|
+
/Elasticsearch setup did not complete normally, please review previously logged errors/i,
|
980
|
+
hash_including(message: 'A data_stream configuration is only supported since Elasticsearch 7.9.0 (detected version 7.8.0), please upgrade your cluster')
|
981
|
+
).exactly(count).times
|
982
|
+
end
|
983
|
+
|
984
|
+
subject.multi_receive [ LogStash::Event.new('foo' => 1) ]
|
985
|
+
expect_logged_error.call(1)
|
986
|
+
|
987
|
+
subject.multi_receive [ LogStash::Event.new('foo' => 2) ]
|
988
|
+
expect_logged_error.call(2)
|
989
|
+
end
|
990
|
+
|
991
|
+
end
|
992
|
+
end
|
993
|
+
|
859
994
|
@private
|
860
995
|
|
861
996
|
def stub_manticore_client!(manticore_double = nil)
|