logstash-filter-elasticsearch 3.9.5 → 3.10.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
  SHA256:
3
- metadata.gz: 3c42fd982d06ded966f625f3665120e64edc9b8585a2e5086214a14dd41f6e2a
4
- data.tar.gz: 8411efb4ab1747adf5d824c39d098ccc64660c657916920b1bb4a194e8baf8ef
3
+ metadata.gz: 8e04ff9ca7407b8404764623b42f7ce8e754fe9ceafc6bde7cc064bc13c30723
4
+ data.tar.gz: 3b317df7d5bc1b11c912e8f9d6ec14c2ef260fa975412f2ebbf2baf84da547ba
5
5
  SHA512:
6
- metadata.gz: c7be68bcfcd60db5d7b7c76ae484d382f8efb470abe5c33393330b1a2344b8b01e79f6a02038b2f37032783bd6abc045f44a12c504cac8b2ca1d534d110872a9
7
- data.tar.gz: 57d1ab30bb38a717d3f1e8da8dc9b70fb2b1873bb8e2e482b67a0ae2396a32948842233d586cf8ea29831280ad4af7f284f73e5eef5bf0027a9f2040588cca4b
6
+ metadata.gz: 6dd245e044d1c06882885e776ba64463c1dbfc93d3c80ad03ad4009b6a3b6246e5a166dc11c09cafb58f2b05b3a6e485741aef6a2137edc227081b1e06bf9e3c
7
+ data.tar.gz: b9b211e1bf50bcb18d028e5322e78eaa3e113a034550eaae4ee3550b941e74235b5ed672417759eb35709e46693f7f602b8106ce13beb17bc6937eacbd991514
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 3.10.0
2
+ - Feat: add user-agent header passed to the Elasticsearch HTTP connection [#152](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/152)
3
+
1
4
  ## 3.9.5
2
5
  - Fixed SSL handshake hang indefinitely with proxy setup [#151](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/151)
3
6
 
@@ -16,10 +16,12 @@ module LogStash
16
16
  password = options.fetch(:password, nil)
17
17
  api_key = options.fetch(:api_key, nil)
18
18
  proxy = options.fetch(:proxy, nil)
19
+ user_agent = options[:user_agent]
19
20
 
20
21
  transport_options = {:headers => {}}
21
22
  transport_options[:headers].merge!(setup_basic_auth(user, password))
22
23
  transport_options[:headers].merge!(setup_api_key(api_key))
24
+ transport_options[:headers].merge!({ 'user-agent' => "#{user_agent}" })
23
25
 
24
26
  logger.warn "Supplied proxy setting (proxy => '') has no effect" if @proxy.eql?('')
25
27
  transport_options[:proxy] = proxy.to_s if proxy && !proxy.eql?('')
@@ -20,7 +20,18 @@ if es_client_version >= Gem::Version.new('7.2') && es_client_version < Gem::Vers
20
20
  def apply_headers(request_options, options)
21
21
  headers = (options && options[:headers]) || {}
22
22
  headers[CONTENT_TYPE_STR] = find_value(headers, CONTENT_TYPE_REGEX) || DEFAULT_CONTENT_TYPE
23
- headers[USER_AGENT_STR] = find_value(headers, USER_AGENT_REGEX) || user_agent_header
23
+
24
+ # this code is necessary to grab the correct user-agent header
25
+ # when this method is invoked with apply_headers(@request_options, options)
26
+ # from https://github.com/elastic/elasticsearch-ruby/blob/v7.14.0/elasticsearch-transport/lib/elasticsearch/transport/transport/http/manticore.rb#L113-L114
27
+ transport_user_agent = nil
28
+ if (options && options[:transport_options] && options[:transport_options][:headers])
29
+ transport_headers = {}
30
+ transport_headers = options[:transport_options][:headers]
31
+ transport_user_agent = find_value(transport_headers, USER_AGENT_REGEX)
32
+ end
33
+
34
+ headers[USER_AGENT_STR] = transport_user_agent || find_value(headers, USER_AGENT_REGEX) || user_agent_header
24
35
  headers[ACCEPT_ENCODING] = GZIP if use_compression?
25
36
  (request_options[:headers] ||= {}).merge!(headers) # this line was changed
26
37
  end
@@ -176,6 +176,19 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
176
176
  end
177
177
  end # def filter
178
178
 
179
+ # public only to be reuse in testing
180
+ def prepare_user_agent
181
+ os_name = java.lang.System.getProperty('os.name')
182
+ os_version = java.lang.System.getProperty('os.version')
183
+ os_arch = java.lang.System.getProperty('os.arch')
184
+ jvm_vendor = java.lang.System.getProperty('java.vendor')
185
+ jvm_version = java.lang.System.getProperty('java.version')
186
+
187
+ plugin_version = Gem.loaded_specs['logstash-filter-elasticsearch'].version
188
+ # example: logstash/7.14.1 (OS=Linux-5.4.0-84-generic-amd64; JVM=AdoptOpenJDK-11.0.11) logstash-output-elasticsearch/11.0.1
189
+ "logstash/#{LOGSTASH_VERSION} (OS=#{os_name}-#{os_version}-#{os_arch}; JVM=#{jvm_vendor}-#{jvm_version}) logstash-#{@plugin_type}-#{config_name}/#{plugin_version}"
190
+ end
191
+
179
192
  private
180
193
 
181
194
  def client_options
@@ -192,7 +205,11 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
192
205
  def new_client
193
206
  # NOTE: could pass cloud-id/cloud-auth to client but than we would need to be stricter on ES version requirement
194
207
  # and also LS parsing might differ from ES client's parsing so for consistency we do not pass cloud options ...
195
- LogStash::Filters::ElasticsearchClient.new(@logger, @hosts, client_options)
208
+ opts = client_options
209
+
210
+ opts[:user_agent] = prepare_user_agent
211
+
212
+ LogStash::Filters::ElasticsearchClient.new(@logger, @hosts, opts)
196
213
  end
197
214
 
198
215
  def get_client
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-filter-elasticsearch'
4
- s.version = '3.9.5'
4
+ s.version = '3.10.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Copies fields from previous log events in Elasticsearch to current events "
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"
@@ -23,6 +23,8 @@ Gem::Specification.new do |s|
23
23
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
24
24
  s.add_runtime_dependency 'elasticsearch', ">= 5.0.5" # LS >= 6.7 and < 7.14 all used version 5.0.5
25
25
  s.add_runtime_dependency 'manticore', ">= 0.7.1"
26
+ s.add_development_dependency 'cabin', ['~> 0.6']
27
+ s.add_development_dependency 'webrick'
26
28
 
27
29
  s.add_development_dependency 'logstash-devutils'
28
30
  end
@@ -3,6 +3,9 @@ require "logstash/devutils/rspec/spec_helper"
3
3
  require "logstash/plugin"
4
4
  require "logstash/filters/elasticsearch"
5
5
  require "logstash/json"
6
+ require "cabin"
7
+ require "webrick"
8
+ require "uri"
6
9
 
7
10
  describe LogStash::Filters::Elasticsearch do
8
11
 
@@ -291,6 +294,112 @@ describe LogStash::Filters::Elasticsearch do
291
294
  end
292
295
  end
293
296
 
297
+ class StoppableServer
298
+
299
+ attr_reader :port
300
+
301
+ def initialize()
302
+ queue = Queue.new
303
+ @first_req_waiter = java.util.concurrent.CountDownLatch.new(1)
304
+ @first_request = nil
305
+
306
+ @t = java.lang.Thread.new(
307
+ proc do
308
+ begin
309
+ @server = WEBrick::HTTPServer.new :Port => 0, :DocumentRoot => ".",
310
+ :Logger => Cabin::Channel.get, # silence WEBrick logging
311
+ :StartCallback => Proc.new {
312
+ queue.push("started")
313
+ }
314
+ @port = @server.config[:Port]
315
+ @server.mount_proc '/' do |req, res|
316
+ res.body = '''
317
+ {
318
+ "name": "ce7ccfb438e8",
319
+ "cluster_name": "docker-cluster",
320
+ "cluster_uuid": "DyR1hN03QvuCWXRy3jtb0g",
321
+ "version": {
322
+ "number": "7.13.1",
323
+ "build_flavor": "default",
324
+ "build_type": "docker",
325
+ "build_hash": "9a7758028e4ea59bcab41c12004603c5a7dd84a9",
326
+ "build_date": "2021-05-28T17:40:59.346932922Z",
327
+ "build_snapshot": false,
328
+ "lucene_version": "8.8.2",
329
+ "minimum_wire_compatibility_version": "6.8.0",
330
+ "minimum_index_compatibility_version": "6.0.0-beta1"
331
+ },
332
+ "tagline": "You Know, for Search"
333
+ }
334
+ '''
335
+ res.status = 200
336
+ res['Content-Type'] = 'application/json'
337
+ @first_request = req
338
+ @first_req_waiter.countDown()
339
+ end
340
+
341
+ @server.start
342
+ rescue => e
343
+ puts "Error in webserver thread #{e}"
344
+ # ignore
345
+ end
346
+ end
347
+ )
348
+ @t.daemon = true
349
+ @t.start
350
+ queue.pop # blocks until the server is up
351
+ end
352
+
353
+ def stop
354
+ @server.shutdown
355
+ end
356
+
357
+ def wait_receive_request
358
+ @first_req_waiter.await(2, java.util.concurrent.TimeUnit::SECONDS)
359
+ @first_request
360
+ end
361
+ end
362
+
363
+ describe "user-agent header" do
364
+ let!(:webserver) { StoppableServer.new } # webserver must be started before the call, so no lazy "let"
365
+
366
+ after :each do
367
+ webserver.stop
368
+ end
369
+
370
+ it "server should be started" do
371
+ require 'net/http'
372
+ response = nil
373
+ Net::HTTP.start('localhost', webserver.port) {|http|
374
+ response = http.request_get('/')
375
+ }
376
+ expect(response.code.to_i).to eq(200)
377
+ end
378
+
379
+ context "used by plugin" do
380
+ let(:config) do
381
+ {
382
+ "hosts" => ["localhost:#{webserver.port}"],
383
+ "query" => "response: 404",
384
+ "fields" => { "response" => "code" },
385
+ "docinfo_fields" => { "_index" => "es_index" },
386
+ "aggregation_fields" => { "bytes_avg" => "bytes_avg_ls_field" }
387
+ }
388
+ end
389
+ let(:plugin) { described_class.new(config) }
390
+ let(:event) { LogStash::Event.new({}) }
391
+
392
+ it "client should sent the expect user-agent" do
393
+ plugin.register
394
+
395
+ request = webserver.wait_receive_request
396
+
397
+ expect(request.header['user-agent'].size).to eq(1)
398
+ expect(request.header['user-agent'][0]).to match(/logstash\/\d*\.\d*\.\d* \(OS=.*; JVM=.*\) logstash-filter-elasticsearch\/\d*\.\d*\.\d*/)
399
+ end
400
+ end
401
+ end
402
+
294
403
  describe "client" do
295
404
  let(:config) do
296
405
  {
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.9.5
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-20 00:00:00.000000000 Z
11
+ date: 2021-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -58,6 +58,34 @@ dependencies:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: 0.7.1
61
+ - !ruby/object:Gem::Dependency
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '0.6'
67
+ name: cabin
68
+ prerelease: false
69
+ type: :development
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.6'
75
+ - !ruby/object:Gem::Dependency
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ name: webrick
82
+ prerelease: false
83
+ type: :development
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
61
89
  - !ruby/object:Gem::Dependency
62
90
  requirement: !ruby/object:Gem::Requirement
63
91
  requirements: