logstash-output-elasticsearch 5.3.5-java → 5.4.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
  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