logstash-output-elasticsearch 11.15.0-java → 11.15.2-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: e99f37b77580192819e3215149302e093a99906de26cdf613e4b6c6b24dacda5
4
- data.tar.gz: 6a18546d9e7f1fab675c4a88c1728646613cff63dc87dab5a2bac1756642b91f
3
+ metadata.gz: d000a73f7c5397c4e4643c0d1dbb4efb0c04b290054b0d455f020ec3443765d5
4
+ data.tar.gz: 9330ee2b0e8a903cc966c502fdc321e39fb2ee15b7b2782f2539567743346d71
5
5
  SHA512:
6
- metadata.gz: 3fb0cf262bf06830ae5089095f5421920f4ffad6936060df74286bf6aadbd18f729bca32021df94f7cb6251b48a6d25d7e00b849d83a5534718f2b0248c73e9c
7
- data.tar.gz: 50ddf8e65adb4d9b4e67519edaf19bf9b1f127fecc3d8b7736505d20bde0eac822c7d554f208aeed812efe3166940fba7655e484b40ce217785e92136594ad6a
6
+ metadata.gz: ddcee04fc7e64d4dd77b6c868c34e65e9fff345c7d1d2c37da5752ae612f09ae8147d0686cfdcdee8494c9c6e6c6045a204ddc157db959733c677f719ca958f9
7
+ data.tar.gz: '032939b34d7fbf6b4107295ea12c80ea651da05b29290154da37e6ff2b04cb123dcc07dee3bdce2ba184f06d2a2d0b4036dac9b3d8099e403bfda836efb4f29e'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 11.15.2
2
+ - Restores DLQ logging behavior from 11.8.x to include the action-tuple as structured [#1105](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1105)
3
+
4
+ ## 11.15.1
5
+ - Move async finish_register to bottom of register to avoid race condition [#1125](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1125)
6
+
1
7
  ## 11.15.0
2
8
  - 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)
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
- # To support BWC, we check if DLQ exists in core (< 5.4). If it doesn't, we use nil to resort to previous behavior.
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
@@ -401,7 +405,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
401
405
 
402
406
  event_mapping_errors.each do |event_mapping_error|
403
407
  detailed_message = "#{event_mapping_error.message}; event: `#{event_mapping_error.event.to_hash_with_metadata}`"
404
- handle_dlq_status(event_mapping_error.event, :warn, detailed_message)
408
+ @dlq_writer ? @dlq_writer.write(event_mapping_error.event, detailed_message) : @logger.warn(detailed_message)
405
409
  end
406
410
  @document_level_metrics.increment(:non_retryable_failures, event_mapping_errors.size)
407
411
  end
@@ -418,7 +422,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
418
422
  successful_events << @event_mapper.call(event)
419
423
  rescue EventMappingError => ie
420
424
  event_mapping_errors << FailedEventMapping.new(event, ie.message)
421
- end
425
+ end
422
426
  end
423
427
  MapEventsResult.new(successful_events, event_mapping_errors)
424
428
  end
@@ -227,22 +227,16 @@ module LogStash; module PluginMixins; module ElasticSearch
227
227
  end
228
228
 
229
229
  def handle_dlq_response(message, action, status, response)
230
- _, action_params = action.event, [action[0], action[1], action[2]]
230
+ event, action_params = action.event, [action[0], action[1], action[2]]
231
231
 
232
- # TODO: Change this to send a map with { :status => status, :action => action } in the future
233
- detailed_message = "#{message} status: #{status}, action: #{action_params}, response: #{response}"
234
-
235
- log_level = dig_value(response, 'index', 'error', 'type') == 'invalid_index_name_exception' ? :error : :warn
236
-
237
- handle_dlq_status(action.event, log_level, detailed_message)
238
- end
239
-
240
- def handle_dlq_status(event, log_level, message)
241
- # To support bwc, we check if DLQ exists. otherwise we log and drop event (previous behavior)
242
232
  if @dlq_writer
243
- @dlq_writer.write(event, "#{message}")
233
+ # TODO: Change this to send a map with { :status => status, :action => action } in the future
234
+ detailed_message = "#{message} status: #{status}, action: #{action_params}, response: #{response}"
235
+ @dlq_writer.write(event, "#{detailed_message}")
244
236
  else
245
- @logger.send log_level, message
237
+ log_level = dig_value(response, 'index', 'error', 'type') == 'invalid_index_name_exception' ? :error : :warn
238
+
239
+ @logger.public_send(log_level, message, status: status, action: action_params, response: response)
246
240
  end
247
241
  end
248
242
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-elasticsearch'
3
- s.version = '11.15.0'
3
+ s.version = '11.15.2'
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"
@@ -67,19 +67,24 @@ module ESHelper
67
67
  end
68
68
 
69
69
  RSpec::Matchers.define :have_hits do |expected|
70
+ hits_count_path = ESHelper.es_version_satisfies?(">=7") ? %w(hits total value) : %w(hits total)
71
+
70
72
  match do |actual|
71
- if ESHelper.es_version_satisfies?(">=7")
72
- expected == actual['hits']['total']['value']
73
- else
74
- expected == actual['hits']['total']
75
- end
73
+ @actual_hits_count = actual&.dig(*hits_count_path)
74
+ values_match? expected, @actual_hits_count
75
+ end
76
+ failure_message do |actual|
77
+ "expected that #{actual} with #{@actual_hits_count || "UNKNOWN" } hits would have #{expected} hits"
76
78
  end
77
79
  end
78
80
 
79
81
  RSpec::Matchers.define :have_index_pattern do |expected|
80
82
  match do |actual|
81
- test_against = Array(actual['index_patterns'].nil? ? actual['template'] : actual['index_patterns'])
82
- test_against.include?(expected)
83
+ @actual_index_pattterns = Array(actual['index_patterns'].nil? ? actual['template'] : actual['index_patterns'])
84
+ @actual_index_pattterns.any? { |v| values_match? expected, v }
85
+ end
86
+ failure_message do |actual|
87
+ "expected that #{actual} with index patterns #{@actual_index_pattterns} would have included `#{expected}`"
83
88
  end
84
89
  end
85
90
 
@@ -23,7 +23,9 @@ describe "index template expected behavior", :integration => true do
23
23
 
24
24
  elasticsearch_client.indices.delete_template(:name => '*')
25
25
  # This can fail if there are no indexes, ignore failure.
26
- elasticsearch_client.indices.delete(:index => '*') rescue nil
26
+ elasticsearch_client.indices.delete(:index => '*') rescue puts("DELETE INDICES ERROR: #{$!}")
27
+ # Since we are pinned to ES client 7.x, we need to delete data streams the hard way...
28
+ elasticsearch_client.perform_request("DELETE", "/_data_stream/*") rescue puts("DELETE DATA STREAMS ERROR: #{$!}")
27
29
  end
28
30
 
29
31
  context 'with ecs_compatibility => disabled' do
@@ -1121,41 +1121,63 @@ describe LogStash::Outputs::ElasticSearch do
1121
1121
  end if LOGSTASH_VERSION > '6.0'
1122
1122
 
1123
1123
  context 'handling elasticsearch document-level status meant for the DLQ' do
1124
+ let(:es_api_action) { "CUSTOM_ACTION" }
1125
+ let(:es_api_params) { Hash['_index' => 'MY_INDEX'] }
1126
+
1124
1127
  let(:options) { { "manage_template" => false, "data_stream" => 'false' } }
1125
- let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, LogStash::Event.new("foo" => "bar")) }
1128
+ let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(es_api_action, es_api_params, LogStash::Event.new("foo" => "bar")) }
1129
+
1130
+ let(:logger) { double('logger').as_null_object }
1131
+ before(:each) { subject.instance_variable_set(:@logger, logger) }
1126
1132
 
1127
1133
  context 'when @dlq_writer is nil' do
1128
1134
  before { subject.instance_variable_set '@dlq_writer', nil }
1129
- let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, LogStash::Event.new("foo" => "bar")) }
1130
1135
 
1131
1136
  context 'resorting to previous behaviour of logging the error' do
1132
1137
  context 'getting an invalid_index_name_exception' do
1133
1138
  it 'should log at ERROR level' do
1134
- subject.instance_variable_set(:@logger, double("logger").as_null_object)
1139
+ # logger = double("logger").as_null_object
1140
+ # subject.instance_variable_set(:@logger, logger)
1141
+
1135
1142
  mock_response = { 'index' => { 'error' => { 'type' => 'invalid_index_name_exception' } } }
1136
1143
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, :some_status, mock_response)
1144
+
1145
+ expect(logger).to have_received(:error).with(a_string_including("Could not index event to Elasticsearch"),
1146
+ a_hash_including(:status => :some_status,
1147
+ :action => [es_api_action, es_api_params, action.event.to_hash],
1148
+ :response => mock_response))
1137
1149
  end
1138
1150
  end
1139
1151
 
1140
1152
  context 'when getting any other exception' do
1141
1153
  it 'should log at WARN level' do
1142
- logger = double("logger").as_null_object
1143
- subject.instance_variable_set(:@logger, logger)
1144
- expect(logger).to receive(:warn).with(a_string_including "Could not index event to Elasticsearch. status: some_status, action: [:action, :params, {")
1154
+ # logger = double("logger").as_null_object
1155
+ # subject.instance_variable_set(:@logger, logger)
1156
+
1145
1157
  mock_response = { 'index' => { 'error' => { 'type' => 'illegal_argument_exception' } } }
1146
1158
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, :some_status, mock_response)
1159
+
1160
+ expect(logger).to have_received(:warn).with(a_string_including("Could not index event to Elasticsearch"),
1161
+ a_hash_including(:status => :some_status,
1162
+ :action => [es_api_action, es_api_params, action.event.to_hash],
1163
+ :response => mock_response))
1147
1164
  end
1148
1165
  end
1149
1166
 
1150
1167
  context 'when the response does not include [error]' do
1151
1168
  it 'should not fail, but just log a warning' do
1152
- logger = double("logger").as_null_object
1153
- subject.instance_variable_set(:@logger, logger)
1154
- expect(logger).to receive(:warn).with(a_string_including "Could not index event to Elasticsearch. status: some_status, action: [:action, :params, {")
1169
+ # logger = double("logger").as_null_object
1170
+ # subject.instance_variable_set(:@logger, logger)
1171
+
1155
1172
  mock_response = { 'index' => {} }
1156
1173
  expect do
1157
1174
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, :some_status, mock_response)
1158
1175
  end.to_not raise_error
1176
+
1177
+ expect(logger).to have_received(:warn).with(a_string_including("Could not index event to Elasticsearch"),
1178
+ a_hash_including(:status => :some_status,
1179
+ :action => [es_api_action, es_api_params, action.event.to_hash],
1180
+ :response => mock_response))
1159
1181
  end
1160
1182
  end
1161
1183
  end
@@ -1175,6 +1197,8 @@ describe LogStash::Outputs::ElasticSearch do
1175
1197
  mock_response = { 'index' => { 'error' => { 'type' => 'illegal_argument_exception' } } }
1176
1198
  action = LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, event)
1177
1199
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, 404, mock_response)
1200
+
1201
+ expect(logger).to_not have_received(:warn).with(a_string_including("Could not index event to Elasticsearch"))
1178
1202
  end
1179
1203
  end
1180
1204
 
@@ -1456,6 +1480,42 @@ describe LogStash::Outputs::ElasticSearch do
1456
1480
  end
1457
1481
 
1458
1482
  end
1483
+
1484
+ context 'during register/finish_register' do
1485
+
1486
+ let(:options) { { 'hosts' => '127.0.0.1:9999', 'data_stream' => 'true' } }
1487
+ let(:es_version) { '8.7.0' } # DS default on LS 8.x
1488
+
1489
+ before do
1490
+ allow(subject).to receive(:discover_cluster_uuid)
1491
+ allow(subject).to receive(:maybe_create_rollover_alias)
1492
+ allow(subject).to receive(:maybe_create_ilm_policy)
1493
+ allow(subject).to receive(:build_client)
1494
+ end
1495
+
1496
+ # this test could not have been done using latches as the fix to the race
1497
+ # condition alters the order of the instructions in elasticsearch.rb
1498
+ #
1499
+ # the race condition happened when the @index was set to the datastream
1500
+ # after `ilm_in_use?` is called but before `setup_ilm`
1501
+ it 'doesn\'t have a race condition leading to resetting back to ILM' do
1502
+ ilm_in_use = subject.method(:ilm_in_use?)
1503
+ expect(subject).to receive(:ilm_in_use?) do |params|
1504
+ ret = ilm_in_use.call
1505
+ sleep 3
1506
+ ret
1507
+ end
1508
+ setup_mapper_and_target = subject.method(:setup_mapper_and_target)
1509
+ expect(subject).to receive(:setup_mapper_and_target).once do |params|
1510
+ sleep 1
1511
+ setup_mapper_and_target.call(params)
1512
+ end
1513
+ subject.register
1514
+ sleep 6
1515
+ expect(subject.index).to eq("logs-generic-default")
1516
+ end
1517
+
1518
+ end
1459
1519
  end
1460
1520
 
1461
1521
  @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.15.0
4
+ version: 11.15.2
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-04 00:00:00.000000000 Z
11
+ date: 2023-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement