logstash-output-elasticsearch 11.14.1-java → 11.15.1-java
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ad6b80e4c6db7a54c8b7a830f6a922a7057b2e7585820db8a6c093b57db3800
|
4
|
+
data.tar.gz: 82cd893394fc7ac08ae7a79b2cd953f80fbf258ec2faad225300a2ce516ab208
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b861d195377c3eeadf4489d21780be6627597aa0b93992bd7378b7cf680f6f99ac120ae342a4b48739ee6ef2652aa9238ee9fc08838cbed0f6dae0c887b06daa
|
7
|
+
data.tar.gz: 16091be406132dbb590ad76a0ba2e83cb0729717d8229b410bccbcabc660a7a26146fd2c7aaae6976f954bd17f1f763c6353552699ffd67173efb9917b913658
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 11.15.1
|
2
|
+
- Move async finish_register to bottom of register to avoid race condition [#1125](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1125)
|
3
|
+
|
4
|
+
## 11.15.0
|
5
|
+
- Added the ability to negatively acknowledge the batch under processing if the plugin is blocked in a retry-error-loop and a shutdown is requested. [#1119](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1119)
|
6
|
+
|
1
7
|
## 11.14.1
|
2
8
|
- [DOC] Fixed incorrect pull request link on the CHANGELOG `11.14.0` entry [#1122](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1122)
|
3
9
|
|
@@ -313,6 +313,27 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
313
313
|
data_stream_enabled = data_stream_config?
|
314
314
|
|
315
315
|
setup_template_manager_defaults(data_stream_enabled)
|
316
|
+
# To support BWC, we check if DLQ exists in core (< 5.4). If it doesn't, we use nil to resort to previous behavior.
|
317
|
+
@dlq_writer = dlq_enabled? ? execution_context.dlq_writer : nil
|
318
|
+
|
319
|
+
@dlq_codes = DOC_DLQ_CODES.to_set
|
320
|
+
|
321
|
+
if dlq_enabled?
|
322
|
+
check_dlq_custom_codes
|
323
|
+
@dlq_codes.merge(dlq_custom_codes)
|
324
|
+
else
|
325
|
+
raise LogStash::ConfigurationError, "DLQ feature (dlq_custom_codes) is configured while DLQ is not enabled" unless dlq_custom_codes.empty?
|
326
|
+
end
|
327
|
+
|
328
|
+
setup_mapper_and_target(data_stream_enabled)
|
329
|
+
|
330
|
+
@bulk_request_metrics = metric.namespace(:bulk_requests)
|
331
|
+
@document_level_metrics = metric.namespace(:documents)
|
332
|
+
|
333
|
+
if ecs_compatibility == :v8
|
334
|
+
@logger.warn("Elasticsearch Output configured with `ecs_compatibility => v8`, which resolved to an UNRELEASED preview of version 8.0.0 of the Elastic Common Schema. " +
|
335
|
+
"Once ECS v8 and an updated release of this plugin are publicly available, you will need to update this plugin to resolve this warning.")
|
336
|
+
end
|
316
337
|
|
317
338
|
@after_successful_connection_thread = after_successful_connection do
|
318
339
|
begin
|
@@ -326,18 +347,9 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
326
347
|
end
|
327
348
|
end
|
328
349
|
|
329
|
-
|
330
|
-
@dlq_writer = dlq_enabled? ? execution_context.dlq_writer : nil
|
331
|
-
|
332
|
-
@dlq_codes = DOC_DLQ_CODES.to_set
|
333
|
-
|
334
|
-
if dlq_enabled?
|
335
|
-
check_dlq_custom_codes
|
336
|
-
@dlq_codes.merge(dlq_custom_codes)
|
337
|
-
else
|
338
|
-
raise LogStash::ConfigurationError, "DLQ feature (dlq_custom_codes) is configured while DLQ is not enabled" unless dlq_custom_codes.empty?
|
339
|
-
end
|
350
|
+
end
|
340
351
|
|
352
|
+
def setup_mapper_and_target(data_stream_enabled)
|
341
353
|
if data_stream_enabled
|
342
354
|
@event_mapper = -> (e) { data_stream_event_action_tuple(e) }
|
343
355
|
@event_target = -> (e) { data_stream_name(e) }
|
@@ -346,14 +358,6 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
346
358
|
@event_mapper = -> (e) { event_action_tuple(e) }
|
347
359
|
@event_target = -> (e) { e.sprintf(@index) }
|
348
360
|
end
|
349
|
-
|
350
|
-
@bulk_request_metrics = metric.namespace(:bulk_requests)
|
351
|
-
@document_level_metrics = metric.namespace(:documents)
|
352
|
-
|
353
|
-
if ecs_compatibility == :v8
|
354
|
-
@logger.warn("Elasticsearch Output configured with `ecs_compatibility => v8`, which resolved to an UNRELEASED preview of version 8.0.0 of the Elastic Common Schema. " +
|
355
|
-
"Once ECS v8 and an updated release of this plugin are publicly available, you will need to update this plugin to resolve this warning.")
|
356
|
-
end
|
357
361
|
end
|
358
362
|
|
359
363
|
# @override post-register when ES connection established
|
@@ -431,7 +435,12 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
431
435
|
def wait_for_successful_connection
|
432
436
|
after_successful_connection_done = @after_successful_connection_done
|
433
437
|
return unless after_successful_connection_done
|
434
|
-
stoppable_sleep 1 until after_successful_connection_done.true?
|
438
|
+
stoppable_sleep 1 until (after_successful_connection_done.true? || pipeline_shutdown_requested?)
|
439
|
+
|
440
|
+
if pipeline_shutdown_requested?
|
441
|
+
logger.info "Aborting the batch due to shutdown request while waiting for connections to become live"
|
442
|
+
abort_batch_if_available!
|
443
|
+
end
|
435
444
|
|
436
445
|
status = @after_successful_connection_thread && @after_successful_connection_thread.value
|
437
446
|
if status.is_a?(Exception) # check if thread 'halted' with an error
|
@@ -159,6 +159,8 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
159
159
|
def after_successful_connection(&block)
|
160
160
|
Thread.new do
|
161
161
|
sleep_interval = @retry_initial_interval
|
162
|
+
# in case of a pipeline's shutdown_requested?, the method #close shutdown also this thread
|
163
|
+
# so no need to explicitly handle it here and return an AbortedBatchException.
|
162
164
|
until successful_connection? || @stopping.true?
|
163
165
|
@logger.debug("Waiting for connectivity to Elasticsearch cluster, retrying in #{sleep_interval}s")
|
164
166
|
sleep_interval = sleep_for_interval(sleep_interval)
|
@@ -191,8 +193,14 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
191
193
|
@logger.info("Retrying individual bulk actions that failed or were rejected by the previous bulk request", count: submit_actions.size)
|
192
194
|
end
|
193
195
|
rescue => e
|
194
|
-
|
195
|
-
|
196
|
+
if abort_batch_present? && e.instance_of?(org.logstash.execution.AbortedBatchException)
|
197
|
+
# if Logstash support abort of a batch and the batch is aborting,
|
198
|
+
# bubble up the exception so that the pipeline can handle it
|
199
|
+
raise e
|
200
|
+
else
|
201
|
+
@logger.error("Encountered an unexpected error submitting a bulk request, will retry",
|
202
|
+
message: e.message, exception: e.class, backtrace: e.backtrace)
|
203
|
+
end
|
196
204
|
end
|
197
205
|
|
198
206
|
# Everything was a success!
|
@@ -331,6 +339,11 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
331
339
|
|
332
340
|
sleep_interval = sleep_for_interval(sleep_interval)
|
333
341
|
@bulk_request_metrics.increment(:failures)
|
342
|
+
if pipeline_shutdown_requested?
|
343
|
+
# when any connection is available and a shutdown is requested
|
344
|
+
# the batch can be aborted, eventually for future retry.
|
345
|
+
abort_batch_if_available!
|
346
|
+
end
|
334
347
|
retry unless @stopping.true?
|
335
348
|
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
336
349
|
@bulk_request_metrics.increment(:failures)
|
@@ -349,6 +362,11 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
349
362
|
end
|
350
363
|
|
351
364
|
sleep_interval = sleep_for_interval(sleep_interval)
|
365
|
+
if pipeline_shutdown_requested?
|
366
|
+
# In case ES side changes access credentials and a pipeline reload is triggered
|
367
|
+
# this error becomes a retry on restart
|
368
|
+
abort_batch_if_available!
|
369
|
+
end
|
352
370
|
retry
|
353
371
|
rescue => e # Stuff that should never happen - print out full connection issues
|
354
372
|
@logger.error(
|
@@ -363,6 +381,19 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
363
381
|
end
|
364
382
|
end
|
365
383
|
|
384
|
+
def pipeline_shutdown_requested?
|
385
|
+
return super if defined?(super) # since LS 8.1.0
|
386
|
+
execution_context&.pipeline&.shutdown_requested
|
387
|
+
end
|
388
|
+
|
389
|
+
def abort_batch_if_available!
|
390
|
+
raise org.logstash.execution.AbortedBatchException.new if abort_batch_present?
|
391
|
+
end
|
392
|
+
|
393
|
+
def abort_batch_present?
|
394
|
+
::Gem::Version.create(LOGSTASH_VERSION) >= ::Gem::Version.create('8.8.0')
|
395
|
+
end
|
396
|
+
|
366
397
|
def dlq_enabled?
|
367
398
|
# TODO there should be a better way to query if DLQ is enabled
|
368
399
|
# See more in: https://github.com/elastic/logstash/issues/8064
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-elasticsearch'
|
3
|
-
s.version = '11.
|
3
|
+
s.version = '11.15.1'
|
4
4
|
s.licenses = ['apache-2.0']
|
5
5
|
s.summary = "Stores logs in Elasticsearch"
|
6
6
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
@@ -50,6 +50,104 @@ describe LogStash::Outputs::ElasticSearch do
|
|
50
50
|
subject.close
|
51
51
|
end
|
52
52
|
|
53
|
+
context "check aborting of a batch" do
|
54
|
+
context "on an unreachable ES instance" do
|
55
|
+
let(:events) { [ ::LogStash::Event.new("foo" => "bar1"), ::LogStash::Event.new("foo" => "bar2") ] }
|
56
|
+
|
57
|
+
let(:shutdown_value) { true }
|
58
|
+
|
59
|
+
let(:logger) { double("logger") }
|
60
|
+
|
61
|
+
before(:each) do
|
62
|
+
allow(subject).to receive(:logger).and_return(logger)
|
63
|
+
allow(logger).to receive(:info)
|
64
|
+
|
65
|
+
allow(subject).to receive(:pipeline_shutdown_requested?) do
|
66
|
+
shutdown_value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "the #multi_receive abort while waiting on unreachable and a shutdown is requested" do
|
71
|
+
expect { subject.multi_receive(events) }.to raise_error(org.logstash.execution.AbortedBatchException)
|
72
|
+
expect(logger).to have_received(:info).with(/Aborting the batch due to shutdown request while waiting for connections to become live/i)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when a connected ES becomes unreachable" do
|
77
|
+
# let(:error) do
|
78
|
+
# ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(
|
79
|
+
# 429, double("url").as_null_object, request_body, double("response body")
|
80
|
+
# )
|
81
|
+
# end
|
82
|
+
|
83
|
+
shared_examples 'raise an abort error' do
|
84
|
+
let(:options) {
|
85
|
+
{
|
86
|
+
"index" => "my-index",
|
87
|
+
"hosts" => ["localhost","localhost:9202"],
|
88
|
+
"path" => "some-path",
|
89
|
+
"manage_template" => false
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
let(:manticore_urls) { subject.client.pool.urls }
|
94
|
+
let(:manticore_url) { manticore_urls.first }
|
95
|
+
|
96
|
+
let(:stub_http_client_pool!) do
|
97
|
+
[:start_resurrectionist, :start_sniffer, :healthcheck!].each do |method|
|
98
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(method)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:event) { ::LogStash::Event.new("foo" => "bar") }
|
103
|
+
|
104
|
+
let(:logger) { double("logger").as_null_object }
|
105
|
+
let(:response) { { :errors => [], :items => [] } }
|
106
|
+
|
107
|
+
let(:request_body) { double(:request_body, :bytesize => 1023) }
|
108
|
+
|
109
|
+
before(:each) do
|
110
|
+
bulk_param = [["index", anything, event.to_hash]]
|
111
|
+
|
112
|
+
allow(subject).to receive(:logger).and_return(logger)
|
113
|
+
|
114
|
+
# fail consistently for ever
|
115
|
+
allow(subject.client).to receive(:bulk).with(bulk_param).and_raise(error)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should exit the retry with an abort exception if shutdown is requested" do
|
119
|
+
# execute in another thread because it blocks in a retry loop until the shutdown is triggered
|
120
|
+
th = Thread.new do
|
121
|
+
subject.multi_receive([event])
|
122
|
+
rescue org.logstash.execution.AbortedBatchException => e
|
123
|
+
# return exception's class so that it can be verified when retrieving the thread's value
|
124
|
+
e.class
|
125
|
+
end
|
126
|
+
|
127
|
+
# trigger the shutdown signal
|
128
|
+
allow(subject).to receive(:pipeline_shutdown_requested?) { true }
|
129
|
+
|
130
|
+
expect(th.value).to eq(org.logstash.execution.AbortedBatchException)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with 429 error" do
|
135
|
+
let(:error) do
|
136
|
+
::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(
|
137
|
+
429, double("url").as_null_object, request_body, double("response body")
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
it_behaves_like 'raise an abort error'
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with 'no connections' error" do
|
145
|
+
let(:error) { ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::NoConnectionAvailableError.new }
|
146
|
+
|
147
|
+
it_behaves_like 'raise an abort error'
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end if LOGSTASH_VERSION >= '8.8'
|
53
151
|
|
54
152
|
context "with an active instance" do
|
55
153
|
let(:options) {
|
@@ -1358,6 +1456,42 @@ describe LogStash::Outputs::ElasticSearch do
|
|
1358
1456
|
end
|
1359
1457
|
|
1360
1458
|
end
|
1459
|
+
|
1460
|
+
context 'during register/finish_register' do
|
1461
|
+
|
1462
|
+
let(:options) { { 'hosts' => '127.0.0.1:9999', 'data_stream' => 'true' } }
|
1463
|
+
let(:es_version) { '8.7.0' } # DS default on LS 8.x
|
1464
|
+
|
1465
|
+
before do
|
1466
|
+
allow(subject).to receive(:discover_cluster_uuid)
|
1467
|
+
allow(subject).to receive(:maybe_create_rollover_alias)
|
1468
|
+
allow(subject).to receive(:maybe_create_ilm_policy)
|
1469
|
+
allow(subject).to receive(:build_client)
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
# this test could not have been done using latches as the fix to the race
|
1473
|
+
# condition alters the order of the instructions in elasticsearch.rb
|
1474
|
+
#
|
1475
|
+
# the race condition happened when the @index was set to the datastream
|
1476
|
+
# after `ilm_in_use?` is called but before `setup_ilm`
|
1477
|
+
it 'doesn\'t have a race condition leading to resetting back to ILM' do
|
1478
|
+
ilm_in_use = subject.method(:ilm_in_use?)
|
1479
|
+
expect(subject).to receive(:ilm_in_use?) do |params|
|
1480
|
+
ret = ilm_in_use.call
|
1481
|
+
sleep 3
|
1482
|
+
ret
|
1483
|
+
end
|
1484
|
+
setup_mapper_and_target = subject.method(:setup_mapper_and_target)
|
1485
|
+
expect(subject).to receive(:setup_mapper_and_target).once do |params|
|
1486
|
+
sleep 1
|
1487
|
+
setup_mapper_and_target.call(params)
|
1488
|
+
end
|
1489
|
+
subject.register
|
1490
|
+
sleep 6
|
1491
|
+
expect(subject.index).to eq("logs-generic-default")
|
1492
|
+
end
|
1493
|
+
|
1494
|
+
end
|
1361
1495
|
end
|
1362
1496
|
|
1363
1497
|
@private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-elasticsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 11.
|
4
|
+
version: 11.15.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -356,7 +356,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
356
356
|
- !ruby/object:Gem::Version
|
357
357
|
version: '0'
|
358
358
|
requirements: []
|
359
|
-
rubygems_version: 3.
|
359
|
+
rubygems_version: 3.2.29
|
360
360
|
signing_key:
|
361
361
|
specification_version: 4
|
362
362
|
summary: Stores logs in Elasticsearch
|