logstash-output-elasticsearch 10.8.0-java → 10.8.6-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.
@@ -417,7 +417,9 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
417
417
  # @param noop_required_client [nil]: required `nil` for legacy reasons.
418
418
  # @return [Boolean]
419
419
  def use_event_type?(noop_required_client)
420
- maximum_seen_major_version < 8
420
+ # always set type for ES <= 6
421
+ # for ES 7 only set it if the user defined it
422
+ (maximum_seen_major_version < 7) || (maximum_seen_major_version == 7 && @document_type)
421
423
  end
422
424
 
423
425
  def install_template
@@ -109,27 +109,50 @@ module LogStash; module Outputs; class ElasticSearch;
109
109
  body_stream = StringIO.new
110
110
  if http_compression
111
111
  body_stream.set_encoding "BINARY"
112
- stream_writer = Zlib::GzipWriter.new(body_stream, Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
113
- else
112
+ stream_writer = gzip_writer(body_stream)
113
+ else
114
114
  stream_writer = body_stream
115
115
  end
116
116
  bulk_responses = []
117
- bulk_actions.each do |action|
117
+ batch_actions = []
118
+ bulk_actions.each_with_index do |action, index|
118
119
  as_json = action.is_a?(Array) ?
119
120
  action.map {|line| LogStash::Json.dump(line)}.join("\n") :
120
121
  LogStash::Json.dump(action)
121
122
  as_json << "\n"
122
- if (body_stream.size + as_json.bytesize) > TARGET_BULK_BYTES
123
- bulk_responses << bulk_send(body_stream) unless body_stream.size == 0
123
+ if (stream_writer.pos + as_json.bytesize) > TARGET_BULK_BYTES && stream_writer.pos > 0
124
+ stream_writer.flush # ensure writer has sync'd buffers before reporting sizes
125
+ logger.debug("Sending partial bulk request for batch with one or more actions remaining.",
126
+ :action_count => batch_actions.size,
127
+ :payload_size => stream_writer.pos,
128
+ :content_length => body_stream.size,
129
+ :batch_offset => (index + 1 - batch_actions.size))
130
+ bulk_responses << bulk_send(body_stream, batch_actions)
131
+ body_stream.truncate(0) && body_stream.seek(0)
132
+ stream_writer = gzip_writer(body_stream) if http_compression
133
+ batch_actions.clear
124
134
  end
125
135
  stream_writer.write(as_json)
136
+ batch_actions << action
126
137
  end
127
138
  stream_writer.close if http_compression
128
- bulk_responses << bulk_send(body_stream) if body_stream.size > 0
139
+ logger.debug("Sending final bulk request for batch.",
140
+ :action_count => batch_actions.size,
141
+ :payload_size => stream_writer.pos,
142
+ :content_length => body_stream.size,
143
+ :batch_offset => (actions.size - batch_actions.size))
144
+ bulk_responses << bulk_send(body_stream, batch_actions) if body_stream.size > 0
129
145
  body_stream.close if !http_compression
130
146
  join_bulk_responses(bulk_responses)
131
147
  end
132
148
 
149
+ def gzip_writer(io)
150
+ fail(ArgumentError, "Cannot create gzip writer on IO with unread bytes") unless io.eof?
151
+ fail(ArgumentError, "Cannot create gzip writer on non-empty IO") unless io.pos == 0
152
+
153
+ Zlib::GzipWriter.new(io, Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
154
+ end
155
+
133
156
  def join_bulk_responses(bulk_responses)
134
157
  {
135
158
  "errors" => bulk_responses.any? {|r| r["errors"] == true},
@@ -137,25 +160,37 @@ module LogStash; module Outputs; class ElasticSearch;
137
160
  }
138
161
  end
139
162
 
140
- def bulk_send(body_stream)
163
+ def bulk_send(body_stream, batch_actions)
141
164
  params = http_compression ? {:headers => {"Content-Encoding" => "gzip"}} : {}
142
- # Discard the URL
143
165
  response = @pool.post(@bulk_path, params, body_stream.string)
144
- if !body_stream.closed?
145
- body_stream.truncate(0)
146
- body_stream.seek(0)
147
- end
148
166
 
149
167
  @bulk_response_metrics.increment(response.code.to_s)
150
168
 
151
- if response.code != 200
169
+ case response.code
170
+ when 200 # OK
171
+ LogStash::Json.load(response.body)
172
+ when 413 # Payload Too Large
173
+ logger.warn("Bulk request rejected: `413 Payload Too Large`", :action_count => batch_actions.size, :content_length => body_stream.size)
174
+ emulate_batch_error_response(batch_actions, response.code, 'payload_too_large')
175
+ else
152
176
  url = ::LogStash::Util::SafeURI.new(response.final_url)
153
177
  raise ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(
154
178
  response.code, url, body_stream.to_s, response.body
155
179
  )
156
180
  end
181
+ end
157
182
 
158
- LogStash::Json.load(response.body)
183
+ def emulate_batch_error_response(actions, http_code, reason)
184
+ {
185
+ "errors" => true,
186
+ "items" => actions.map do |action|
187
+ action = action.first if action.is_a?(Array)
188
+ request_action, request_parameters = action.first
189
+ {
190
+ request_action => {"status" => http_code, "error" => { "type" => reason }}
191
+ }
192
+ end
193
+ }
159
194
  end
160
195
 
161
196
  def get(path)
@@ -400,6 +435,7 @@ module LogStash; module Outputs; class ElasticSearch;
400
435
 
401
436
  # Build a bulk item for an elasticsearch update action
402
437
  def update_action_builder(args, source)
438
+ args = args.clone()
403
439
  if args[:_script]
404
440
  # Use the event as a hash from your script with variable name defined
405
441
  # by script_var_name (default: "event")
@@ -70,7 +70,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
70
70
  @url_info = {}
71
71
  @stopping = false
72
72
 
73
- @license_checker = options.fetch(:license_checker) { LogStash::PluginMixins::ElasticSearch::NoopLicenseChecker::INSTANCE }
73
+ @license_checker = options[:license_checker] || LogStash::PluginMixins::ElasticSearch::NoopLicenseChecker::INSTANCE
74
74
  end
75
75
 
76
76
  def start
@@ -204,8 +204,16 @@ module LogStash; module PluginMixins; module ElasticSearch
204
204
  return
205
205
  end
206
206
 
207
+ responses = bulk_response["items"]
208
+ if responses.size != actions.size # can not map action -> response reliably
209
+ # an ES bug (on 7.10.2, 7.11.1) where a _bulk request to index X documents would return Y (> X) items
210
+ msg = "Sent #{actions.size} documents but Elasticsearch returned #{responses.size} responses"
211
+ @logger.warn(msg, actions: actions, responses: responses)
212
+ fail("#{msg} (likely a bug with _bulk endpoint)")
213
+ end
214
+
207
215
  actions_to_retry = []
208
- bulk_response["items"].each_with_index do |response,idx|
216
+ responses.each_with_index do |response,idx|
209
217
  action_type, action_props = response.first
210
218
 
211
219
  status = action_props["status"]
@@ -291,7 +299,7 @@ module LogStash; module PluginMixins; module ElasticSearch
291
299
  retry unless @stopping.true?
292
300
  rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
293
301
  @bulk_request_metrics.increment(:failures)
294
- log_hash = {:code => e.response_code, :url => e.url.sanitized.to_s}
302
+ log_hash = {:code => e.response_code, :url => e.url.sanitized.to_s, :content_length => e.request_body.bytesize}
295
303
  log_hash[:body] = e.response_body if @logger.debug? # Generally this is too verbose
296
304
  message = "Encountered a retryable error. Will Retry with exponential backoff "
297
305
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-elasticsearch'
3
- s.version = '10.8.0'
3
+ s.version = '10.8.6'
4
4
 
5
5
  s.licenses = ['apache-2.0']
6
6
  s.summary = "Stores logs in Elasticsearch"
@@ -5,7 +5,7 @@ shared_examples_for 'an ILM enabled Logstash' do
5
5
  context 'with a policy with a maximum number of documents' do
6
6
  let (:policy) { small_max_doc_policy }
7
7
  let (:ilm_policy_name) { "logstash-policy-custom"}
8
- let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
8
+ let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
9
9
 
10
10
  it 'should rollover when the policy max docs is reached' do
11
11
  put_policy(@es, ilm_policy_name, policy)
@@ -54,7 +54,7 @@ shared_examples_for 'an ILM enabled Logstash' do
54
54
  context 'with a policy where the maximum number of documents is not reached' do
55
55
  let (:policy) { large_max_doc_policy }
56
56
  let (:ilm_policy_name) { "logstash-policy-custom-policy"}
57
- let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
57
+ let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
58
58
 
59
59
  it 'should ingest into a single index when max docs is not reached' do
60
60
  put_policy(@es,ilm_policy_name, policy)
@@ -119,7 +119,7 @@ shared_examples_for 'an ILM disabled Logstash' do
119
119
  context 'with an existing policy that will roll over' do
120
120
  let (:policy) { small_max_doc_policy }
121
121
  let (:ilm_policy_name) { "logstash-policy-3_docs"}
122
- let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
122
+ let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
123
123
 
124
124
  it 'should not roll over indices' do
125
125
  subject.register
@@ -155,7 +155,7 @@ shared_examples_for 'an ILM disabled Logstash' do
155
155
 
156
156
  context 'with a custom template name' do
157
157
  let (:template_name) { "logstash_custom_template_name" }
158
- let (:settings) { super.merge('template_name' => template_name)}
158
+ let (:settings) { super().merge('template_name' => template_name)}
159
159
 
160
160
  it 'should not write the ILM settings into the template' do
161
161
  subject.register
@@ -195,7 +195,7 @@ shared_examples_for 'an Elasticsearch instance that does not support index lifec
195
195
  subject { LogStash::Outputs::ElasticSearch.new(settings) }
196
196
 
197
197
  context 'when ilm is enabled in Logstash' do
198
- let (:settings) { super.merge!({ 'ilm_enabled' => true }) }
198
+ let (:settings) { super().merge!({ 'ilm_enabled' => true }) }
199
199
 
200
200
  it 'should raise a configuration error' do
201
201
  expect do
@@ -210,13 +210,13 @@ shared_examples_for 'an Elasticsearch instance that does not support index lifec
210
210
  end
211
211
 
212
212
  context 'when ilm is disabled in Logstash' do
213
- let (:settings) { super.merge!({ 'ilm_enabled' => false }) }
213
+ let (:settings) { super().merge!({ 'ilm_enabled' => false }) }
214
214
 
215
215
  it_behaves_like 'an ILM disabled Logstash'
216
216
  end
217
217
 
218
218
  context 'when ilm is set to auto in Logstash' do
219
- let (:settings) { super.merge!({ 'ilm_enabled' => 'auto' }) }
219
+ let (:settings) { super().merge!({ 'ilm_enabled' => 'auto' }) }
220
220
 
221
221
  it_behaves_like 'an ILM disabled Logstash'
222
222
  end
@@ -286,7 +286,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
286
286
 
287
287
  context 'when using the default policy' do
288
288
  context 'with a custom pattern' do
289
- let (:settings) { super.merge("ilm_pattern" => "000001")}
289
+ let (:settings) { super().merge("ilm_pattern" => "000001")}
290
290
  it 'should create a rollover alias' do
291
291
  expect(@es.indices.exists_alias(name: "logstash")).to be_falsey
292
292
  subject.register
@@ -346,7 +346,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
346
346
 
347
347
  context 'when not using the default policy' do
348
348
  let (:ilm_policy_name) {"logstash-policy-small"}
349
- let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
349
+ let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
350
350
  let (:policy) { small_max_doc_policy }
351
351
 
352
352
  before do
@@ -363,7 +363,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
363
363
 
364
364
  context 'when using a time based policy' do
365
365
  let (:ilm_policy_name) {"logstash-policy-time"}
366
- let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
366
+ let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
367
367
  let (:policy) { max_age_policy("1d") }
368
368
 
369
369
  before do
@@ -409,7 +409,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
409
409
  let (:template) { "spec/fixtures/template-with-policy-es6x.json" }
410
410
  end
411
411
 
412
- let (:settings) { super.merge("template" => template,
412
+ let (:settings) { super().merge("template" => template,
413
413
  "index" => "overwrite-4")}
414
414
 
415
415
  it 'should not overwrite the index patterns' do
@@ -426,7 +426,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
426
426
  let (:ilm_rollover_alias) { "logstash_the_cat_in_the_hat" }
427
427
  let (:index) { ilm_rollover_alias }
428
428
  let(:expected_index) { index }
429
- let (:settings) { super.merge("ilm_policy" => ilm_policy_name,
429
+ let (:settings) { super().merge("ilm_policy" => ilm_policy_name,
430
430
  "template" => template,
431
431
  "ilm_rollover_alias" => ilm_rollover_alias)}
432
432
 
@@ -480,7 +480,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
480
480
 
481
481
  context 'with a different template_name' do
482
482
  let (:template_name) { "logstash_custom_template_name" }
483
- let (:settings) { super.merge('template_name' => template_name)}
483
+ let (:settings) { super().merge('template_name' => template_name)}
484
484
 
485
485
  it_behaves_like 'an ILM enabled Logstash'
486
486
 
@@ -514,7 +514,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
514
514
  end
515
515
 
516
516
  context 'when ilm_enabled is the default' do
517
- let (:settings) { super.tap{|x|x.delete('ilm_enabled')}}
517
+ let (:settings) { super().tap{|x|x.delete('ilm_enabled')}}
518
518
 
519
519
  if ESHelper.es_version_satisfies?(">=7.0")
520
520
  context 'when Elasticsearch is version 7 or above' do
@@ -530,13 +530,13 @@ if ESHelper.es_version_satisfies?(">= 6.6")
530
530
  end
531
531
 
532
532
  context 'with ilm disabled' do
533
- let (:settings) { super.merge('ilm_enabled' => false )}
533
+ let (:settings) { super().merge('ilm_enabled' => false )}
534
534
 
535
535
  it_behaves_like 'an ILM disabled Logstash'
536
536
  end
537
537
 
538
538
  context 'with ilm disabled using a string' do
539
- let (:settings) { super.merge('ilm_enabled' => 'false' )}
539
+ let (:settings) { super().merge('ilm_enabled' => 'false' )}
540
540
 
541
541
  it_behaves_like 'an ILM disabled Logstash'
542
542
  end
@@ -4,9 +4,21 @@ require_relative "../../../spec/es_spec_helper"
4
4
  describe "failures in bulk class expected behavior", :integration => true do
5
5
  let(:template) { '{"template" : "not important, will be updated by :index"}' }
6
6
  let(:event1) { LogStash::Event.new("somevalue" => 100, "@timestamp" => "2014-11-17T20:37:17.223Z", "@metadata" => {"retry_count" => 0}) }
7
- let(:action1) { ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event1]) }
7
+ let(:action1) do
8
+ if ESHelper.es_version_satisfies?(">= 6", "< 7")
9
+ ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event1])
10
+ else
11
+ ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17" }, event1])
12
+ end
13
+ end
8
14
  let(:event2) { LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0] }, "@timestamp" => "2014-11-17T20:37:17.223Z", "@metadata" => {"retry_count" => 0}) }
9
- let(:action2) { ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event2]) }
15
+ let(:action2) do
16
+ if ESHelper.es_version_satisfies?(">= 6", "< 7")
17
+ ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event2])
18
+ else
19
+ ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17" }, event2])
20
+ end
21
+ end
10
22
  let(:invalid_event) { LogStash::Event.new("geoip" => { "location" => "notlatlon" }, "@timestamp" => "2014-11-17T20:37:17.223Z") }
11
23
 
12
24
  def mock_actions_with_response(*resp)
@@ -40,10 +40,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
40
40
 
41
41
  context "when setting bulk_path" do
42
42
  let(:bulk_path) { "/meh" }
43
- let(:options) { super.merge("bulk_path" => bulk_path) }
43
+ let(:options) { super().merge("bulk_path" => bulk_path) }
44
44
 
45
45
  context "when using path" do
46
- let(:options) { super.merge("path" => "/path") }
46
+ let(:options) { super().merge("path" => "/path") }
47
47
  it "ignores the path setting" do
48
48
  expect(described_class).to receive(:create_http_client) do |options|
49
49
  expect(options[:bulk_path]).to eq(bulk_path)
@@ -66,7 +66,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
66
66
 
67
67
  context "when using path" do
68
68
  let(:path) { "/meh" }
69
- let(:options) { super.merge("path" => path) }
69
+ let(:options) { super().merge("path" => path) }
70
70
  it "sets bulk_path to path+_bulk" do
71
71
  expect(described_class).to receive(:create_http_client) do |options|
72
72
  expect(options[:bulk_path]).to eq("#{path}/_bulk")
@@ -88,10 +88,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
88
88
  describe "healthcheck_path" do
89
89
  context "when setting healthcheck_path" do
90
90
  let(:healthcheck_path) { "/meh" }
91
- let(:options) { super.merge("healthcheck_path" => healthcheck_path) }
91
+ let(:options) { super().merge("healthcheck_path" => healthcheck_path) }
92
92
 
93
93
  context "when using path" do
94
- let(:options) { super.merge("path" => "/path") }
94
+ let(:options) { super().merge("path" => "/path") }
95
95
  it "ignores the path setting" do
96
96
  expect(described_class).to receive(:create_http_client) do |options|
97
97
  expect(options[:healthcheck_path]).to eq(healthcheck_path)
@@ -114,7 +114,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
114
114
 
115
115
  context "when using path" do
116
116
  let(:path) { "/meh" }
117
- let(:options) { super.merge("path" => path) }
117
+ let(:options) { super().merge("path" => path) }
118
118
  it "sets healthcheck_path to path" do
119
119
  expect(described_class).to receive(:create_http_client) do |options|
120
120
  expect(options[:healthcheck_path]).to eq(path)
@@ -136,10 +136,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
136
136
  describe "sniffing_path" do
137
137
  context "when setting sniffing_path" do
138
138
  let(:sniffing_path) { "/meh" }
139
- let(:options) { super.merge("sniffing_path" => sniffing_path) }
139
+ let(:options) { super().merge("sniffing_path" => sniffing_path) }
140
140
 
141
141
  context "when using path" do
142
- let(:options) { super.merge("path" => "/path") }
142
+ let(:options) { super().merge("path" => "/path") }
143
143
  it "ignores the path setting" do
144
144
  expect(described_class).to receive(:create_http_client) do |options|
145
145
  expect(options[:sniffing_path]).to eq(sniffing_path)
@@ -162,7 +162,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
162
162
 
163
163
  context "when using path" do
164
164
  let(:path) { "/meh" }
165
- let(:options) { super.merge("path" => path) }
165
+ let(:options) { super().merge("path" => path) }
166
166
  it "sets sniffing_path to path+_nodes/http" do
167
167
  expect(described_class).to receive(:create_http_client) do |options|
168
168
  expect(options[:sniffing_path]).to eq("#{path}/_nodes/http")
@@ -68,7 +68,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
68
68
 
69
69
  context "and setting healthcheck_path" do
70
70
  let(:healthcheck_path) { "/my/health" }
71
- let(:options) { super.merge(:healthcheck_path => healthcheck_path) }
71
+ let(:options) { super().merge(:healthcheck_path => healthcheck_path) }
72
72
  it "performs the healthcheck to the healthcheck_path" do
73
73
  expect(adapter).to receive(:perform_request) do |url, method, req_path, _, _|
74
74
  expect(method).to eq(:head)
@@ -130,7 +130,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
130
130
  end
131
131
 
132
132
  context "when enabled" do
133
- let(:options) { super.merge(:sniffing => true)}
133
+ let(:options) { super().merge(:sniffing => true)}
134
134
 
135
135
  it "should start the sniffer" do
136
136
  expect(subject.sniffer_alive?).to eql(true)
@@ -247,7 +247,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
247
247
  end
248
248
 
249
249
  let(:options) do
250
- super.merge(:license_checker => license_checker)
250
+ super().merge(:license_checker => license_checker)
251
251
  end
252
252
 
253
253
  context 'when LicenseChecker#acceptable_license? returns false' do
@@ -48,7 +48,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
48
48
  describe "ssl" do
49
49
  context "when SSL is true" do
50
50
  let(:ssl) { true }
51
- let(:base_options) { super.merge(:hosts => [http_hostname_port]) }
51
+ let(:base_options) { super().merge(:hosts => [http_hostname_port]) }
52
52
 
53
53
  it "should refuse to handle an http url" do
54
54
  expect {
@@ -59,7 +59,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
59
59
 
60
60
  context "when SSL is false" do
61
61
  let(:ssl) { false }
62
- let(:base_options) { super.merge(:hosts => [https_hostname_port]) }
62
+ let(:base_options) { super().merge(:hosts => [https_hostname_port]) }
63
63
 
64
64
  it "should refuse to handle an https url" do
65
65
  expect {
@@ -69,7 +69,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
69
69
  end
70
70
 
71
71
  describe "ssl is nil" do
72
- let(:base_options) { super.merge(:hosts => [https_hostname_port]) }
72
+ let(:base_options) { super().merge(:hosts => [https_hostname_port]) }
73
73
  it "should handle an ssl url correctly when SSL is nil" do
74
74
  subject
75
75
  expect(subject.host_to_url(https_hostname_port).to_s).to eq(https_hostname_port.to_s + "/")
@@ -79,14 +79,14 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
79
79
 
80
80
  describe "path" do
81
81
  let(:url) { http_hostname_port_path }
82
- let(:base_options) { super.merge(:hosts => [url]) }
82
+ let(:base_options) { super().merge(:hosts => [url]) }
83
83
 
84
84
  it "should allow paths in a url" do
85
85
  expect(subject.host_to_url(url)).to eq(url)
86
86
  end
87
87
 
88
88
  context "with the path option set" do
89
- let(:base_options) { super.merge(:client_settings => {:path => "/otherpath"}) }
89
+ let(:base_options) { super().merge(:client_settings => {:path => "/otherpath"}) }
90
90
 
91
91
  it "should not allow paths in two places" do
92
92
  expect {
@@ -97,7 +97,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
97
97
 
98
98
  context "with a path missing a leading /" do
99
99
  let(:url) { http_hostname_port }
100
- let(:base_options) { super.merge(:client_settings => {:path => "otherpath"}) }
100
+ let(:base_options) { super().merge(:client_settings => {:path => "otherpath"}) }
101
101
 
102
102
 
103
103
  it "should automatically insert a / in front of path overlays" do
@@ -204,7 +204,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
204
204
  end
205
205
 
206
206
  describe "#bulk" do
207
- subject { described_class.new(base_options) }
207
+ subject(:http_client) { described_class.new(base_options) }
208
208
 
209
209
  require "json"
210
210
  let(:message) { "hey" }
@@ -212,42 +212,61 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
212
212
  ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message}],
213
213
  ]}
214
214
 
215
- context "if a message is over TARGET_BULK_BYTES" do
216
- let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
217
- let(:message) { "a" * (target_bulk_bytes + 1) }
215
+ [true,false].each do |http_compression_enabled|
216
+ context "with `http_compression => #{http_compression_enabled}`" do
218
217
 
219
- it "should be handled properly" do
220
- allow(subject).to receive(:join_bulk_responses)
221
- expect(subject).to receive(:bulk_send).once do |data|
222
- expect(data.size).to be > target_bulk_bytes
218
+ let(:base_options) { super().merge(:client_settings => {:http_compression => http_compression_enabled}) }
219
+
220
+ before(:each) do
221
+ if http_compression_enabled
222
+ expect(http_client).to receive(:gzip_writer).at_least(:once).and_call_original
223
+ else
224
+ expect(http_client).to_not receive(:gzip_writer)
225
+ end
223
226
  end
224
- s = subject.send(:bulk, actions)
225
- end
226
- end
227
227
 
228
- context "with two messages" do
229
- let(:message1) { "hey" }
230
- let(:message2) { "you" }
231
- let(:actions) { [
232
- ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message1}],
233
- ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message2}],
234
- ]}
235
- it "executes one bulk_send operation" do
236
- allow(subject).to receive(:join_bulk_responses)
237
- expect(subject).to receive(:bulk_send).once
238
- s = subject.send(:bulk, actions)
239
- end
228
+ context "if a message is over TARGET_BULK_BYTES" do
229
+ let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
230
+ let(:message) { "a" * (target_bulk_bytes + 1) }
231
+
232
+ it "should be handled properly" do
233
+ allow(subject).to receive(:join_bulk_responses)
234
+ expect(subject).to receive(:bulk_send).once do |data|
235
+ if !http_compression_enabled
236
+ expect(data.size).to be > target_bulk_bytes
237
+ else
238
+ expect(Zlib::gunzip(data.string).size).to be > target_bulk_bytes
239
+ end
240
+ end
241
+ s = subject.send(:bulk, actions)
242
+ end
243
+ end
244
+
245
+ context "with two messages" do
246
+ let(:message1) { "hey" }
247
+ let(:message2) { "you" }
248
+ let(:actions) { [
249
+ ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message1}],
250
+ ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message2}],
251
+ ]}
252
+ it "executes one bulk_send operation" do
253
+ allow(subject).to receive(:join_bulk_responses)
254
+ expect(subject).to receive(:bulk_send).once
255
+ s = subject.send(:bulk, actions)
256
+ end
240
257
 
241
- context "if one exceeds TARGET_BULK_BYTES" do
242
- let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
243
- let(:message1) { "a" * (target_bulk_bytes + 1) }
244
- it "executes two bulk_send operations" do
245
- allow(subject).to receive(:join_bulk_responses)
246
- expect(subject).to receive(:bulk_send).twice
247
- s = subject.send(:bulk, actions)
258
+ context "if one exceeds TARGET_BULK_BYTES" do
259
+ let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
260
+ let(:message1) { "a" * (target_bulk_bytes + 1) }
261
+ it "executes two bulk_send operations" do
262
+ allow(subject).to receive(:join_bulk_responses)
263
+ expect(subject).to receive(:bulk_send).twice
264
+ s = subject.send(:bulk, actions)
265
+ end
266
+ end
248
267
  end
249
- end
250
- end
268
+ end
269
+ end
251
270
  end
252
271
 
253
272
  describe "sniffing" do