logstash-output-elasticsearch 5.3.5-java → 5.4.0-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5166d95227401f888a2f3ed3606b0c6e42ee30e
4
- data.tar.gz: 5e17a2dd88624f58bc2e3ba78c7f6d53a42b8e94
3
+ metadata.gz: d4c13cc28976cdad32da8417651ef69ad5695333
4
+ data.tar.gz: 145160a4c63cd206a3d869f044b434a169fe5f43
5
5
  SHA512:
6
- metadata.gz: 0d93a1c0a567986a601429c7d30acbb0471c4f8edab1e7a0cc67eacd1eb3e6e402e8ed6ea63332ed16598447ca40820439726e047aeaa71c69c24012d9bcfffb
7
- data.tar.gz: 09551c3614f59c4eba620fe42ff21078f00c3544001585deaa2fee95d2792b75662b3e7bb31b9bedaa012458c53752623aaf2efc8a1974578e388abb6c9e65c9
6
+ metadata.gz: 0256fab32a89ddafee3dbe18023c4d1bc415d32d1aab8bd30e11bac473760bc6c5fa9beab01b058ebee9e14ec4163f9ef1882527e5a5205592add85b63007b25
7
+ data.tar.gz: 297813ad0a6c5103c04fc9cd5085829bb8982bb56be9c15526561fc361d5094f2dbecbde3d5c9dd93b5d4fc1513c1be51dd6ddf8d71c73c15026e802c2411d46
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 5.4.0
2
+ - Perform healthcheck against hosts right after startup / sniffing
3
+
1
4
  ## 5.3.5
2
5
  - Docs: Remove mention of using the elasticsearch_java output plugin because it is no longer supported
3
6
 
@@ -102,6 +102,11 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
102
102
  # not also set this field. That will raise an error at startup
103
103
  config :path, :validate => :string
104
104
 
105
+ # Pass a set of key value pairs as the URL query string. This query string is added
106
+ # to every host listed in the 'hosts' configuration. If the 'hosts' list contains
107
+ # urls that already have query strings, the one specified here will be appended.
108
+ config :parameters, :validate => :hash
109
+
105
110
  # Enable SSL/TLS secured communication to Elasticsearch cluster. Leaving this unspecified will use whatever scheme
106
111
  # is specified in the URLs listed in 'hosts'. If no explicit protocol is specified plain HTTP will be used.
107
112
  # If SSL is explicitly disabled here the plugin will refuse to start if an HTTPS URL is given in 'hosts'
@@ -79,8 +79,8 @@ module LogStash; module Outputs; class ElasticSearch
79
79
  mod.config :hosts, :validate => :array, :default => ["127.0.0.1"]
80
80
 
81
81
  # This plugin uses the bulk index API for improved indexing performance.
82
- # This setting defines the maximum sized bulk request Logstash will make
83
- # You you may want to increase this to be in line with your pipeline's batch size.
82
+ # This setting defines the maximum sized bulk request Logstash will make.
83
+ # You may want to increase this to be in line with your pipeline's batch size.
84
84
  # If you specify a number larger than the batch size of your pipeline it will have no effect,
85
85
  # save for the case where a filter increases the size of an inflight batch by outputting
86
86
  # events.
@@ -131,7 +131,7 @@ module LogStash; module Outputs; class ElasticSearch;
131
131
  timeout = options[:timeout] || 0
132
132
 
133
133
  host_ssl_opt = client_settings[:ssl].nil? ? nil : client_settings[:ssl][:enabled]
134
- urls = hosts.map {|host| host_to_url(host, host_ssl_opt, client_settings[:path])}
134
+ urls = hosts.map {|host| host_to_url(host, host_ssl_opt, client_settings[:path], client_settings[:parameters])}
135
135
 
136
136
  adapter_options = {
137
137
  :socket_timeout => timeout,
@@ -186,7 +186,7 @@ module LogStash; module Outputs; class ElasticSearch;
186
186
  HOSTNAME_PORT_REGEX=/\A(?<hostname>([A-Za-z0-9\.\-]+)|\[[0-9A-Fa-f\:]+\])(:(?<port>\d+))?\Z/
187
187
  URL_REGEX=/\A#{URI::regexp(['http', 'https'])}\z/
188
188
  # Parse a configuration host to a normalized URL
189
- def host_to_url(host, ssl=nil, path=nil)
189
+ def host_to_url(host, ssl=nil, path=nil, parameters=nil)
190
190
  explicit_scheme = case ssl
191
191
  when true
192
192
  "https"
@@ -233,6 +233,15 @@ module LogStash; module Outputs; class ElasticSearch;
233
233
  url.path = path # The URI library cannot stringify if it holds a nil
234
234
  end
235
235
 
236
+ if parameters
237
+ query_string = parameters.map { |k,v| "#{k}=#{v}" }.join("&")
238
+ if query = url.query
239
+ url.query = "#{query}&#{query_string}"
240
+ else
241
+ url.query = query_string
242
+ end
243
+ end
244
+
236
245
  if url.password || url.user
237
246
  raise LogStash::ConfigurationError, "We do not support setting the user password in the URL directly as " +
238
247
  "this may be logged to disk thus leaking credentials. Use the 'user' and 'password' options respectively"
@@ -31,7 +31,8 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
31
31
  def perform_request(url, method, path, params={}, body=nil)
32
32
  params = (params || {}).merge @request_options
33
33
  params[:body] = body if body
34
- url_and_path = (url + path).to_s # Convert URI object to string
34
+ # Convert URI object to string
35
+ url_and_path = path ? (url + path).to_s : url.to_s
35
36
 
36
37
  resp = @manticore.send(method.downcase, url_and_path, params)
37
38
 
@@ -62,8 +62,9 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
62
62
  # Holds metadata about all URLs
63
63
  @url_info = {}
64
64
  @stopping = false
65
-
65
+
66
66
  update_urls(initial_urls)
67
+
67
68
  start_resurrectionist
68
69
  start_sniffer if @sniffing
69
70
  end
@@ -96,7 +97,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
96
97
  end
97
98
 
98
99
  def alive_urls_count
99
- @state_mutex.synchronize { @url_info.values.select {|v| !v[:dead] }.count }
100
+ @state_mutex.synchronize { @url_info.values.select {|v| !v[:state] == :alive }.count }
100
101
  end
101
102
 
102
103
  def url_info
@@ -186,24 +187,24 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
186
187
  def start_resurrectionist
187
188
  @resurrectionist = Thread.new do
188
189
  until_stopped("resurrection", @resurrect_delay) do
189
- resurrect_dead!
190
+ healthcheck!
190
191
  end
191
192
  end
192
193
  end
193
194
 
194
- def resurrect_dead!
195
+ def healthcheck!
195
196
  # Try to keep locking granularity low such that we don't affect IO...
196
- @state_mutex.synchronize { @url_info.select {|url,meta| meta[:dead] } }.each do |url,meta|
197
+ @state_mutex.synchronize { @url_info.select {|url,meta| meta[:state] != :alive } }.each do |url,meta|
197
198
  safe_url = ::LogStash::Outputs::ElasticSearch::SafeURL.without_credentials(url)
198
199
  begin
199
200
  logger.info("Running health check to see if an Elasticsearch connection is working",
200
201
  url: safe_url, healthcheck_path: @healthcheck_path)
201
- perform_request_to_url(url, "HEAD", @healthcheck_path)
202
+ response = perform_request_to_url(url, "HEAD", @healthcheck_path)
202
203
  # If no exception was raised it must have succeeded!
203
204
  logger.warn("Restored connection to ES instance", :url => safe_url)
204
- @state_mutex.synchronize { meta[:dead] = false }
205
- rescue HostUnreachableError => e
206
- logger.debug("Attempted to resurrect connection to dead ES instance, but got an error.", url: safe_url, error_type: e.class, error: e.message)
205
+ @state_mutex.synchronize { meta[:state] = :alive }
206
+ rescue HostUnreachableError, BadResponseCodeError => e
207
+ logger.warn("Attempted to resurrect connection to dead ES instance, but got an error.", url: safe_url, error_type: e.class, error: e.message)
207
208
  end
208
209
  end
209
210
  end
@@ -280,6 +281,12 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
280
281
  logger.info("Elasticsearch pool URLs updated", :changes => safe_state_changes(state_changes))
281
282
  end
282
283
  end
284
+
285
+ # Run an inline healthcheck anytime URLs are updated
286
+ # This guarantees that during startup / post-startup
287
+ # sniffing we don't have idle periods waiting for the
288
+ # periodic sniffer to allow new hosts to come online
289
+ healthcheck!
283
290
  end
284
291
 
285
292
  def safe_state_changes(state_changes)
@@ -305,7 +312,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
305
312
  def empty_url_meta
306
313
  {
307
314
  :in_use => 0,
308
- :dead => false
315
+ :state => :unknown
309
316
  }
310
317
  end
311
318
 
@@ -340,7 +347,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
340
347
  safe_url = ::LogStash::Outputs::ElasticSearch::SafeURL.without_credentials(url)
341
348
  logger.warn("Marking url as dead.", :reason => error.message, :url => safe_url,
342
349
  :error_message => error.message, :error_class => error.class.name)
343
- meta[:dead] = true
350
+ meta[:state] = :dead
344
351
  meta[:last_error] = error
345
352
  meta[:last_errored_at] = Time.now
346
353
  end
@@ -361,7 +368,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
361
368
  lowest_value_seen = nil
362
369
  @url_info.each do |url,meta|
363
370
  meta_in_use = meta[:in_use]
364
- next if meta[:dead]
371
+ next if meta[:state] == :dead
365
372
 
366
373
  if lowest_value_seen.nil? || meta_in_use < lowest_value_seen
367
374
  lowest_value_seen = meta_in_use
@@ -24,6 +24,10 @@ module LogStash; module Outputs; class ElasticSearch;
24
24
  client_settings[:path] = "/#{params["path"]}/".gsub(/\/+/, "/") # Normalize slashes
25
25
  end
26
26
 
27
+ if params["parameters"]
28
+ client_settings[:parameters] = params["parameters"]
29
+ end
30
+
27
31
  logger.debug? && logger.debug("Normalizing http path", :path => params["path"], :normalized => client_settings[:path])
28
32
 
29
33
  client_settings.merge! setup_ssl(logger, params)
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-output-elasticsearch'
4
- s.version = '5.3.5'
4
+ s.version = '5.4.0'
5
5
  s.licenses = ['apache-2.0']
6
6
  s.summary = "Logstash Output to Elasticsearch"
7
7
  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"
@@ -9,6 +9,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
9
9
  let(:options) { {:resurrect_delay => 2} } # Shorten the delay a bit to speed up tests
10
10
 
11
11
  subject { described_class.new(logger, adapter, initial_urls, options) }
12
+
13
+ before do
14
+ allow(adapter).to receive(:perform_request).with(anything, 'HEAD', subject.healthcheck_path, {}, nil)
15
+ end
12
16
 
13
17
  describe "initialization" do
14
18
  it "should be successful" do
@@ -22,7 +26,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
22
26
  end
23
27
 
24
28
  it "should attempt to resurrect connections after the ressurrect delay" do
25
- expect(subject).to receive(:resurrect_dead!).once
29
+ expect(subject).to receive(:healthcheck!).once
26
30
  sleep(subject.resurrect_delay + 1)
27
31
  end
28
32
  end
@@ -148,9 +152,9 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
148
152
  subject.return_connection(u)
149
153
  subject.mark_dead(u, Exception.new)
150
154
 
151
- expect(subject.url_meta(u)[:dead]).to eql(true)
155
+ expect(subject.url_meta(u)[:state]).to eql(:dead)
152
156
  sleep subject.resurrect_delay + 1
153
- expect(subject.url_meta(u)[:dead]).to eql(false)
157
+ expect(subject.url_meta(u)[:state]).to eql(:alive)
154
158
  end
155
159
  end
156
160
  end
@@ -1,6 +1,7 @@
1
1
  require_relative "../../../spec/es_spec_helper"
2
2
  require 'stud/temporary'
3
3
  require "logstash/outputs/elasticsearch"
4
+ require 'manticore/client'
4
5
 
5
6
  describe "Proxy option" do
6
7
  let(:settings) {
@@ -14,7 +15,7 @@ describe "Proxy option" do
14
15
  }
15
16
 
16
17
  before do
17
- allow(::Manticore::Client).to receive(:new).with(any_args)
18
+ allow(::Manticore::Client).to receive(:new).with(any_args).and_call_original
18
19
  end
19
20
 
20
21
  describe "valid configs" do
@@ -128,6 +128,7 @@ describe "outputs/elasticsearch" do
128
128
  end
129
129
  end
130
130
  end
131
+
131
132
  describe "without a port specified" do
132
133
  it "should properly set the default port (9200) on the HTTP client" do
133
134
  expect(manticore_url.port).to eql(9200)
@@ -285,7 +286,7 @@ describe "outputs/elasticsearch" do
285
286
  subject(:eso) { LogStash::Outputs::ElasticSearch.new("validate_after_inactivity" => validate_after_inactivity) }
286
287
 
287
288
  before do
288
- allow(::Manticore::Client).to receive(:new).with(any_args)
289
+ allow(::Manticore::Client).to receive(:new).with(any_args).and_call_original
289
290
  subject.register
290
291
  end
291
292
 
@@ -295,4 +296,91 @@ describe "outputs/elasticsearch" do
295
296
  end
296
297
  end
297
298
  end
299
+
300
+ describe "custom parameters" do
301
+
302
+ let(:eso) {LogStash::Outputs::ElasticSearch.new(options)}
303
+
304
+ let(:manticore_urls) { eso.client.pool.urls }
305
+ let(:manticore_url) { manticore_urls.first }
306
+
307
+ let(:custom_parameters_hash) { { "id" => 1, "name" => "logstash" } }
308
+ let(:custom_parameters_query) { custom_parameters_hash.map {|k,v| "#{k}=#{v}" }.join("&") }
309
+
310
+ before(:each) do
311
+ eso.register
312
+ end
313
+
314
+ after(:each) do
315
+ eso.close rescue nil
316
+ end
317
+
318
+ context "using non-url hosts" do
319
+
320
+ let(:options) {
321
+ {
322
+ "index" => "my-index",
323
+ "hosts" => ["localhost:9202"],
324
+ "path" => "some-path",
325
+ "parameters" => custom_parameters_hash
326
+ }
327
+ }
328
+
329
+ it "creates a URI with the added parameters" do
330
+ expect(eso.parameters).to eql(custom_parameters_hash)
331
+ end
332
+
333
+ it "sets the query string on the HTTP client" do
334
+ expect(manticore_url.query).to eql(custom_parameters_query)
335
+ end
336
+ end
337
+
338
+ context "using url hosts" do
339
+
340
+ context "with embedded query parameters" do
341
+ let(:options) {
342
+ { "hosts" => ["http://localhost:9202/path?#{custom_parameters_query}"] }
343
+ }
344
+
345
+ it "sets the query string on the HTTP client" do
346
+ expect(manticore_url.query).to eql(custom_parameters_query)
347
+ end
348
+ end
349
+
350
+ context "with explicity query parameters" do
351
+ let(:options) {
352
+ {
353
+ "hosts" => ["http://localhost:9202/path"],
354
+ "parameters" => custom_parameters_hash
355
+ }
356
+ }
357
+
358
+ it "sets the query string on the HTTP client" do
359
+ expect(manticore_url.query).to eql(custom_parameters_query)
360
+ end
361
+ end
362
+
363
+ context "with explicity query parameters and existing url parameters" do
364
+ let(:existing_query_string) { "existing=param" }
365
+ let(:options) {
366
+ {
367
+ "hosts" => ["http://localhost:9202/path?#{existing_query_string}"],
368
+ "parameters" => custom_parameters_hash
369
+ }
370
+ }
371
+
372
+ it "keeps the existing query string" do
373
+ expect(manticore_url.query).to include(existing_query_string)
374
+ end
375
+
376
+ it "includes the new query string" do
377
+ expect(manticore_url.query).to include(custom_parameters_query)
378
+ end
379
+
380
+ it "appends the new query string to the existing one" do
381
+ expect(manticore_url.query).to eql("#{existing_query_string}&#{custom_parameters_query}")
382
+ end
383
+ end
384
+ end
385
+ end
298
386
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "../../../spec/es_spec_helper"
2
2
  require 'stud/temporary'
3
+ require "logstash/outputs/elasticsearch"
3
4
 
4
5
  describe "SSL option" do
5
6
  context "when using ssl without cert verification" do
@@ -16,7 +17,7 @@ describe "SSL option" do
16
17
  end
17
18
 
18
19
  it "should pass the flag to the ES client" do
19
- expect(::Manticore::Client).to receive(:new) do |args|
20
+ expect(::Manticore::Client).to receive(:new).and_call_original do |args|
20
21
  expect(args[:ssl]).to eq(:enabled => true, :verify => false)
21
22
  end
22
23
  subject.register
@@ -32,6 +33,9 @@ describe "SSL option" do
32
33
 
33
34
  context "when using ssl with client certificates" do
34
35
  let(:keystore_path) { Stud::Temporary.file.path }
36
+ before do
37
+ `openssl req -x509 -batch -nodes -newkey rsa:2048 -keyout lumberjack.key -out #{keystore_path}.pem`
38
+ end
35
39
 
36
40
  after :each do
37
41
  File.delete(keystore_path)
@@ -42,8 +46,7 @@ describe "SSL option" do
42
46
  settings = {
43
47
  "hosts" => "node01",
44
48
  "ssl" => true,
45
- "keystore" => keystore_path,
46
- "keystore_password" => "test"
49
+ "cacert" => keystore_path,
47
50
  }
48
51
  next LogStash::Outputs::ElasticSearch.new(settings)
49
52
  end
@@ -51,7 +54,7 @@ describe "SSL option" do
51
54
  it "should pass the keystore parameters to the ES client" do
52
55
  expect(::Manticore::Client).to receive(:new) do |args|
53
56
  expect(args[:ssl]).to include(:keystore => keystore_path, :keystore_password => "test")
54
- end
57
+ end.and_call_original
55
58
  subject.register
56
59
  end
57
60
 
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: 5.3.5
4
+ version: 5.4.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-22 00:00:00.000000000 Z
11
+ date: 2016-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement