logstash-output-elasticsearch 11.19.0-java → 11.20.1-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 +7 -1
- data/docs/index.asciidoc +2 -2
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +2 -2
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +13 -8
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +4 -2
- data/lib/logstash/outputs/elasticsearch.rb +24 -2
- data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +1 -1
- data/lib/logstash/plugin_mixins/elasticsearch/common.rb +9 -0
- data/logstash-output-elasticsearch.gemspec +1 -1
- data/spec/integration/outputs/no_es_on_startup_spec.rb +4 -4
- data/spec/unit/outputs/error_whitelist_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f3f97949dede5ce24e127df3a0cf4c809f1436d1ff34831cea6d0b873784968
|
4
|
+
data.tar.gz: cadc8d310da90f1cc853b24734520859101cd787efe29b5371394248303999f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ef570b20433e6b3d69c24c9e402c39aa59a9f5556cb8c03f5643be65a7800b1a66b744be3095d11fe640a262902506fa78a7a10c3ea5b6ce1dfa81da98ea4e9
|
7
|
+
data.tar.gz: c323b23e45dfa795df06fdd206134ba340c5745529c690543bf94cfdb81526306c415723bb7a9cba759df658f38cbe6b6c62a4e6d1bbc6d777b224da830e8613
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
+
## 11.20.1
|
2
|
+
- Doc: Replace `document_already_exist_exception` with `version_conflict_engine_exception` in the `silence_errors_in_log` setting example [#1159](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1159)
|
3
|
+
|
4
|
+
## 11.20.0
|
5
|
+
- Changed the register to initiate pipeline shutdown upon bootstrap failure instead of simply logging the error [#1151](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1151)
|
6
|
+
|
1
7
|
## 11.19.0
|
2
|
-
- Added `filter_path` to bulk requests to reduce the size of responses from elasticsearch
|
8
|
+
- Added `filter_path` to bulk requests to reduce the size of responses from elasticsearch [#1154](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1154)
|
3
9
|
|
4
10
|
## 11.18.0
|
5
11
|
- Added request header `Elastic-Api-Version` for serverless [#1147](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1147)
|
data/docs/index.asciidoc
CHANGED
@@ -988,12 +988,12 @@ if enabled, script is in charge of creating non-existent document (scripted upda
|
|
988
988
|
|
989
989
|
Defines the list of Elasticsearch errors that you don't want to log.
|
990
990
|
A useful example is when you want to skip all 409 errors
|
991
|
-
which are `
|
991
|
+
which are `version_conflict_engine_exception`.
|
992
992
|
|
993
993
|
[source,ruby]
|
994
994
|
output {
|
995
995
|
elasticsearch {
|
996
|
-
silence_errors_in_log => ["
|
996
|
+
silence_errors_in_log => ["version_conflict_engine_exception"]
|
997
997
|
}
|
998
998
|
}
|
999
999
|
|
@@ -145,12 +145,12 @@ module LogStash module Outputs class ElasticSearch
|
|
145
145
|
# @note assumes to be running AFTER {after_successful_connection} completed, due ES version checks
|
146
146
|
# @return [Gem::Version] if ES supports DS nil (or raise) otherwise
|
147
147
|
def assert_es_version_supports_data_streams
|
148
|
-
|
148
|
+
raise LogStash::ConfigurationError 'no last_es_version' unless last_es_version # assert - should not happen
|
149
149
|
es_version = ::Gem::Version.create(last_es_version)
|
150
150
|
if es_version < ::Gem::Version.create(DATA_STREAMS_ORIGIN_ES_VERSION)
|
151
151
|
@logger.error "Elasticsearch version does not support data streams, Logstash might end up writing to an index", es_version: es_version.version
|
152
152
|
# NOTE: when switching to synchronous check from register, this should be a ConfigurationError
|
153
|
-
raise LogStash::
|
153
|
+
raise LogStash::ConfigurationError, "A data_stream configuration is only supported since Elasticsearch #{DATA_STREAMS_ORIGIN_ES_VERSION} " +
|
154
154
|
"(detected version #{es_version.version}), please upgrade your cluster"
|
155
155
|
end
|
156
156
|
es_version # return truthy
|
@@ -28,7 +28,12 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
28
28
|
@response_code == 403
|
29
29
|
end
|
30
30
|
|
31
|
+
def too_many_requests?
|
32
|
+
@response_code == 429
|
33
|
+
end
|
34
|
+
|
31
35
|
end
|
36
|
+
|
32
37
|
class HostUnreachableError < Error;
|
33
38
|
attr_reader :original_error, :url
|
34
39
|
|
@@ -69,7 +74,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
69
74
|
@adapter = adapter
|
70
75
|
@metric = options[:metric]
|
71
76
|
@initial_urls = initial_urls
|
72
|
-
|
77
|
+
|
73
78
|
raise ArgumentError, "No URL Normalizer specified!" unless options[:url_normalizer]
|
74
79
|
@url_normalizer = options[:url_normalizer]
|
75
80
|
DEFAULT_OPTIONS.merge(options).tap do |merged|
|
@@ -159,7 +164,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
159
164
|
:error_message => e.message,
|
160
165
|
:class => e.class.name,
|
161
166
|
:backtrace => e.backtrace
|
162
|
-
|
167
|
+
)
|
163
168
|
end
|
164
169
|
end
|
165
170
|
end
|
@@ -197,11 +202,11 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
197
202
|
sniff(nodes)
|
198
203
|
end
|
199
204
|
end
|
200
|
-
|
205
|
+
|
201
206
|
def major_version(version_string)
|
202
207
|
version_string.split('.').first.to_i
|
203
208
|
end
|
204
|
-
|
209
|
+
|
205
210
|
def sniff(nodes)
|
206
211
|
nodes.map do |id,info|
|
207
212
|
# Skip master-only nodes
|
@@ -360,7 +365,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
360
365
|
|
361
366
|
def update_urls(new_urls)
|
362
367
|
return if new_urls.nil?
|
363
|
-
|
368
|
+
|
364
369
|
# Normalize URLs
|
365
370
|
new_urls = new_urls.map(&method(:normalize_url))
|
366
371
|
|
@@ -388,14 +393,14 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
388
393
|
if state_changes[:removed].size > 0 || state_changes[:added].size > 0
|
389
394
|
logger.info? && logger.info("Elasticsearch pool URLs updated", :changes => state_changes)
|
390
395
|
end
|
391
|
-
|
396
|
+
|
392
397
|
# Run an inline healthcheck anytime URLs are updated
|
393
398
|
# This guarantees that during startup / post-startup
|
394
399
|
# sniffing we don't have idle periods waiting for the
|
395
400
|
# periodic sniffer to allow new hosts to come online
|
396
|
-
healthcheck!
|
401
|
+
healthcheck!
|
397
402
|
end
|
398
|
-
|
403
|
+
|
399
404
|
def size
|
400
405
|
@state_mutex.synchronize { @url_info.size }
|
401
406
|
end
|
@@ -37,7 +37,7 @@ module LogStash; module Outputs; class ElasticSearch
|
|
37
37
|
template_path = default_template_path(es_major_version, ecs_compatibility)
|
38
38
|
read_template_file(template_path)
|
39
39
|
rescue => e
|
40
|
-
|
40
|
+
raise LogStash::ConfigurationError, "Failed to load default template for Elasticsearch v#{es_major_version} with ECS #{ecs_compatibility}; caused by: #{e.inspect}"
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.install(client, template_endpoint, template_name, template, template_overwrite)
|
@@ -99,9 +99,11 @@ module LogStash; module Outputs; class ElasticSearch
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def self.read_template_file(template_path)
|
102
|
-
raise
|
102
|
+
raise LogStash::ConfigurationError, "Template file '#{template_path}' could not be found" unless ::File.exists?(template_path)
|
103
103
|
template_data = ::IO.read(template_path)
|
104
104
|
LogStash::Json.load(template_data)
|
105
|
+
rescue => e
|
106
|
+
raise LogStash::ConfigurationError, "Failed to load template file '#{template_path}': #{e.message}"
|
105
107
|
end
|
106
108
|
|
107
109
|
def self.template_endpoint(plugin)
|
@@ -322,12 +322,29 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
322
322
|
@bulk_request_metrics = metric.namespace(:bulk_requests)
|
323
323
|
@document_level_metrics = metric.namespace(:documents)
|
324
324
|
|
325
|
+
@shutdown_from_finish_register = Concurrent::AtomicBoolean.new(false)
|
325
326
|
@after_successful_connection_thread = after_successful_connection do
|
326
327
|
begin
|
327
328
|
finish_register
|
328
329
|
true # thread.value
|
330
|
+
rescue LogStash::ConfigurationError, LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
331
|
+
return e if pipeline_shutdown_requested?
|
332
|
+
|
333
|
+
# retry when 429
|
334
|
+
@logger.debug("Received a 429 status code during registration. Retrying..") && retry if too_many_requests?(e)
|
335
|
+
|
336
|
+
# shut down pipeline
|
337
|
+
if execution_context&.agent.respond_to?(:stop_pipeline)
|
338
|
+
details = { message: e.message, exception: e.class }
|
339
|
+
details[:backtrace] = e.backtrace if @logger.debug?
|
340
|
+
@logger.error("Failed to bootstrap. Pipeline \"#{execution_context.pipeline_id}\" is going to shut down", details)
|
341
|
+
|
342
|
+
@shutdown_from_finish_register.make_true
|
343
|
+
execution_context.agent.stop_pipeline(execution_context.pipeline_id)
|
344
|
+
end
|
345
|
+
|
346
|
+
e
|
329
347
|
rescue => e
|
330
|
-
# we do not want to halt the thread with an exception as that has consequences for LS
|
331
348
|
e # thread.value
|
332
349
|
ensure
|
333
350
|
@after_successful_connection_done.make_true
|
@@ -450,7 +467,11 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
450
467
|
private
|
451
468
|
|
452
469
|
def stop_after_successful_connection_thread
|
453
|
-
|
470
|
+
# avoid deadlock when finish_register calling execution_context.agent.stop_pipeline
|
471
|
+
# stop_pipeline triggers plugin close and the plugin close waits for after_successful_connection_thread to join
|
472
|
+
return if @shutdown_from_finish_register&.true?
|
473
|
+
|
474
|
+
@after_successful_connection_thread.join if @after_successful_connection_thread&.alive?
|
454
475
|
end
|
455
476
|
|
456
477
|
# Convert the event into a 3-tuple of action, params and event hash
|
@@ -599,6 +620,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
599
620
|
details = { message: e.message, exception: e.class, backtrace: e.backtrace }
|
600
621
|
details[:body] = e.response_body if e.respond_to?(:response_body)
|
601
622
|
@logger.error("Failed to install template", details)
|
623
|
+
raise e if register_termination_error?(e)
|
602
624
|
end
|
603
625
|
|
604
626
|
def setup_ecs_compatibility_related_defaults
|
@@ -149,7 +149,7 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
149
149
|
|
150
150
|
# Defines the list of Elasticsearch errors that you don't want to log.
|
151
151
|
# A useful example is when you want to skip all 409 errors
|
152
|
-
# which are `
|
152
|
+
# which are `version_conflict_engine_exception`.
|
153
153
|
# Deprecates `failure_type_logging_whitelist`.
|
154
154
|
:silence_errors_in_log => { :validate => :array, :default => [] },
|
155
155
|
|
@@ -407,5 +407,14 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
407
407
|
return val if rest_keys.empty? || val == nil
|
408
408
|
dig_value(val, *rest_keys)
|
409
409
|
end
|
410
|
+
|
411
|
+
def register_termination_error?(e)
|
412
|
+
e.is_a?(LogStash::ConfigurationError) || e.is_a?(LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError)
|
413
|
+
end
|
414
|
+
|
415
|
+
def too_many_requests?(e)
|
416
|
+
e.is_a?(LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError) &&
|
417
|
+
e.too_many_requests?
|
418
|
+
end
|
410
419
|
end
|
411
420
|
end; end; end
|
@@ -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.20.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"
|
@@ -33,11 +33,11 @@ describe "elasticsearch is down on startup", :integration => true do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'should ingest events when Elasticsearch recovers before documents are sent' do
|
36
|
-
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:
|
36
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:get_root_path).with(any_args).and_raise(
|
37
37
|
::LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError.new StandardError.new("TEST: before docs are sent"), 'http://test.es/'
|
38
38
|
)
|
39
39
|
subject.register
|
40
|
-
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:
|
40
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:get_root_path).with(any_args).and_call_original
|
41
41
|
subject.multi_receive([event1, event2])
|
42
42
|
@es.indices.refresh
|
43
43
|
r = @es.search(index: 'logstash-*')
|
@@ -45,13 +45,13 @@ describe "elasticsearch is down on startup", :integration => true do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'should ingest events when Elasticsearch recovers after documents are sent' do
|
48
|
-
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:
|
48
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:get_root_path).with(any_args).and_raise(
|
49
49
|
::LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError.new StandardError.new("TEST: after docs are sent"), 'http://test.es/'
|
50
50
|
)
|
51
51
|
subject.register
|
52
52
|
Thread.new do
|
53
53
|
sleep 4
|
54
|
-
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:
|
54
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:get_root_path).with(any_args).and_call_original
|
55
55
|
end
|
56
56
|
subject.multi_receive([event1, event2])
|
57
57
|
@es.indices.refresh
|
@@ -25,7 +25,7 @@ describe "whitelisting error types in expected behavior" do
|
|
25
25
|
"create" => {
|
26
26
|
"status" => 409,
|
27
27
|
"error" => {
|
28
|
-
"type" => "
|
28
|
+
"type" => "version_conflict_engine_exception",
|
29
29
|
"reason" => "[shard] document already exists"
|
30
30
|
}
|
31
31
|
}
|
@@ -46,7 +46,7 @@ describe "whitelisting error types in expected behavior" do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
describe "when failure logging is disabled for document exists error" do
|
49
|
-
let(:settings) { super().merge("silence_errors_in_log" => ["
|
49
|
+
let(:settings) { super().merge("silence_errors_in_log" => ["version_conflict_engine_exception"]) }
|
50
50
|
|
51
51
|
it "should log a failure on the action" do
|
52
52
|
expect(subject.logger).not_to have_received(:warn).with("Failed action", anything)
|
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.20.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-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|