fluent-plugin-elasticsearch 1.2.1 → 1.3.0

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: 129193e2eba365974ee13d84c4cdda02c76f2e78
4
- data.tar.gz: 5f8d50deb55473586b8400fb802cac87faab9370
3
+ metadata.gz: 1e5c36c889794052ff9bab9d9b6e69aa8d937eed
4
+ data.tar.gz: a719c42134c8d53969abe517a47f47a6936d092d
5
5
  SHA512:
6
- metadata.gz: 0680f132de350ab43743328b68b785a663ced2bafadc010d6f16c185d852b40321e7326487c24e095c67af53603d0518d7868bc4ddb21dffe9b240e6365ff42a
7
- data.tar.gz: 32640f604a3f5b2549b5a4eceb0f7e4a61a590b0027c2636f810a6de077ac60dd88a338907e1dfd7866205c7e54bf18fd35dba14245db146dd5eed4a4a30483c
6
+ metadata.gz: e75bdccd2859b063eb1fc48fdce8394e43648ff05b4d25214b66b85111482c1d8d671e24d3a5376d37f0f1093fbefb2866afc5e9882728df2b09c2147cf16a90
7
+ data.tar.gz: 3393dce7f111c75ce16b8b4af7fff51064870cb1033bf446701180cf0c84458ffc3a8ea3f6a58503eff46d1d7e414e588073497fd5e6a20becc036971ddb40d8
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+
data/.travis.yml CHANGED
@@ -7,3 +7,4 @@ rvm:
7
7
  - 2.2
8
8
 
9
9
  script: bundle exec rake test
10
+ sudo: false
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in fluent-plugin-elasticsearch.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'simplecov', require: false
6
7
  gem 'coveralls', require: false
data/History.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ## Changelog
2
2
 
3
- ### Future
3
+ ### 1.3.0
4
+ - add `write_operation`
4
5
 
5
6
  ### 1.2.1
6
7
  - fix `resurrect_after` in out_elasticsearch_dynamic
data/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Fluent::Plugin::Elasticsearch, a plugin for [Fluentd](http://fluentd.org)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/fluent-plugin-elasticsearch.png)](http://badge.fury.io/rb/fluent-plugin-elasticsearch)
4
- [![Dependency Status](https://gemnasium.com/uken/guard-sidekiq.png)](https://gemnasium.com/uken/fluent-plugin-elasticsearch)
5
4
  [![Build Status](https://travis-ci.org/uken/fluent-plugin-elasticsearch.png?branch=master)](https://travis-ci.org/uken/fluent-plugin-elasticsearch)
6
5
  [![Coverage Status](https://coveralls.io/repos/uken/fluent-plugin-elasticsearch/badge.png)](https://coveralls.io/r/uken/fluent-plugin-elasticsearch)
7
6
  [![Code Climate](https://codeclimate.com/github/uken/fluent-plugin-elasticsearch.png)](https://codeclimate.com/github/uken/fluent-plugin-elasticsearch)
7
+ [![Issue Stats](http://issuestats.com/github/uken/fluent-plugin-elasticsearch/badge/pr)](http://issuestats.com/github/uken/fluent-plugin-elasticsearch)
8
+ [![Issue Stats](http://issuestats.com/github/uken/fluent-plugin-elasticsearch/badge/issue)](http://issuestats.com/github/uken/fluent-plugin-elasticsearch)
8
9
 
9
10
  Send your logs to ElasticSearch (and search them with Kibana maybe?)
10
11
 
@@ -27,6 +28,7 @@ Note: For Amazon Elasticsearch Service please consider using [fluent-plugin-aws-
27
28
  + [resurrect_after](#resurrect_after)
28
29
  + [include_tag_key, tag_key](#include_tag_key-tag_key)
29
30
  + [id_key](#id_key)
31
+ + [write_operation](#write_operation)
30
32
  + [Client/host certificate options](#clienthost-certificate-options)
31
33
  + [Buffered output options](#buffered-output-options)
32
34
  + [Not seeing a config you need?](#not-seeing-a-config-you-need)
@@ -164,21 +166,21 @@ request_timeout 15s # defaults to 5s
164
166
 
165
167
  ### reload_connections
166
168
 
169
+ You can tune how the elasticsearch-transport host reloading feature works. By default it will reload the host list from the server every 10,000th request to spread the load. This can be an issue if your ElasticSearch cluster is behind a Reverse Proxy, as Fluentd process may not have direct network access to the ElasticSearch nodes.
170
+
167
171
  ```
168
172
  reload_connections false # defaults to true
169
173
  ```
170
174
 
171
175
  ### reload_on_failure
172
176
 
173
- You can tune how the elasticsearch-transport host reloading feature works. By default it will reload the host list from the server every 10,000th request to spread the load. This can be an issue if your ElasticSearch cluster is behind a Reverse Proxy, as Fluentd process may not have direct network access to the ElasticSearch nodes.
177
+ Indicates that the elasticsearch-transport will try to reload the nodes addresses if there is a failure while making the
178
+ request, this can be useful to quickly remove a dead node from the list of addresses.
174
179
 
175
180
  ```
176
181
  reload_on_failure true # defaults to false
177
182
  ```
178
183
 
179
- Indicates that the elasticsearch-transport will try to reload the nodes addresses if there is a failure while making the
180
- request, this can be useful to quickly remove a dead node from the list of addresses.
181
-
182
184
  ### resurrect_after
183
185
 
184
186
  You can set in the elasticsearch-transport how often dead connections from the elasticsearch-transport's pool will be resurrected.
@@ -225,6 +227,19 @@ This following record `{"name":"Johnny","request_id":"87d89af7daffad6"}` will tr
225
227
  { "name": "Johnny", "request_id": "87d89af7daffad6" }
226
228
  ```
227
229
 
230
+ ### write_operation
231
+
232
+ The write_operation can be any of:
233
+
234
+ | Operation | Description |
235
+ | ------------- | ----------- |
236
+ | index (default) | new data is added while existing data (based on its id) is replaced (reindexed).|
237
+ | create | adds new data - if the data already exists (based on its id), the op is skipped.|
238
+ | update | updates existing data (based on its id). If no data is found, the op is skipped.|
239
+ | upsert | known as merge or insert if the data does not exist, updates if the data exists (based on its id).|
240
+
241
+ **Please note, id is required in create, update, and upsert scenario. Without id, the message will be dropped.**
242
+
228
243
  ### Client/host certificate options
229
244
 
230
245
  Need to verify ElasticSearch's certificate? You can use the following parameter to specify a CA instead of using an environment variable.
data/Rakefile CHANGED
@@ -1,11 +1,10 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
3
 
4
4
  Rake::TestTask.new(:test) do |test|
5
- test.libs << 'lib' << 'test'
5
+ test.libs << 'test'
6
6
  test.pattern = 'test/**/test_*.rb'
7
7
  test.verbose = true
8
8
  end
9
9
 
10
10
  task :default => :test
11
-
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'fluent-plugin-elasticsearch'
6
- s.version = '1.2.1'
6
+ s.version = '1.3.0'
7
7
  s.authors = ['diogo', 'pitr']
8
8
  s.email = ['pitr.vern@gmail.com', 'me@diogoterror.com']
9
9
  s.description = %q{ElasticSearch output plugin for Fluent event collector}
@@ -21,8 +21,8 @@ Gem::Specification.new do |s|
21
21
  s.add_runtime_dependency 'elasticsearch', '>= 0'
22
22
 
23
23
 
24
- s.add_development_dependency 'rake', '~> 0'
24
+ s.add_development_dependency 'rake', '>= 0'
25
25
  s.add_development_dependency 'webmock', '~> 1'
26
26
  s.add_development_dependency 'test-unit', '~> 3.1.0'
27
- s.add_development_dependency 'minitest', '~> 5.7.0'
27
+ s.add_development_dependency 'minitest', '~> 5.8'
28
28
  end
@@ -23,6 +23,7 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
23
23
  config_param :type_name, :string, :default => "fluentd"
24
24
  config_param :index_name, :string, :default => "fluentd"
25
25
  config_param :id_key, :string, :default => nil
26
+ config_param :write_operation, :string, :default => "index"
26
27
  config_param :parent_key, :string, :default => nil
27
28
  config_param :request_timeout, :time, :default => 5
28
29
  config_param :reload_connections, :bool, :default => true
@@ -127,6 +128,24 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
127
128
  super
128
129
  end
129
130
 
131
+ def append_record_to_messages(op, meta, record, msgs)
132
+ case op
133
+ when "update", "upsert"
134
+ if meta.has_key?("_id")
135
+ msgs << { "update" => meta }
136
+ msgs << { "doc" => record, "doc_as_upsert" => op == "upsert" }
137
+ end
138
+ when "create"
139
+ if meta.has_key?("_id")
140
+ msgs << { "create" => meta }
141
+ msgs << record
142
+ end
143
+ when "index"
144
+ msgs << { "index" => meta }
145
+ msgs << record
146
+ end
147
+ end
148
+
130
149
  def write(chunk)
131
150
  bulk_message = []
132
151
 
@@ -154,17 +173,16 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
154
173
  record.merge!(@tag_key => tag)
155
174
  end
156
175
 
157
- meta = { "index" => {"_index" => target_index, "_type" => type_name} }
176
+ meta = {"_index" => target_index, "_type" => type_name}
158
177
  if @id_key && record[@id_key]
159
- meta['index']['_id'] = record[@id_key]
178
+ meta['_id'] = record[@id_key]
160
179
  end
161
180
 
162
181
  if @parent_key && record[@parent_key]
163
- meta['index']['_parent'] = record[@parent_key]
182
+ meta['_parent'] = record[@parent_key]
164
183
  end
165
184
 
166
- bulk_message << meta
167
- bulk_message << record
185
+ append_record_to_messages(@write_operation, meta, record, bulk_message)
168
186
  end
169
187
 
170
188
  send(bulk_message) unless bulk_message.empty?
@@ -149,13 +149,13 @@ class Fluent::ElasticsearchOutputDynamic < Fluent::ElasticsearchOutput
149
149
  record.merge!(dynamic_conf['tag_key'] => tag)
150
150
  end
151
151
 
152
- meta = { "index" => {"_index" => target_index, "_type" => dynamic_conf['type_name']} }
152
+ meta = {"_index" => target_index, "_type" => dynamic_conf['type_name']}
153
153
  if dynamic_conf['id_key'] && record[dynamic_conf['id_key']]
154
- meta['index']['_id'] = record[dynamic_conf['id_key']]
154
+ meta['_id'] = record[dynamic_conf['id_key']]
155
155
  end
156
156
 
157
157
  if dynamic_conf['parent_key'] && record[dynamic_conf['parent_key']]
158
- meta['index']['_parent'] = record[dynamic_conf['parent_key']]
158
+ meta['_parent'] = record[dynamic_conf['parent_key']]
159
159
  end
160
160
 
161
161
  if dynamic_conf['hosts']
@@ -164,9 +164,7 @@ class Fluent::ElasticsearchOutputDynamic < Fluent::ElasticsearchOutput
164
164
  host = "#{dynamic_conf['host']}:#{dynamic_conf['port']}"
165
165
  end
166
166
 
167
- bulk_message[host] << meta
168
- bulk_message[host] << record
169
-
167
+ append_record_to_messages(dynamic_conf["write_operation"], meta, record, bulk_message[host])
170
168
  end
171
169
 
172
170
  bulk_message.each do | hKey, array |
data/test/helper.rb CHANGED
@@ -1 +1,24 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter do |src|
4
+ !(src.filename =~ /^#{SimpleCov.root}\/lib/)
5
+ end
6
+ end
7
+
8
+ require 'coveralls'
9
+ Coveralls.wear!
10
+
11
+ # needs to be after simplecov but before test/unit, because fluentd sets default
12
+ # encoding to ASCII-8BIT, but coverall might load git data which could contain a
13
+ # UTF-8 character
14
+ at_exit do
15
+ Encoding.default_internal = 'UTF-8' if defined?(Encoding) && Encoding.respond_to?(:default_internal)
16
+ Encoding.default_external = 'UTF-8' if defined?(Encoding) && Encoding.respond_to?(:default_external)
17
+ end
18
+
19
+ require 'test/unit'
20
+ require 'fluent/test'
1
21
  require 'minitest/pride'
22
+
23
+ require 'webmock/test_unit'
24
+ WebMock.disable_net_connect!
@@ -1,23 +1,12 @@
1
- require 'test/unit'
2
-
3
- require 'fluent/test'
4
- require 'fluent/plugin/out_elasticsearch'
5
-
6
- require 'webmock/test_unit'
7
- require 'date'
8
-
9
- $:.push File.expand_path("../..", __FILE__)
10
- $:.push File.dirname(__FILE__)
11
-
12
1
  require 'helper'
13
-
14
- WebMock.disable_net_connect!
2
+ require 'date'
15
3
 
16
4
  class ElasticsearchOutput < Test::Unit::TestCase
17
5
  attr_accessor :index_cmds, :index_command_counts
18
6
 
19
7
  def setup
20
8
  Fluent::Test.setup
9
+ require 'fluent/plugin/out_elasticsearch'
21
10
  @driver = nil
22
11
  end
23
12
 
@@ -449,4 +438,64 @@ class ElasticsearchOutput < Test::Unit::TestCase
449
438
  }
450
439
  assert_equal(connection_resets, 3)
451
440
  end
441
+
442
+ def test_update_should_not_write_if_theres_no_id
443
+ driver.configure("write_operation update\n")
444
+ stub_elastic_ping
445
+ stub_elastic
446
+ driver.emit(sample_record)
447
+ driver.run
448
+ assert_nil(index_cmds)
449
+ end
450
+
451
+ def test_upsert_should_not_write_if_theres_no_id
452
+ driver.configure("write_operation upsert\n")
453
+ stub_elastic_ping
454
+ stub_elastic
455
+ driver.emit(sample_record)
456
+ driver.run
457
+ assert_nil(index_cmds)
458
+ end
459
+
460
+ def test_create_should_not_write_if_theres_no_id
461
+ driver.configure("write_operation create\n")
462
+ stub_elastic_ping
463
+ stub_elastic
464
+ driver.emit(sample_record)
465
+ driver.run
466
+ assert_nil(index_cmds)
467
+ end
468
+
469
+ def test_update_should_write_update_op_and_doc_as_upsert_is_false
470
+ driver.configure("write_operation update
471
+ id_key request_id")
472
+ stub_elastic_ping
473
+ stub_elastic
474
+ driver.emit(sample_record)
475
+ driver.run
476
+ assert(index_cmds[0].has_key?("update"))
477
+ assert(!index_cmds[1]["doc_as_upsert"])
478
+ end
479
+
480
+ def test_upsert_should_write_update_op_and_doc_as_upsert_is_true
481
+ driver.configure("write_operation upsert
482
+ id_key request_id")
483
+ stub_elastic_ping
484
+ stub_elastic
485
+ driver.emit(sample_record)
486
+ driver.run
487
+ assert(index_cmds[0].has_key?("update"))
488
+ assert(index_cmds[1]["doc_as_upsert"])
489
+ end
490
+
491
+ def test_create_should_write_create_op
492
+ driver.configure("write_operation create
493
+ id_key request_id")
494
+ stub_elastic_ping
495
+ stub_elastic
496
+ driver.emit(sample_record)
497
+ driver.run
498
+ assert(index_cmds[0].has_key?("create"))
499
+ end
500
+
452
501
  end
@@ -1,23 +1,12 @@
1
- require 'test/unit'
2
-
3
- require 'fluent/test'
4
- require 'fluent/plugin/out_elasticsearch_dynamic'
5
-
6
- require 'webmock/test_unit'
7
- require 'date'
8
-
9
- $:.push File.expand_path("../..", __FILE__)
10
- $:.push File.dirname(__FILE__)
11
-
12
1
  require 'helper'
13
-
14
- WebMock.disable_net_connect!
2
+ require 'date'
15
3
 
16
4
  class ElasticsearchOutputDynamic < Test::Unit::TestCase
17
5
  attr_accessor :index_cmds, :index_command_counts
18
6
 
19
7
  def setup
20
8
  Fluent::Test.setup
9
+ require 'fluent/plugin/out_elasticsearch_dynamic'
21
10
  @driver = nil
22
11
  end
23
12
 
@@ -449,4 +438,63 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
449
438
  }
450
439
  assert_equal(connection_resets, 3)
451
440
  end
441
+
442
+ def test_update_should_not_write_if_theres_no_id
443
+ driver.configure("write_operation update\n")
444
+ stub_elastic_ping
445
+ stub_elastic
446
+ driver.emit(sample_record)
447
+ driver.run
448
+ assert_nil(index_cmds)
449
+ end
450
+
451
+ def test_upsert_should_not_write_if_theres_no_id
452
+ driver.configure("write_operation upsert\n")
453
+ stub_elastic_ping
454
+ stub_elastic
455
+ driver.emit(sample_record)
456
+ driver.run
457
+ assert_nil(index_cmds)
458
+ end
459
+
460
+ def test_create_should_not_write_if_theres_no_id
461
+ driver.configure("write_operation create\n")
462
+ stub_elastic_ping
463
+ stub_elastic
464
+ driver.emit(sample_record)
465
+ driver.run
466
+ assert_nil(index_cmds)
467
+ end
468
+
469
+ def test_update_should_write_update_op_and_doc_as_upsert_is_false
470
+ driver.configure("write_operation update
471
+ id_key request_id")
472
+ stub_elastic_ping
473
+ stub_elastic
474
+ driver.emit(sample_record)
475
+ driver.run
476
+ assert(index_cmds[0].has_key?("update"))
477
+ assert(!index_cmds[1]["doc_as_upsert"])
478
+ end
479
+
480
+ def test_upsert_should_write_update_op_and_doc_as_upsert_is_true
481
+ driver.configure("write_operation upsert
482
+ id_key request_id")
483
+ stub_elastic_ping
484
+ stub_elastic
485
+ driver.emit(sample_record)
486
+ driver.run
487
+ assert(index_cmds[0].has_key?("update"))
488
+ assert(index_cmds[1]["doc_as_upsert"])
489
+ end
490
+
491
+ def test_create_should_write_create_op
492
+ driver.configure("write_operation create
493
+ id_key request_id")
494
+ stub_elastic_ping
495
+ stub_elastic
496
+ driver.emit(sample_record)
497
+ driver.run
498
+ assert(index_cmds[0].has_key?("create"))
499
+ end
452
500
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - diogo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-03 00:00:00.000000000 Z
12
+ date: 2016-01-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
@@ -57,14 +57,14 @@ dependencies:
57
57
  name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - "~>"
60
+ - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - "~>"
67
+ - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
70
  - !ruby/object:Gem::Dependency
@@ -101,14 +101,14 @@ dependencies:
101
101
  requirements:
102
102
  - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: 5.7.0
104
+ version: '5.8'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - "~>"
110
110
  - !ruby/object:Gem::Version
111
- version: 5.7.0
111
+ version: '5.8'
112
112
  description: ElasticSearch output plugin for Fluent event collector
113
113
  email:
114
114
  - pitr.vern@gmail.com
@@ -117,6 +117,7 @@ executables: []
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - ".coveralls.yml"
120
121
  - ".editorconfig"
121
122
  - ".gitignore"
122
123
  - ".travis.yml"