logstash-output-elasticsearch 6.0.0-java → 6.1.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 +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/logstash/outputs/elasticsearch.rb +5 -1
- data/lib/logstash/outputs/elasticsearch/http_client.rb +1 -0
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +32 -18
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +15 -5
- data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +2 -1
- data/logstash-output-elasticsearch.gemspec +1 -1
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +28 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +31 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8df743661ac7aed2fb52dddaf677ce1705a0612
|
4
|
+
data.tar.gz: 10bcb6b88076eafe00aea65c6d9e01d4d3fd8648
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 605c1958b1b4d22e51132e71932174c86c3d1696b80a7f35e07ec147301072dec9befeb64fae5bd240cff7c38f791fa3ede8bfa8a4781cd705a956d4a6e5b6b4
|
7
|
+
data.tar.gz: 69fae6a096cfa00b41037800d7a09737d0fec46b9722796f746d2aa1074be49147b3d2e8f2ec9ca39fdabf35130a2d603f8f512f771bceb09b1afdc1ffa6d0e8
|
data/CHANGELOG.md
CHANGED
@@ -176,7 +176,11 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
176
176
|
# to service requests. If you have custom firewall rules you may need to change
|
177
177
|
# this
|
178
178
|
config :healthcheck_path, :validate => :string, :default => "/"
|
179
|
-
|
179
|
+
# When a `healthcheck_path` config is provided, this additional flag can be used to
|
180
|
+
# specify whether it is an absolute URI or a relative path.
|
181
|
+
# If this flag is true, `healthcheck_path` is expected to be a fully formed URL
|
182
|
+
# with any basic auth credentials provided in the URL itself.
|
183
|
+
config :absolute_healthcheck_path, :validate => :boolean, :default => false
|
180
184
|
# How frequently, in seconds, to wait between resurrection attempts.
|
181
185
|
# Resurrection is the process by which backend endpoints marked 'down' are checked
|
182
186
|
# to see if they have come back to life
|
@@ -250,6 +250,7 @@ module LogStash; module Outputs; class ElasticSearch;
|
|
250
250
|
:sniffing => sniffing,
|
251
251
|
:sniffer_delay => options[:sniffer_delay],
|
252
252
|
:healthcheck_path => options[:healthcheck_path],
|
253
|
+
:absolute_healthcheck_path => options[:absolute_healthcheck_path],
|
253
254
|
:resurrect_delay => options[:resurrect_delay],
|
254
255
|
:url_normalizer => self.method(:host_to_url)
|
255
256
|
}
|
@@ -46,26 +46,13 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
46
46
|
def perform_request(url, method, path, params={}, body=nil)
|
47
47
|
params = (params || {}).merge @request_options
|
48
48
|
params[:body] = body if body
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# First, we make sure the path is relative so URI.join does
|
53
|
-
# the right thing
|
54
|
-
relative_path = path && path.start_with?("/") ? path[1..-1] : path
|
55
|
-
# Wrap this with a safe URI defensively against careless handling later
|
56
|
-
::LogStash::Util::SafeURI.new(URI.join(url.uri, relative_path))
|
57
|
-
else
|
58
|
-
::LogStash::Util::SafeURI.new(url.uri.clone)
|
59
|
-
end
|
60
|
-
|
61
|
-
# We excise auth info from the URL in case manticore itself tries to stick
|
62
|
-
# sensitive data in a thrown exception or log data
|
63
|
-
if request_uri.user
|
64
|
-
params[:auth] = { :user => request_uri.user, :password => request_uri.password, :eager => true }
|
65
|
-
request_uri.user = nil
|
66
|
-
request_uri.password = nil
|
49
|
+
|
50
|
+
if url.user
|
51
|
+
params[:auth] = { :user => url.user, :password => url.password, :eager => true }
|
67
52
|
end
|
68
53
|
|
54
|
+
request_uri = format_url(url, path)
|
55
|
+
|
69
56
|
resp = @manticore.send(method.downcase, request_uri.to_s, params)
|
70
57
|
|
71
58
|
# Manticore returns lazy responses by default
|
@@ -83,6 +70,33 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
83
70
|
resp
|
84
71
|
end
|
85
72
|
|
73
|
+
def format_url(url, path)
|
74
|
+
|
75
|
+
request_uri = url.uri
|
76
|
+
|
77
|
+
if path
|
78
|
+
# Combine the paths using the minimal # of /s
|
79
|
+
# First, we make sure the path is relative so URI.join does
|
80
|
+
# the right thing
|
81
|
+
relative_path = path && path.start_with?("/") ? path[1..-1] : path
|
82
|
+
# because URI.join obliterates the query parameter, we need to save it
|
83
|
+
# and restore it after this operation
|
84
|
+
query = request_uri.query
|
85
|
+
request_uri = URI.join(request_uri, relative_path)
|
86
|
+
request_uri.query = query
|
87
|
+
else
|
88
|
+
request_uri = request_uri.clone
|
89
|
+
end
|
90
|
+
|
91
|
+
# We excise auth info from the URL in case manticore itself tries to stick
|
92
|
+
# sensitive data in a thrown exception or log data
|
93
|
+
request_uri.user = nil
|
94
|
+
request_uri.password = nil
|
95
|
+
|
96
|
+
# Wrap this with a safe URI defensively against careless handling later
|
97
|
+
::LogStash::Util::SafeURI.new(request_uri)
|
98
|
+
end
|
99
|
+
|
86
100
|
def close
|
87
101
|
@manticore.close
|
88
102
|
end
|
@@ -27,10 +27,13 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
attr_reader :logger, :adapter, :sniffing, :sniffer_delay, :resurrect_delay, :healthcheck_path
|
30
|
+
attr_reader :logger, :adapter, :sniffing, :sniffer_delay, :resurrect_delay, :healthcheck_path, :absolute_healthcheck_path
|
31
|
+
|
32
|
+
ROOT_URI_PATH = '/'.freeze
|
31
33
|
|
32
34
|
DEFAULT_OPTIONS = {
|
33
|
-
:healthcheck_path =>
|
35
|
+
:healthcheck_path => ROOT_URI_PATH,
|
36
|
+
:absolute_healthcheck_path => false,
|
34
37
|
:scheme => 'http',
|
35
38
|
:resurrect_delay => 5,
|
36
39
|
:sniffing => false,
|
@@ -46,6 +49,7 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
46
49
|
@url_normalizer = options[:url_normalizer]
|
47
50
|
DEFAULT_OPTIONS.merge(options).tap do |merged|
|
48
51
|
@healthcheck_path = merged[:healthcheck_path]
|
52
|
+
@absolute_healthcheck_path = merged[:absolute_healthcheck_path]
|
49
53
|
@resurrect_delay = merged[:resurrect_delay]
|
50
54
|
@sniffing = merged[:sniffing]
|
51
55
|
@sniffer_delay = merged[:sniffer_delay]
|
@@ -225,11 +229,17 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
225
229
|
# Try to keep locking granularity low such that we don't affect IO...
|
226
230
|
@state_mutex.synchronize { @url_info.select {|url,meta| meta[:state] != :alive } }.each do |url,meta|
|
227
231
|
begin
|
232
|
+
path = healthcheck_path
|
233
|
+
healthcheck_url = url
|
234
|
+
if @absolute_healthcheck_path
|
235
|
+
healthcheck_url = ::LogStash::Util::SafeURI.new(healthcheck_path)
|
236
|
+
path = ROOT_URI_PATH
|
237
|
+
end
|
228
238
|
logger.info("Running health check to see if an Elasticsearch connection is working",
|
229
|
-
|
230
|
-
response = perform_request_to_url(
|
239
|
+
:healthcheck_url => healthcheck_url, :path => path)
|
240
|
+
response = perform_request_to_url(healthcheck_url, :head, path)
|
231
241
|
# If no exception was raised it must have succeeded!
|
232
|
-
logger.warn("Restored connection to ES instance", :url =>
|
242
|
+
logger.warn("Restored connection to ES instance", :url => healthcheck_url.sanitized)
|
233
243
|
@state_mutex.synchronize { meta[:state] = :alive }
|
234
244
|
rescue HostUnreachableError, BadResponseCodeError => e
|
235
245
|
logger.warn("Attempted to resurrect connection to dead ES instance, but got an error.", url: url.sanitized, error_type: e.class, error: e.message)
|
@@ -12,7 +12,8 @@ module LogStash; module Outputs; class ElasticSearch;
|
|
12
12
|
common_options = {
|
13
13
|
:client_settings => client_settings,
|
14
14
|
:resurrect_delay => params["resurrect_delay"],
|
15
|
-
:healthcheck_path => params["healthcheck_path"]
|
15
|
+
:healthcheck_path => params["healthcheck_path"],
|
16
|
+
:absolute_healthcheck_path => params["absolute_healthcheck_path"]
|
16
17
|
}
|
17
18
|
|
18
19
|
if params["sniffing"]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-output-elasticsearch'
|
4
|
-
s.version = '6.
|
4
|
+
s.version = '6.1.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"
|
@@ -39,6 +39,34 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::ManticoreAdapter do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
describe "format_url" do
|
43
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/") }
|
44
|
+
let(:path) { "_bulk" }
|
45
|
+
subject { described_class.new(double("logger"), {}) }
|
46
|
+
|
47
|
+
it "should add the path argument to the uri's path" do
|
48
|
+
expect(subject.format_url(url, path).path).to eq("/path/_bulk")
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when uri contains query parameters" do
|
52
|
+
let(:query_params) { "query=value&key=value2" }
|
53
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/?#{query_params}") }
|
54
|
+
|
55
|
+
it "should retain query_params after format" do
|
56
|
+
expect(subject.format_url(url, path).query).to eq(query_params)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when uri contains credentials" do
|
61
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://user:pass@localhost:9200") }
|
62
|
+
|
63
|
+
it "should remove credentials after format" do
|
64
|
+
expect(subject.format_url(url, path).user).to be_nil
|
65
|
+
expect(subject.format_url(url, path).password).to be_nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
42
70
|
describe "integration specs", :integration => true do
|
43
71
|
it "should perform correct tests without error" do
|
44
72
|
resp = subject.perform_request(::LogStash::Util::SafeURI.new("http://localhost:9200"), :get, "/")
|
@@ -9,26 +9,25 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
9
9
|
let(:options) { {:resurrect_delay => 2, :url_normalizer => proc {|u| u}} } # Shorten the delay a bit to speed up tests
|
10
10
|
|
11
11
|
subject { described_class.new(logger, adapter, initial_urls, options) }
|
12
|
-
|
12
|
+
|
13
13
|
let(:manticore_double) { double("manticore a") }
|
14
14
|
before do
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
|
18
16
|
response_double = double("manticore response").as_null_object
|
19
17
|
# Allow healtchecks
|
20
18
|
allow(manticore_double).to receive(:head).with(any_args).and_return(response_double)
|
21
19
|
allow(manticore_double).to receive(:get).with(any_args).and_return(response_double)
|
22
|
-
|
20
|
+
allow(manticore_double).to receive(:close)
|
21
|
+
|
23
22
|
allow(::Manticore::Client).to receive(:new).and_return(manticore_double)
|
24
23
|
|
25
24
|
subject.start
|
26
25
|
end
|
27
|
-
|
26
|
+
|
28
27
|
after do
|
29
28
|
subject.close
|
30
29
|
end
|
31
|
-
|
30
|
+
|
32
31
|
describe "initialization" do
|
33
32
|
it "should be successful" do
|
34
33
|
expect { subject }.not_to raise_error
|
@@ -44,6 +43,26 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
44
43
|
expect(subject).to receive(:healthcheck!).once
|
45
44
|
sleep(subject.resurrect_delay + 1)
|
46
45
|
end
|
46
|
+
|
47
|
+
describe "absolute_healthcheck_path" do
|
48
|
+
let(:options) { super.merge(:absolute_healthcheck_path => true, :healthcheck_path => "http://abc:xyz@localhost:9200")}
|
49
|
+
let(:pool) { described_class.new(logger, adapter, initial_urls, options) }
|
50
|
+
|
51
|
+
before do
|
52
|
+
pool.start
|
53
|
+
end
|
54
|
+
|
55
|
+
after do
|
56
|
+
pool.close
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when enabled" do
|
60
|
+
it "should use the healthcheck_path as URL to do a health check" do
|
61
|
+
expect(adapter).to receive(:perform_request).with(::LogStash::Util::SafeURI.new(subject.healthcheck_path), :head, "/", {}, nil)
|
62
|
+
pool.healthcheck!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
47
66
|
end
|
48
67
|
|
49
68
|
describe "the sniffer" do
|
@@ -88,7 +107,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
88
107
|
expect(subject).to have_received(:in_use_connections).twice
|
89
108
|
end
|
90
109
|
end
|
91
|
-
|
110
|
+
|
92
111
|
describe "connection management" do
|
93
112
|
context "with only one URL in the list" do
|
94
113
|
it "should use the only URL in 'with_connection'" do
|
@@ -99,8 +118,11 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
|
|
99
118
|
end
|
100
119
|
|
101
120
|
context "with multiple URLs in the list" do
|
121
|
+
before :each do
|
122
|
+
allow(adapter).to receive(:perform_request).with(anything, :head, subject.healthcheck_path, {}, nil)
|
123
|
+
end
|
102
124
|
let(:initial_urls) { [ ::LogStash::Util::SafeURI.new("http://localhost:9200"), ::LogStash::Util::SafeURI.new("http://localhost:9201"), ::LogStash::Util::SafeURI.new("http://localhost:9202") ] }
|
103
|
-
|
125
|
+
|
104
126
|
it "should minimize the number of connections to a single URL" do
|
105
127
|
connected_urls = []
|
106
128
|
|
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: 6.
|
4
|
+
version: 6.1.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-12-
|
11
|
+
date: 2016-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|