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
@@ -5,7 +5,7 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
5
5
|
|
6
6
|
# This module defines common methods that can be reused by alternate elasticsearch output plugins such as the elasticsearch_data_streams output.
|
7
7
|
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :hosts
|
9
9
|
|
10
10
|
# These codes apply to documents, not at the request level
|
11
11
|
DOC_DLQ_CODES = [400, 404]
|
@@ -31,7 +31,7 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
31
31
|
if @proxy.eql?('')
|
32
32
|
@logger.warn "Supplied proxy setting (proxy => '') has no effect"
|
33
33
|
end
|
34
|
-
|
34
|
+
::LogStash::Outputs::ElasticSearch::HttpClientBuilder.build(@logger, @hosts, params)
|
35
35
|
end
|
36
36
|
|
37
37
|
def validate_authentication
|
@@ -115,6 +115,15 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
115
115
|
end
|
116
116
|
private :parse_user_password_from_cloud_auth
|
117
117
|
|
118
|
+
# Plugin initialization extension point (after a successful ES connection).
|
119
|
+
def finish_register
|
120
|
+
end
|
121
|
+
protected :finish_register
|
122
|
+
|
123
|
+
def last_es_version
|
124
|
+
client.last_es_version
|
125
|
+
end
|
126
|
+
|
118
127
|
def maximum_seen_major_version
|
119
128
|
client.maximum_seen_major_version
|
120
129
|
end
|
@@ -126,25 +135,24 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
126
135
|
# launch a thread that waits for an initial successful connection to the ES cluster to call the given block
|
127
136
|
# @param block [Proc] the block to execute upon initial successful connection
|
128
137
|
# @return [Thread] the successful connection wait thread
|
129
|
-
def
|
138
|
+
def after_successful_connection(&block)
|
130
139
|
Thread.new do
|
131
140
|
sleep_interval = @retry_initial_interval
|
132
141
|
until successful_connection? || @stopping.true?
|
133
|
-
@logger.debug("Waiting for connectivity to Elasticsearch cluster
|
134
|
-
|
135
|
-
sleep_interval = next_sleep_interval(sleep_interval)
|
142
|
+
@logger.debug("Waiting for connectivity to Elasticsearch cluster, retrying in #{sleep_interval}s")
|
143
|
+
sleep_interval = sleep_for_interval(sleep_interval)
|
136
144
|
end
|
137
145
|
block.call if successful_connection?
|
138
146
|
end
|
139
147
|
end
|
148
|
+
private :after_successful_connection
|
140
149
|
|
141
150
|
def discover_cluster_uuid
|
142
151
|
return unless defined?(plugin_metadata)
|
143
152
|
cluster_info = client.get('/')
|
144
153
|
plugin_metadata.set(:cluster_uuid, cluster_info['cluster_uuid'])
|
145
154
|
rescue => e
|
146
|
-
|
147
|
-
# @logger.error("Unable to retrieve elasticsearch cluster uuid", error => e.message)
|
155
|
+
@logger.error("Unable to retrieve Elasticsearch cluster uuid", message: e.message, exception: e.class, backtrace: e.backtrace)
|
148
156
|
end
|
149
157
|
|
150
158
|
def retrying_submit(actions)
|
@@ -159,13 +167,11 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
159
167
|
begin
|
160
168
|
submit_actions = submit(submit_actions)
|
161
169
|
if submit_actions && submit_actions.size > 0
|
162
|
-
@logger.info("Retrying individual bulk actions that failed or were rejected by the previous bulk request
|
170
|
+
@logger.info("Retrying individual bulk actions that failed or were rejected by the previous bulk request", count: submit_actions.size)
|
163
171
|
end
|
164
172
|
rescue => e
|
165
|
-
@logger.error("Encountered an unexpected error submitting a bulk request
|
166
|
-
|
167
|
-
:class => e.class.name,
|
168
|
-
:backtrace => e.backtrace)
|
173
|
+
@logger.error("Encountered an unexpected error submitting a bulk request, will retry",
|
174
|
+
message: e.message, exception: e.class, backtrace: e.backtrace)
|
169
175
|
end
|
170
176
|
|
171
177
|
# Everything was a success!
|
@@ -173,21 +179,42 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
173
179
|
|
174
180
|
# If we're retrying the action sleep for the recommended interval
|
175
181
|
# Double the interval for the next time through to achieve exponential backoff
|
176
|
-
|
177
|
-
sleep_interval = next_sleep_interval(sleep_interval)
|
182
|
+
sleep_interval = sleep_for_interval(sleep_interval)
|
178
183
|
end
|
179
184
|
end
|
180
185
|
|
181
186
|
def sleep_for_interval(sleep_interval)
|
182
|
-
|
187
|
+
stoppable_sleep(sleep_interval)
|
183
188
|
next_sleep_interval(sleep_interval)
|
184
189
|
end
|
185
190
|
|
191
|
+
def stoppable_sleep(interval)
|
192
|
+
Stud.stoppable_sleep(interval) { @stopping.true? }
|
193
|
+
end
|
194
|
+
|
186
195
|
def next_sleep_interval(current_interval)
|
187
196
|
doubled = current_interval * 2
|
188
197
|
doubled > @retry_max_interval ? @retry_max_interval : doubled
|
189
198
|
end
|
190
199
|
|
200
|
+
def handle_dlq_status(message, action, status, response)
|
201
|
+
# To support bwc, we check if DLQ exists. otherwise we log and drop event (previous behavior)
|
202
|
+
if @dlq_writer
|
203
|
+
event, action = action.event, [action[0], action[1], action[2]]
|
204
|
+
# TODO: Change this to send a map with { :status => status, :action => action } in the future
|
205
|
+
@dlq_writer.write(event, "#{message} status: #{status}, action: #{action}, response: #{response}")
|
206
|
+
else
|
207
|
+
if dig_value(response, 'index', 'error', 'type') == 'invalid_index_name_exception'
|
208
|
+
level = :error
|
209
|
+
else
|
210
|
+
level = :warn
|
211
|
+
end
|
212
|
+
@logger.send level, message, status: status, action: action, response: response
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
private
|
217
|
+
|
191
218
|
def submit(actions)
|
192
219
|
bulk_response = safe_bulk(actions)
|
193
220
|
|
@@ -217,7 +244,7 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
217
244
|
action_type, action_props = response.first
|
218
245
|
|
219
246
|
status = action_props["status"]
|
220
|
-
|
247
|
+
error = action_props["error"]
|
221
248
|
action = actions[idx]
|
222
249
|
action_params = action[1]
|
223
250
|
|
@@ -230,7 +257,7 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
230
257
|
next
|
231
258
|
elsif DOC_CONFLICT_CODE == status
|
232
259
|
@document_level_metrics.increment(:non_retryable_failures)
|
233
|
-
@logger.warn "Failed action
|
260
|
+
@logger.warn "Failed action", status: status, action: action, response: response if log_failure_type?(error)
|
234
261
|
next
|
235
262
|
elsif DOC_DLQ_CODES.include?(status)
|
236
263
|
handle_dlq_status("Could not index event to Elasticsearch.", action, status, response)
|
@@ -239,7 +266,7 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
239
266
|
else
|
240
267
|
# only log what the user whitelisted
|
241
268
|
@document_level_metrics.increment(:retryable_failures)
|
242
|
-
@logger.info "
|
269
|
+
@logger.info "Retrying failed action", status: status, action: action, error: error if log_failure_type?(error)
|
243
270
|
actions_to_retry << action
|
244
271
|
end
|
245
272
|
end
|
@@ -247,40 +274,25 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
247
274
|
actions_to_retry
|
248
275
|
end
|
249
276
|
|
250
|
-
def
|
251
|
-
|
252
|
-
if @dlq_writer
|
253
|
-
# TODO: Change this to send a map with { :status => status, :action => action } in the future
|
254
|
-
@dlq_writer.write(action[2], "#{message} status: #{status}, action: #{action}, response: #{response}")
|
255
|
-
else
|
256
|
-
error_type = response.fetch('index', {}).fetch('error', {})['type']
|
257
|
-
if 'invalid_index_name_exception' == error_type
|
258
|
-
level = :error
|
259
|
-
else
|
260
|
-
level = :warn
|
261
|
-
end
|
262
|
-
@logger.send level, message, status: status, action: action, response: response
|
263
|
-
end
|
277
|
+
def log_failure_type?(failure)
|
278
|
+
!failure_type_logging_whitelist.include?(failure["type"])
|
264
279
|
end
|
265
280
|
|
266
281
|
# Rescue retryable errors during bulk submission
|
282
|
+
# @param actions a [action, params, event.to_hash] tuple
|
283
|
+
# @return response [Hash] which contains 'errors' and processed 'items' entries
|
267
284
|
def safe_bulk(actions)
|
268
285
|
sleep_interval = @retry_initial_interval
|
269
286
|
begin
|
270
|
-
|
271
|
-
response = @client.bulk(es_actions)
|
272
|
-
response
|
287
|
+
@client.bulk(actions) # returns { 'errors': ..., 'items': ... }
|
273
288
|
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError => e
|
274
289
|
# If we can't even connect to the server let's just print out the URL (:hosts is actually a URL)
|
275
290
|
# and let the user sort it out from there
|
276
291
|
@logger.error(
|
277
|
-
"Attempted to send a bulk request to
|
278
|
-
|
279
|
-
:error_message => e.message,
|
280
|
-
:class => e.class.name,
|
281
|
-
:will_retry_in_seconds => sleep_interval
|
292
|
+
"Attempted to send a bulk request but Elasticsearch appears to be unreachable or down",
|
293
|
+
message: e.message, exception: e.class, will_retry_in_seconds: sleep_interval
|
282
294
|
)
|
283
|
-
@logger.debug("Failed actions for last bad bulk request
|
295
|
+
@logger.debug? && @logger.debug("Failed actions for last bad bulk request", :actions => actions)
|
284
296
|
|
285
297
|
# We retry until there are no errors! Errors should all go to the retry queue
|
286
298
|
sleep_interval = sleep_for_interval(sleep_interval)
|
@@ -288,20 +300,19 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
288
300
|
retry unless @stopping.true?
|
289
301
|
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::NoConnectionAvailableError => e
|
290
302
|
@logger.error(
|
291
|
-
"Attempted to send a bulk request
|
292
|
-
|
293
|
-
:
|
294
|
-
:will_retry_in_seconds => sleep_interval
|
303
|
+
"Attempted to send a bulk request but there are no living connections in the pool " +
|
304
|
+
"(perhaps Elasticsearch is unreachable or down?)",
|
305
|
+
message: e.message, exception: e.class, will_retry_in_seconds: sleep_interval
|
295
306
|
)
|
296
|
-
|
297
|
-
sleep_interval =
|
307
|
+
|
308
|
+
sleep_interval = sleep_for_interval(sleep_interval)
|
298
309
|
@bulk_request_metrics.increment(:failures)
|
299
310
|
retry unless @stopping.true?
|
300
311
|
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
301
312
|
@bulk_request_metrics.increment(:failures)
|
302
313
|
log_hash = {:code => e.response_code, :url => e.url.sanitized.to_s, :content_length => e.request_body.bytesize}
|
303
314
|
log_hash[:body] = e.response_body if @logger.debug? # Generally this is too verbose
|
304
|
-
message = "Encountered a retryable error
|
315
|
+
message = "Encountered a retryable error (will retry with exponential backoff)"
|
305
316
|
|
306
317
|
# We treat 429s as a special case because these really aren't errors, but
|
307
318
|
# rather just ES telling us to back off a bit, which we do.
|
@@ -315,17 +326,12 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
315
326
|
|
316
327
|
sleep_interval = sleep_for_interval(sleep_interval)
|
317
328
|
retry
|
318
|
-
rescue => e
|
319
|
-
# Stuff that should never happen
|
320
|
-
# For all other errors print out full connection issues
|
329
|
+
rescue => e # Stuff that should never happen - print out full connection issues
|
321
330
|
@logger.error(
|
322
|
-
"An unknown error occurred sending a bulk request to Elasticsearch
|
323
|
-
:
|
324
|
-
:error_class => e.class.name,
|
325
|
-
:backtrace => e.backtrace
|
331
|
+
"An unknown error occurred sending a bulk request to Elasticsearch (will retry indefinitely)",
|
332
|
+
message: e.message, exception: e.class, backtrace: e.backtrace
|
326
333
|
)
|
327
|
-
|
328
|
-
@logger.debug("Failed actions for last bad bulk request!", :actions => actions)
|
334
|
+
@logger.debug? && @logger.debug("Failed actions for last bad bulk request", :actions => actions)
|
329
335
|
|
330
336
|
sleep_interval = sleep_for_interval(sleep_interval)
|
331
337
|
@bulk_request_metrics.increment(:failures)
|
@@ -339,5 +345,12 @@ module LogStash; module PluginMixins; module ElasticSearch
|
|
339
345
|
respond_to?(:execution_context) && execution_context.respond_to?(:dlq_writer) &&
|
340
346
|
!execution_context.dlq_writer.inner_writer.is_a?(::LogStash::Util::DummyDeadLetterQueueWriter)
|
341
347
|
end
|
348
|
+
|
349
|
+
def dig_value(val, first_key, *rest_keys)
|
350
|
+
fail(TypeError, "cannot dig value from #{val.class}") unless val.kind_of?(Hash)
|
351
|
+
val = val[first_key]
|
352
|
+
return val if rest_keys.empty? || val == nil
|
353
|
+
dig_value(val, *rest_keys)
|
354
|
+
end
|
342
355
|
end
|
343
356
|
end; end; end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-elasticsearch'
|
3
|
-
s.version = '
|
3
|
+
s.version = '11.0.3'
|
4
4
|
|
5
5
|
s.licenses = ['apache-2.0']
|
6
6
|
s.summary = "Stores logs in Elasticsearch"
|
@@ -21,15 +21,15 @@ Gem::Specification.new do |s|
|
|
21
21
|
# Special flag to let us know this is actually a logstash plugin
|
22
22
|
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
|
23
23
|
|
24
|
-
s.add_runtime_dependency "manticore", '>= 0.
|
24
|
+
s.add_runtime_dependency "manticore", '>= 0.7.1', '< 1.0.0'
|
25
25
|
s.add_runtime_dependency 'stud', ['>= 0.0.17', '~> 0.0']
|
26
|
-
s.add_runtime_dependency 'cabin', ['~> 0.6']
|
27
26
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
28
27
|
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.0'
|
29
28
|
|
30
29
|
s.add_development_dependency 'logstash-codec-plain'
|
31
30
|
s.add_development_dependency 'logstash-devutils'
|
32
31
|
s.add_development_dependency 'flores'
|
32
|
+
s.add_development_dependency 'cabin', ['~> 0.6']
|
33
33
|
# Still used in some specs, we should remove this ASAP
|
34
34
|
s.add_development_dependency 'elasticsearch'
|
35
35
|
end
|
data/spec/es_spec_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
3
|
require 'elasticsearch'
|
4
4
|
require_relative "support/elasticsearch/api/actions/delete_ilm_policy"
|
5
5
|
require_relative "support/elasticsearch/api/actions/get_alias"
|
@@ -8,10 +8,7 @@ require_relative "support/elasticsearch/api/actions/get_ilm_policy"
|
|
8
8
|
require_relative "support/elasticsearch/api/actions/put_ilm_policy"
|
9
9
|
|
10
10
|
require 'json'
|
11
|
-
|
12
|
-
unless defined?(LogStash::OSS)
|
13
|
-
LogStash::OSS = ENV['DISTRIBUTION'] != "default"
|
14
|
-
end
|
11
|
+
require 'cabin'
|
15
12
|
|
16
13
|
module ESHelper
|
17
14
|
def get_host_port
|
@@ -23,7 +20,9 @@ module ESHelper
|
|
23
20
|
end
|
24
21
|
|
25
22
|
def get_client
|
26
|
-
Elasticsearch::Client.new(:hosts => [get_host_port])
|
23
|
+
Elasticsearch::Client.new(:hosts => [get_host_port]).tap do |client|
|
24
|
+
allow(client).to receive(:verify_elasticsearch).and_return(true) # bypass client side version checking
|
25
|
+
end
|
27
26
|
end
|
28
27
|
|
29
28
|
def doc_type
|
@@ -56,11 +55,7 @@ module ESHelper
|
|
56
55
|
end
|
57
56
|
|
58
57
|
def routing_field_name
|
59
|
-
|
60
|
-
:routing
|
61
|
-
else
|
62
|
-
:_routing
|
63
|
-
end
|
58
|
+
:routing
|
64
59
|
end
|
65
60
|
|
66
61
|
def self.es_version
|
@@ -11,7 +11,7 @@
|
|
11
11
|
"transport_address" : "http://localhost:9200",
|
12
12
|
"host" : "localhost",
|
13
13
|
"ip" : "127.0.0.1",
|
14
|
-
"version" : "
|
14
|
+
"version" : "6.8.10",
|
15
15
|
"build_hash" : "19c13d0",
|
16
16
|
"roles" : [
|
17
17
|
"master"
|
@@ -29,7 +29,7 @@
|
|
29
29
|
"transport_address" : "http://localhost:9201",
|
30
30
|
"host" : "localhost",
|
31
31
|
"ip" : "127.0.0.1",
|
32
|
-
"version" : "
|
32
|
+
"version" : "6.8.10",
|
33
33
|
"build_hash" : "19c13d0",
|
34
34
|
"roles" : [
|
35
35
|
"data"
|
@@ -47,7 +47,7 @@
|
|
47
47
|
"transport_address" : "http://localhost:9202",
|
48
48
|
"host" : "localhost",
|
49
49
|
"ip" : "127.0.0.1",
|
50
|
-
"version" : "
|
50
|
+
"version" : "6.8.10",
|
51
51
|
"build_hash" : "19c13d0",
|
52
52
|
"roles" : [
|
53
53
|
"data",
|
@@ -66,7 +66,7 @@
|
|
66
66
|
"transport_address" : "http://localhost:9203",
|
67
67
|
"host" : "localhost",
|
68
68
|
"ip" : "127.0.0.1",
|
69
|
-
"version" : "
|
69
|
+
"version" : "6.8.10",
|
70
70
|
"build_hash" : "19c13d0",
|
71
71
|
"roles" : [ ],
|
72
72
|
"http" : {
|
@@ -78,4 +78,4 @@
|
|
78
78
|
}
|
79
79
|
}
|
80
80
|
}
|
81
|
-
}
|
81
|
+
}
|
@@ -8,62 +8,63 @@ RSpec::Matchers.define :a_valid_gzip_encoded_string do
|
|
8
8
|
}
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"http_compression" => true
|
23
|
-
}
|
11
|
+
describe "indexing with http_compression turned on", :integration => true do
|
12
|
+
let(:event) { LogStash::Event.new("message" => "Hello World!", "type" => type) }
|
13
|
+
let(:index) { 10.times.collect { rand(10).to_s }.join("") }
|
14
|
+
let(:type) { ESHelper.es_version_satisfies?("< 7") ? "doc" : "_doc" }
|
15
|
+
let(:event_count) { 10000 + rand(500) }
|
16
|
+
let(:events) { event_count.times.map { event }.to_a }
|
17
|
+
let(:config) {
|
18
|
+
{
|
19
|
+
"hosts" => get_host_port,
|
20
|
+
"index" => index,
|
21
|
+
"http_compression" => true
|
24
22
|
}
|
25
|
-
|
23
|
+
}
|
24
|
+
subject { LogStash::Outputs::ElasticSearch.new(config) }
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
let(:es_url) { "http://#{get_host_port}" }
|
27
|
+
let(:index_url) {"#{es_url}/#{index}"}
|
28
|
+
let(:http_client_options) { {} }
|
29
|
+
let(:http_client) do
|
30
|
+
Manticore::Client.new(http_client_options)
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
before do
|
34
|
+
subject.register
|
35
|
+
subject.multi_receive([])
|
36
|
+
end
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
shared_examples "an indexer" do
|
39
|
+
it "ships events" do
|
40
|
+
subject.multi_receive(events)
|
42
41
|
|
43
|
-
|
42
|
+
http_client.post("#{es_url}/_refresh").call
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
response = http_client.get("#{index_url}/_count?q=*")
|
45
|
+
result = LogStash::Json.load(response.body)
|
46
|
+
cur_count = result["count"]
|
47
|
+
expect(cur_count).to eq(event_count)
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
expect(doc
|
55
|
-
|
49
|
+
response = http_client.get("#{index_url}/_search?q=*&size=1000")
|
50
|
+
result = LogStash::Json.load(response.body)
|
51
|
+
result["hits"]["hits"].each do |doc|
|
52
|
+
if ESHelper.es_version_satisfies?("< 8")
|
53
|
+
expect(doc["_type"]).to eq(type)
|
54
|
+
else
|
55
|
+
expect(doc).not_to include("_type")
|
56
56
|
end
|
57
|
+
expect(doc["_index"]).to eq(index)
|
57
58
|
end
|
58
59
|
end
|
60
|
+
end
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
it_behaves_like("an indexer")
|
62
|
+
it "sets the correct content-encoding header and body is compressed" do
|
63
|
+
expect(subject.client.pool.adapter.client).to receive(:send).
|
64
|
+
with(anything, anything, {:headers=>{"Content-Encoding"=>"gzip", "Content-Type"=>"application/json"}, :body => a_valid_gzip_encoded_string}).
|
65
|
+
and_call_original
|
66
|
+
subject.multi_receive(events)
|
68
67
|
end
|
68
|
+
|
69
|
+
it_behaves_like("an indexer")
|
69
70
|
end
|