logstash-filter-elasticsearch 3.1.6 → 3.2.0

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: 1d027cbce1e8a66c1fd88d31d60d7a9b4d3389ae
4
- data.tar.gz: 18c348a0892415779a6b476c2699f5a15a1dd42e
3
+ metadata.gz: 364c2ed330ed87b3914f8a7644460ed48522b5db
4
+ data.tar.gz: a77e91ea3a1071c78742fc9ce972f0d5ee9791f0
5
5
  SHA512:
6
- metadata.gz: 9b5dec688ea1fe123041d1da7dfa6109de38df87444edccc1b296cbb59b012561a8659eaa47b6e85c97f57e07ed8346a3eabf4930709671768988306514e6172
7
- data.tar.gz: 29ef969be8fe60df16eb381d632791dc25a2ca3c3a5c676d290a617a300a2f3a6f30545c75b82abdc311f9c03358377afc53ff3eb9f8ed56193b924a7cd297a5
6
+ metadata.gz: c7df570123dc569cdffd64f310b154f735efe97306b93bd7c76ce8cc43a92f67b9558b16d27d99f653e454473dad2ddf3e95703ea16229625b043d8b5e723a4d
7
+ data.tar.gz: f64a717402ab19107450d6d800d3f5abb0ee32075b9c9afccdb61d8ba891b2f52f25a23c69117ecc0f816c42b42b8f9caa8e7e59b7fd44df5d1930cb58e1d04d
@@ -1,3 +1,9 @@
1
+ ## 3.2.0
2
+ - `index` setting now supports field formatting, such as `index => "%{myindex}"` (Boris Gorbylev)
3
+
4
+ ## 3.1.8
5
+ - Fix a thread safety issue when using this filter with multiple workers on heavy load, we now create an elasticsearch client for every LogStash worker. #76
6
+
1
7
  ## 3.1.6
2
8
  - Fix some documentation issues
3
9
 
@@ -163,7 +163,8 @@ List of elasticsearch hosts to use for querying.
163
163
  * Value type is <<string,string>>
164
164
  * Default value is `""`
165
165
 
166
- Comma-delimited list of index names to search; use `_all` or empty string to perform the operation on all indices
166
+ Comma-delimited list of index names to search; use `_all` or empty string to perform the operation on all indices.
167
+ Field substitution (e.g. `index-name-%{date_field}`) is available
167
168
 
168
169
  [id="plugins-{type}s-{plugin}-password"]
169
170
  ===== `password`
@@ -3,6 +3,7 @@ require "logstash/filters/base"
3
3
  require "logstash/namespace"
4
4
  require_relative "elasticsearch/client"
5
5
  require "logstash/json"
6
+ java_import "java.util.concurrent.ConcurrentHashMap"
6
7
 
7
8
  # .Compatibility Note
8
9
  # [NOTE]
@@ -87,7 +88,8 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
87
88
  # List of elasticsearch hosts to use for querying.
88
89
  config :hosts, :validate => :array, :default => [ "localhost:9200" ]
89
90
 
90
- # Comma-delimited list of index names to search; use `_all` or empty string to perform the operation on all indices
91
+ # Comma-delimited list of index names to search; use `_all` or empty string to perform the operation on all indices.
92
+ # Field substitution (e.g. `index-name-%{date_field}`) is available
91
93
  config :index, :validate => :string, :default => ""
92
94
 
93
95
  # Elasticsearch query string. Read the Elasticsearch query string documentation.
@@ -125,14 +127,10 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
125
127
  # Tags the event on failure to look up geo information. This can be used in later analysis.
126
128
  config :tag_on_failure, :validate => :array, :default => ["_elasticsearch_lookup_failure"]
127
129
 
130
+ attr_reader :clients_pool
131
+
128
132
  def register
129
- options = {
130
- :ssl => @ssl,
131
- :hosts => @hosts,
132
- :ca_file => @ca_file,
133
- :logger => @logger
134
- }
135
- @client = LogStash::Filters::ElasticsearchClient.new(@user, @password, options)
133
+ @clients_pool = java.util.concurrent.ConcurrentHashMap.new
136
134
 
137
135
  #Load query if it exists
138
136
  if @query_template
@@ -148,7 +146,7 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
148
146
  def filter(event)
149
147
  begin
150
148
 
151
- params = {:index => @index }
149
+ params = {:index => event.sprintf(@index) }
152
150
 
153
151
  if @query_dsl
154
152
  query = LogStash::Json.load(event.sprintf(@query_dsl))
@@ -162,7 +160,7 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
162
160
 
163
161
  @logger.debug("Querying elasticsearch for lookup", :params => params)
164
162
 
165
- results = @client.search(params)
163
+ results = get_client.search(params)
166
164
  @fields.each do |old_key, new_key|
167
165
  if !results['hits']['hits'].empty?
168
166
  set = []
@@ -178,4 +176,22 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
178
176
  end
179
177
  filter_matched(event)
180
178
  end # def filter
179
+
180
+ private
181
+ def client_options
182
+ {
183
+ :ssl => @ssl,
184
+ :hosts => @hosts,
185
+ :ca_file => @ca_file,
186
+ :logger => @logger
187
+ }
188
+ end
189
+
190
+ def new_client
191
+ LogStash::Filters::ElasticsearchClient.new(@user, @password, client_options)
192
+ end
193
+
194
+ def get_client
195
+ @clients_pool.computeIfAbsent(Thread.current, lambda { |x| new_client })
196
+ end
181
197
  end #class LogStash::Filters::Elasticsearch
@@ -24,7 +24,7 @@ module LogStash
24
24
  # set ca_file even if ssl isn't on, since the host can be an https url
25
25
  transport_options[:ssl] = { ca_file: options[:ca_file] } if options[:ca_file]
26
26
 
27
- @logger.info("New ElasticSearch filter", :hosts => hosts)
27
+ @logger.info("New ElasticSearch filter client", :hosts => hosts)
28
28
  @client = ::Elasticsearch::Client.new(hosts: hosts, transport_options: transport_options)
29
29
  end
30
30
 
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-filter-elasticsearch'
4
- s.version = '3.1.6'
4
+ s.version = '3.2.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Search elasticsearch for a previous log event and copy some fields from it into the current event"
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"
@@ -38,6 +38,25 @@ describe LogStash::Filters::Elasticsearch do
38
38
  plugin.register
39
39
  end
40
40
 
41
+ after(:each) do
42
+ Thread.current[:filter_elasticsearch_client] = nil
43
+ end
44
+
45
+ # Since the Elasticsearch Ruby client is not thread safe
46
+ # and under high load we can get error with the connection pool
47
+ # we have decided to create a new instance per worker thread which
48
+ # will be lazy created on the first call to `#filter`
49
+ #
50
+ # I am adding a simple test case for future changes
51
+ it "uses a different connection object per thread wait" do
52
+ expect(plugin.clients_pool.size).to eq(0)
53
+
54
+ Thread.new { plugin.filter(event) }.join
55
+ Thread.new { plugin.filter(event) }.join
56
+
57
+ expect(plugin.clients_pool.size).to eq(2)
58
+ end
59
+
41
60
  it "should enhance the current event with new data" do
42
61
  plugin.filter(event)
43
62
  expect(event.get("code")).to eq(404)
@@ -122,6 +141,30 @@ describe LogStash::Filters::Elasticsearch do
122
141
 
123
142
  end
124
143
 
144
+ context "testing a simple index substitution" do
145
+ let(:event) {
146
+ LogStash::Event.new(
147
+ {
148
+ "subst_field" => "subst_value"
149
+ }
150
+ )
151
+ }
152
+ let(:config) do
153
+ {
154
+ "index" => "foo_%{subst_field}*",
155
+ "hosts" => ["localhost:9200"],
156
+ "query" => "response: 404",
157
+ "fields" => [["response", "code"]]
158
+ }
159
+ end
160
+
161
+ it "should receive substituted index name" do
162
+ expect(client).to receive(:search).with({:q => "response: 404", :size => 1, :index => "foo_subst_value*", :sort => "@timestamp:desc"})
163
+ plugin.filter(event)
164
+ end
165
+
166
+ end
167
+
125
168
  end
126
169
 
127
170
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.6
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-15 00:00:00.000000000 Z
11
+ date: 2017-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement