logstash-output-elasticsearch 11.19.0-java → 11.20.0-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: '0490f311461b39c49e3edaf045af9a7172dbd97da8bc456bf044a031c18e5afb'
4
- data.tar.gz: fbf05190ed352c12f0948aecfa6ed08e760b03985b83aa2e6830167a00c431bc
3
+ metadata.gz: d6658ce0c72fc994e737d823dc03e53abf84d00c2692450173684fa9fc8a5865
4
+ data.tar.gz: 466cc891690d71b25df8992e93c7df1b64a09ab68b8e109fe4c4e8cf0faf25dc
5
5
  SHA512:
6
- metadata.gz: b50084b6fb4fd31e7592be7e35e23963dce4cf284763baa4c1c042d1f159f20cebe09c1013ace38a986dbf4c8ee3cc9ae4eda7f38042956bd10dbdfc0ad20114
7
- data.tar.gz: 91643fa15c48a29a02659967c75e0b879f98af2a6e7f1582c83b141f67826337ccaa3d0513b1372266dd068cbccfcdbbe59a5fcf36ceff81318126dd1bdf64cc
6
+ metadata.gz: 8116f03d6cd876a5e6997c07e3a12119c667e30061ca44bd8cdb70987d75659f4cd02bdb6bce15413c4e5c2d7fdac639aa10f95142006e85dcf2e9d248eedc85
7
+ data.tar.gz: 67a56fc6ea82742bbc2605fb09708f017d199fb39a1b59015ccd4b5ffdd8fd9a917dde68d7f2ff23448ef78eb4006af40e1521a8c754d0d38ace29a0a267109b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
+ ## 11.20.0
2
+ - 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)
3
+
1
4
  ## 11.19.0
2
- - Added `filter_path` to bulk requests to reduce the size of responses from elasticsearch
5
+ - 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
6
 
4
7
  ## 11.18.0
5
8
  - Added request header `Elastic-Api-Version` for serverless [#1147](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1147)
@@ -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
- fail 'no last_es_version' unless last_es_version # assert - should not happen
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::Error, "A data_stream configuration is only supported since Elasticsearch #{DATA_STREAMS_ORIGIN_ES_VERSION} " +
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
- fail "Failed to load default template for Elasticsearch v#{es_major_version} with ECS #{ecs_compatibility}; caused by: #{e.inspect}"
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 ArgumentError, "Template file '#{template_path}' could not be found" unless ::File.exists?(template_path)
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
- @after_successful_connection_thread.join unless @after_successful_connection_thread.nil?
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
@@ -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.19.0'
3
+ s.version = '11.20.0'
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(:get_es_version).and_raise(
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(:get_es_version).and_return(ESHelper.es_version)
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(:get_es_version).and_raise(
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(:get_es_version).and_return(ESHelper.es_version)
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
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.19.0
4
+ version: 11.20.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-25 00:00:00.000000000 Z
11
+ date: 2023-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement