fluent-plugin-elasticsearch-check-size 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2cb26a5a6300edf2977d3f66b2133d4b83e1b310
4
+ data.tar.gz: f43d93e52da0bfcb13206d4852060800dcd0164b
5
+ SHA512:
6
+ metadata.gz: 706d876114e2a8f928ffa7da7ee5aa678e6c8c3aa2b8e310c3fd94b78ed40e7379b8d47cf11362557875556d6e837d5950c54e47fdfc8fe6918180678cfa8841
7
+ data.tar.gz: bdd990da4a17ba0f633b39955c62ef106d0ed143746ee14982756c592afacc7f5da9310494c5a7a80cd70d0b5afa62b1e2cfbfe68ea318c4b83f4571d87cd623
@@ -0,0 +1,9 @@
1
+ # EditorConfig: http://EditorConfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ end_of_line = lf
7
+ insert_final_newline = true
8
+ indent_style = space
9
+ indent_size = 2
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.1
7
+
8
+ script: bundle exec ruby -S -Itest test/plugin/test_out_elasticsearch.rb
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-elasticsearch.gemspec
4
+ gemspec
5
+
6
+ gem 'coveralls', require: false
@@ -0,0 +1,59 @@
1
+ ## Changelog
2
+
3
+ ### Future
4
+
5
+ ### 0.9.0
6
+ - Add `ssl_verify` option (#108)
7
+
8
+ ### 0.8.0
9
+ - Replace Patron with Excon HTTP client
10
+
11
+ ### 0.7.0
12
+ - Add new option `time_key` (#85)
13
+
14
+ ### 0.6.1
15
+ - 0.10.43 is minimum version required of fluentd (#79)
16
+
17
+ ### 0.6.0
18
+ - added `reload_on_failure` and `reload_connections` flags (#78)
19
+
20
+ ### 0.5.1
21
+ - fix legacy hosts option, port should be optional (#75)
22
+
23
+ ### 0.5.0
24
+ - add full connection URI support (#65)
25
+ - use `@timestamp` for index (#41)
26
+ - add support for elasticsearch gem version 1 (#71)
27
+ - fix connection reset & retry when connection is lost (#67)
28
+
29
+ ### 0.4.0
30
+ - add `request_timeout` config (#59)
31
+ - fix lockup when non-hash values are sent (#52)
32
+
33
+ ### 0.3.1
34
+ - force using patron (#46)
35
+ - do not generate @timestamp if already part of message (#35)
36
+
37
+ ### 0.3.0
38
+ - add `parent_key` option (#28)
39
+ - have travis-ci build on multiple rubies (#30)
40
+ - add `utc_index` and `hosts` options, switch to using `elasticsearch` gem (#26, #29)
41
+
42
+ ### 0.2.0
43
+ - fix encoding issues with JSON conversion and again when sending to elasticsearch (#19, #21)
44
+ - add logstash_dateformat option (#20)
45
+
46
+ ### 0.1.4
47
+ - add logstash_prefix option
48
+
49
+ ### 0.1.3
50
+ - raising an exception on non-success response from elasticsearch
51
+
52
+ ### 0.1.2
53
+ - add id_key option
54
+
55
+ ### 0.1.1
56
+ - fix timezone in logstash key
57
+
58
+ ### 0.1.0
59
+ - Initial gem release.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Uken Games
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,230 @@
1
+ # Fluent::Plugin::Elasticsearch, a plugin for [Fluentd](http://fluentd.org)
2
+
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
+ [![Build Status](https://travis-ci.org/uken/fluent-plugin-elasticsearch.png?branch=master)](https://travis-ci.org/uken/fluent-plugin-elasticsearch)
6
+ [![Coverage Status](https://coveralls.io/repos/uken/fluent-plugin-elasticsearch/badge.png)](https://coveralls.io/r/uken/fluent-plugin-elasticsearch)
7
+ [![Code Climate](https://codeclimate.com/github/uken/fluent-plugin-elasticsearch.png)](https://codeclimate.com/github/uken/fluent-plugin-elasticsearch)
8
+
9
+ I wrote this so you can search logs routed through Fluentd.
10
+
11
+ ## Installation
12
+
13
+ $ gem install fluent-plugin-elasticsearch
14
+
15
+ * prerequisite : You need to install [libcurl (libcurl-devel)](http://curl.haxx.se/libcurl/) to work with.
16
+
17
+ ## Usage
18
+
19
+ In your fluentd configration, use `type elasticsearch`. Additional configuration is optional, default values would look like this:
20
+
21
+ ```
22
+ host localhost
23
+ port 9200
24
+ index_name fluentd
25
+ type_name fluentd
26
+ ```
27
+
28
+ **Index templates**
29
+
30
+ This plugin creates ElasticSearch indices by merely writing to them. Consider using [Index Templates](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html) to gain control of what get indexed and how. See [this example](https://github.com/uken/fluent-plugin-elasticsearch/issues/33#issuecomment-38693282) for a good starting point.
31
+
32
+ **More options:**
33
+
34
+ **hosts**
35
+
36
+ ```
37
+ hosts host1:port1,host2:port2,host3:port3
38
+ ```
39
+
40
+ or
41
+
42
+ ```
43
+ hosts https://customhost.com:443/path,https://username:password@host-failover.com:443
44
+ ```
45
+
46
+ You can specify multiple elasticsearch hosts with separator ",".
47
+
48
+ If you specify multiple hosts, this plugin will load balance updates to elasticsearch. This is an [elasticsearch-ruby](https://github.com/elasticsearch/elasticsearch-ruby) feature, the default strategy is round-robin.
49
+
50
+ **user, password, path, scheme, ssl_verify**
51
+
52
+ If you specify this option, host and port options are ignored.
53
+
54
+ ```
55
+ user demo
56
+ password secret
57
+ path /elastic_search/
58
+ scheme https
59
+ ```
60
+
61
+ You can specify user and password for HTTP basic auth. If used in conjunction with a hosts list, then these options will be used by default i.e. if you do not provide any of these options within the hosts listed.
62
+
63
+ Specify `ssl_verify false` to skip ssl verification (defaults to true)
64
+
65
+ **logstash_format**
66
+
67
+ ```
68
+ logstash_format true # defaults to false
69
+ ```
70
+
71
+ This is meant to make writing data into elasticsearch compatible to what logstash writes. By doing this, one could take advantade of [kibana](http://kibana.org/).
72
+
73
+ **logstash_prefix**
74
+
75
+ ```
76
+ logstash_prefix mylogs # defaults to "logstash"
77
+ ```
78
+
79
+ **logstash_dateformat**
80
+
81
+ By default, the records inserted into index `logstash-YYMMDD`. This option allows to insert into specified index like `mylogs-YYYYMM` for a monthly index.
82
+
83
+ ```
84
+ logstash_dateformat %Y.%m. # defaults to "%Y.%m.%d"
85
+ ```
86
+
87
+ **time_key**
88
+
89
+ By default, when inserting records in logstash format, @timestamp is dynamically created with the time at log ingestion. If you'd like to use a custom time. Include an @timestamp with your record.
90
+
91
+ ```
92
+ {"@timestamp":"2014-04-07T000:00:00-00:00"}
93
+ ```
94
+
95
+ You can specify an option `time_key` (like the option described in [tail Input Plugin](http://docs.fluentd.org/articles/in_tail)) if you don't like `@timestamp`.
96
+
97
+ Suppose you have settings
98
+
99
+ ```
100
+ logstash_format true
101
+ time_key vtm
102
+ ```
103
+
104
+ Your input is:
105
+ ```
106
+ {
107
+ "title": "developer",
108
+ "vtm": "2014-12-19T08:01:03Z"
109
+ }
110
+ ```
111
+
112
+ The output will be
113
+ ```
114
+ {
115
+ "title": "developer",
116
+ "@timstamp": "2014-12-19T08:01:03Z",
117
+ "vtm": "2014-12-19T08:01:03Z"
118
+ }
119
+ ```
120
+
121
+ **utc_index**
122
+
123
+ ```
124
+ utc_index true
125
+ ```
126
+
127
+ By default, the records inserted into index `logstash-YYMMDD` with utc (Coordinated Universal Time). This option allows to use local time if you describe utc_index to false.
128
+
129
+ **request_timeout**
130
+
131
+ ```
132
+ request_timeout 15s # defaults to 5s
133
+ ```
134
+
135
+ You can specify HTTP request timeout.
136
+
137
+ This is useful when Elasticsearch cannot return response for bulk request within the default of 5 seconds.
138
+
139
+ **reload_connections**
140
+
141
+ ```
142
+ reload_connections false # defaults to true
143
+ ```
144
+
145
+ **reload_on_failure**
146
+
147
+ 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.
148
+
149
+ ```
150
+ reload_on_failure true # defaults to false
151
+ ```
152
+
153
+ Indicates that the elasticsearch-transport will try to reload the nodes addresses if there is a failure while making the
154
+ request, this can be useful to quickly remove a dead node from the list of addresses.
155
+
156
+ **include_tag_key, tag_key**
157
+
158
+ ```
159
+ include_tag_key true # defaults to false
160
+ tag_key tag # defaults to tag
161
+ ```
162
+
163
+ This will add the fluentd tag in the json record. For instance, if you have a config like this:
164
+
165
+ ```
166
+ <match my.logs>
167
+ type elasticsearch
168
+ include_tag_key true
169
+ tag_key _key
170
+ </match>
171
+ ```
172
+
173
+ The record inserted into elasticsearch would be
174
+
175
+ ```
176
+ {"_key":"my.logs", "name":"Johnny Doeie"}
177
+ ```
178
+
179
+ **id_key**
180
+
181
+ ```
182
+ id_key request_id # use "request_id" field as a record id in ES
183
+ ```
184
+
185
+ By default, all records inserted into elasticsearch get a random _id. This option allows to use a field in the record as an identifier.
186
+
187
+ This following record `{"name":"Johnny","request_id":"87d89af7daffad6"}` will trigger the following ElasticSearch command
188
+
189
+ ```
190
+ { "index" : { "_index" : "logstash-2013.01.01, "_type" : "fluentd", "_id" : "87d89af7daffad6" } }
191
+ { "name": "Johnny", "request_id": "87d89af7daffad6" }
192
+ ```
193
+
194
+ **Buffered output options**
195
+
196
+ fluentd-plugin-elasticsearch is a buffered output that uses elasticseach's bulk API. So additional buffer configuration would be (with default values):
197
+
198
+ ```
199
+ buffer_type memory
200
+ flush_interval 60
201
+ retry_limit 17
202
+ retry_wait 1.0
203
+ num_threads 1
204
+ ```
205
+
206
+ **Not seeing a config you need?**
207
+
208
+ We try to keep the scope of this plugin small. If you need more configuration options, please consider using [fluent-plugin-forest](https://github.com/tagomoris/fluent-plugin-forest). For example, to configure multiple tags to be sent to different ElasticSearch indices:
209
+
210
+ ```
211
+ <match my.logs.*>
212
+ type forest
213
+ subtype elasticsearch
214
+ remove_prefix my.logs
215
+ <template>
216
+ logstash_prefix ${tag}
217
+ # ...
218
+ </template>
219
+ </match>
220
+ ```
221
+
222
+ ## Contributing
223
+
224
+ 1. Fork it
225
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
226
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
227
+ 4. Push to the branch (`git push origin my-new-feature`)
228
+ 5. Create new Pull Request
229
+
230
+ If you have a question, [open an Issue](https://github.com/uken/fluent-plugin-elasticsearch/issues).
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :test
11
+
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'fluent-plugin-elasticsearch-check-size'
6
+ s.version = '0.1.0'
7
+ s.authors = ['Nao Akechi']
8
+ s.email = ['nao.akechi@gmail.com']
9
+ s.description = %q{ElasticSearch output plugin for Fluent event collector}
10
+ s.summary = s.description
11
+ s.homepage = 'https://github.com/nakc/fluent-plugin-elasticsearch'
12
+ s.license = 'MIT'
13
+
14
+ s.files = `git ls-files`.split($/)
15
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_runtime_dependency 'fluentd', '>= 0.10.43'
20
+ s.add_runtime_dependency 'excon', '>= 0'
21
+ s.add_runtime_dependency 'elasticsearch', '>= 0'
22
+
23
+
24
+ s.add_development_dependency 'rake', '~> 0'
25
+ s.add_development_dependency 'webmock', '~> 1'
26
+ end
@@ -0,0 +1,188 @@
1
+ # encoding: UTF-8
2
+ require 'date'
3
+ require 'excon'
4
+ require 'elasticsearch'
5
+ require 'uri'
6
+ require 'objspace'
7
+
8
+ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
9
+ class ConnectionFailure < StandardError; end
10
+
11
+ Fluent::Plugin.register_output('elasticsearch', self)
12
+
13
+ config_param :host, :string, :default => 'localhost'
14
+ config_param :port, :integer, :default => 9200
15
+ config_param :user, :string, :default => nil
16
+ config_param :password, :string, :default => nil
17
+ config_param :path, :string, :default => nil
18
+ config_param :scheme, :string, :default => 'http'
19
+ config_param :hosts, :string, :default => nil
20
+ config_param :logstash_format, :bool, :default => false
21
+ config_param :logstash_prefix, :string, :default => "logstash"
22
+ config_param :logstash_dateformat, :string, :default => "%Y.%m.%d"
23
+ config_param :utc_index, :bool, :default => true
24
+ config_param :type_name, :string, :default => "fluentd"
25
+ config_param :index_name, :string, :default => "fluentd"
26
+ config_param :id_key, :string, :default => nil
27
+ config_param :parent_key, :string, :default => nil
28
+ config_param :request_timeout, :time, :default => 5
29
+ config_param :reload_connections, :bool, :default => true
30
+ config_param :reload_on_failure, :bool, :default => false
31
+ config_param :time_key, :string, :default => nil
32
+ config_param :ssl_verify , :bool, :default => true
33
+ config_param :max_size, :integer, :default => 32000
34
+
35
+ include Fluent::SetTagKeyMixin
36
+ config_set_default :include_tag_key, false
37
+
38
+ def initialize
39
+ super
40
+ end
41
+
42
+ def configure(conf)
43
+ super
44
+ end
45
+
46
+ def start
47
+ super
48
+ end
49
+
50
+ def client
51
+ @_es ||= begin
52
+ adapter_conf = lambda {|f| f.adapter :excon }
53
+ transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new(get_connection_options.merge(
54
+ options: {
55
+ reload_connections: @reload_connections,
56
+ reload_on_failure: @reload_on_failure,
57
+ retry_on_failure: 5,
58
+ transport_options: {
59
+ request: { timeout: @request_timeout },
60
+ ssl: { verify: @ssl_verify }
61
+ }
62
+ }), &adapter_conf)
63
+ es = Elasticsearch::Client.new transport: transport
64
+
65
+ begin
66
+ raise ConnectionFailure, "Can not reach Elasticsearch cluster (#{connection_options_description})!" unless es.ping
67
+ rescue *es.transport.host_unreachable_exceptions => e
68
+ raise ConnectionFailure, "Can not reach Elasticsearch cluster (#{connection_options_description})! #{e.message}"
69
+ end
70
+
71
+ log.info "Connection opened to Elasticsearch cluster => #{connection_options_description}"
72
+ es
73
+ end
74
+ end
75
+
76
+ def get_connection_options
77
+ raise "`password` must be present if `user` is present" if @user && !@password
78
+
79
+ hosts = if @hosts
80
+ @hosts.split(',').map do |host_str|
81
+ # Support legacy hosts format host:port,host:port,host:port...
82
+ if host_str.match(%r{^[^:]+(\:\d+)?$})
83
+ {
84
+ host: host_str.split(':')[0],
85
+ port: (host_str.split(':')[1] || @port).to_i,
86
+ scheme: @scheme
87
+ }
88
+ else
89
+ # New hosts format expects URLs such as http://logs.foo.com,https://john:pass@logs2.foo.com/elastic
90
+ uri = URI(host_str)
91
+ %w(user password path).inject(host: uri.host, port: uri.port, scheme: uri.scheme) do |hash, key|
92
+ hash[key.to_sym] = uri.public_send(key) unless uri.public_send(key).nil? || uri.public_send(key) == ''
93
+ hash
94
+ end
95
+ end
96
+ end.compact
97
+ else
98
+ [{host: @host, port: @port, scheme: @scheme}]
99
+ end.each do |host|
100
+ host.merge!(user: @user, password: @password) if !host[:user] && @user
101
+ host.merge!(path: @path) if !host[:path] && @path
102
+ end
103
+
104
+ {
105
+ hosts: hosts
106
+ }
107
+ end
108
+
109
+ def connection_options_description
110
+ get_connection_options[:hosts].map do |host_info|
111
+ attributes = host_info.dup
112
+ attributes[:password] = 'obfuscated' if attributes.has_key?(:password)
113
+ attributes.inspect
114
+ end.join(', ')
115
+ end
116
+
117
+ def format(tag, time, record)
118
+ [tag, time, record].to_msgpack
119
+ end
120
+
121
+ def shutdown
122
+ super
123
+ end
124
+
125
+ def write(chunk)
126
+ bulk_message = []
127
+
128
+ chunk.msgpack_each do |tag, time, record|
129
+ next unless record.is_a? Hash
130
+ if @logstash_format
131
+ if record.has_key?("@timestamp")
132
+ time = Time.parse record["@timestamp"]
133
+ elsif record.has_key?(@time_key)
134
+ time = Time.parse record[@time_key]
135
+ record['@timestamp'] = record[@time_key]
136
+ else
137
+ record.merge!({"@timestamp" => Time.at(time).to_datetime.to_s})
138
+ end
139
+ if @utc_index
140
+ target_index = "#{@logstash_prefix}-#{Time.at(time).getutc.strftime("#{@logstash_dateformat}")}"
141
+ else
142
+ target_index = "#{@logstash_prefix}-#{Time.at(time).strftime("#{@logstash_dateformat}")}"
143
+ end
144
+ else
145
+ target_index = @index_name
146
+ end
147
+
148
+ if @include_tag_key
149
+ record.merge!(@tag_key => tag)
150
+ end
151
+
152
+ meta = { "index" => {"_index" => target_index, "_type" => type_name} }
153
+ if @id_key && record[@id_key]
154
+ meta['index']['_id'] = record[@id_key]
155
+ end
156
+
157
+ if @parent_key && record[@parent_key]
158
+ meta['index']['_parent'] = record[@parent_key]
159
+ end
160
+
161
+ if ObjectSpace.memsize_of(record) < @max_size
162
+ bulk_message << meta
163
+ bulk_message << record
164
+ else
165
+ log.info "Could not send log to Elasticsearch: the size of log exceeded max_size"
166
+ end
167
+ end
168
+
169
+ send(bulk_message) unless bulk_message.empty?
170
+ bulk_message.clear
171
+ end
172
+
173
+ def send(data)
174
+ retries = 0
175
+ begin
176
+ client.bulk body: data
177
+ rescue *client.transport.host_unreachable_exceptions => e
178
+ if retries < 2
179
+ retries += 1
180
+ @_es = nil
181
+ log.warn "Could not push logs to Elasticsearch, resetting connection and trying again. #{e.message}"
182
+ sleep 2**retries
183
+ retry
184
+ end
185
+ raise ConnectionFailure, "Could not push logs to Elasticsearch after #{retries} retries. #{e.message}"
186
+ end
187
+ end
188
+ end
@@ -0,0 +1 @@
1
+ require 'minitest/pride'
@@ -0,0 +1,452 @@
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
+ require 'helper'
13
+
14
+ WebMock.disable_net_connect!
15
+
16
+ class ElasticsearchOutput < Test::Unit::TestCase
17
+ attr_accessor :index_cmds, :index_command_counts
18
+
19
+ def setup
20
+ Fluent::Test.setup
21
+ @driver = nil
22
+ end
23
+
24
+ def driver(tag='test', conf='')
25
+ @driver ||= Fluent::Test::BufferedOutputTestDriver.new(Fluent::ElasticsearchOutput, tag).configure(conf)
26
+ end
27
+
28
+ def sample_record
29
+ {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent'}
30
+ end
31
+
32
+ def stub_elastic_ping(url="http://localhost:9200")
33
+ stub_request(:head, url).to_return(:status => 200, :body => "", :headers => {})
34
+ end
35
+
36
+ def stub_elastic(url="http://localhost:9200/_bulk")
37
+ stub_request(:post, url).with do |req|
38
+ @index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
39
+ end
40
+ end
41
+
42
+ def stub_elastic_unavailable(url="http://localhost:9200/_bulk")
43
+ stub_request(:post, url).to_return(:status => [503, "Service Unavailable"])
44
+ end
45
+
46
+ def stub_elastic_with_store_index_command_counts(url="http://localhost:9200/_bulk")
47
+ if @index_command_counts == nil
48
+ @index_command_counts = {}
49
+ @index_command_counts.default = 0
50
+ end
51
+
52
+ stub_request(:post, url).with do |req|
53
+ index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
54
+ @index_command_counts[url] += index_cmds.size
55
+ end
56
+ end
57
+
58
+ def test_configure
59
+ config = %{
60
+ host logs.google.com
61
+ port 777
62
+ scheme https
63
+ path /es/
64
+ user john
65
+ password doe
66
+ }
67
+ instance = driver('test', config).instance
68
+
69
+ assert_equal 'logs.google.com', instance.host
70
+ assert_equal 777, instance.port
71
+ assert_equal 'https', instance.scheme
72
+ assert_equal '/es/', instance.path
73
+ assert_equal 'john', instance.user
74
+ assert_equal 'doe', instance.password
75
+ end
76
+
77
+ def test_legacy_hosts_list
78
+ config = %{
79
+ hosts host1:50,host2:100,host3
80
+ scheme https
81
+ path /es/
82
+ port 123
83
+ }
84
+ instance = driver('test', config).instance
85
+
86
+ assert_equal 3, instance.get_connection_options[:hosts].length
87
+ host1, host2, host3 = instance.get_connection_options[:hosts]
88
+
89
+ assert_equal 'host1', host1[:host]
90
+ assert_equal 50, host1[:port]
91
+ assert_equal 'https', host1[:scheme]
92
+ assert_equal '/es/', host2[:path]
93
+ assert_equal 'host3', host3[:host]
94
+ assert_equal 123, host3[:port]
95
+ assert_equal 'https', host3[:scheme]
96
+ assert_equal '/es/', host3[:path]
97
+ end
98
+
99
+ def test_hosts_list
100
+ config = %{
101
+ hosts https://john:password@host1:443/elastic/,http://host2
102
+ path /default_path
103
+ user default_user
104
+ password default_password
105
+ }
106
+ instance = driver('test', config).instance
107
+
108
+ assert_equal 2, instance.get_connection_options[:hosts].length
109
+ host1, host2 = instance.get_connection_options[:hosts]
110
+
111
+ assert_equal 'host1', host1[:host]
112
+ assert_equal 443, host1[:port]
113
+ assert_equal 'https', host1[:scheme]
114
+ assert_equal 'john', host1[:user]
115
+ assert_equal 'password', host1[:password]
116
+ assert_equal '/elastic/', host1[:path]
117
+
118
+ assert_equal 'host2', host2[:host]
119
+ assert_equal 'http', host2[:scheme]
120
+ assert_equal 'default_user', host2[:user]
121
+ assert_equal 'default_password', host2[:password]
122
+ assert_equal '/default_path', host2[:path]
123
+ end
124
+
125
+ def test_single_host_params_and_defaults
126
+ config = %{
127
+ host logs.google.com
128
+ user john
129
+ password doe
130
+ }
131
+ instance = driver('test', config).instance
132
+
133
+ assert_equal 1, instance.get_connection_options[:hosts].length
134
+ host1 = instance.get_connection_options[:hosts][0]
135
+
136
+ assert_equal 'logs.google.com', host1[:host]
137
+ assert_equal 9200, host1[:port]
138
+ assert_equal 'http', host1[:scheme]
139
+ assert_equal 'john', host1[:user]
140
+ assert_equal 'doe', host1[:password]
141
+ assert_equal nil, host1[:path]
142
+ end
143
+
144
+ def test_writes_to_default_index
145
+ stub_elastic_ping
146
+ stub_elastic
147
+ driver.emit(sample_record)
148
+ driver.run
149
+ assert_equal('fluentd', index_cmds.first['index']['_index'])
150
+ end
151
+
152
+ def test_writes_to_default_type
153
+ stub_elastic_ping
154
+ stub_elastic
155
+ driver.emit(sample_record)
156
+ driver.run
157
+ assert_equal('fluentd', index_cmds.first['index']['_type'])
158
+ end
159
+
160
+ def test_writes_to_speficied_index
161
+ driver.configure("index_name myindex\n")
162
+ stub_elastic_ping
163
+ stub_elastic
164
+ driver.emit(sample_record)
165
+ driver.run
166
+ assert_equal('myindex', index_cmds.first['index']['_index'])
167
+ end
168
+
169
+ def test_writes_to_speficied_type
170
+ driver.configure("type_name mytype\n")
171
+ stub_elastic_ping
172
+ stub_elastic
173
+ driver.emit(sample_record)
174
+ driver.run
175
+ assert_equal('mytype', index_cmds.first['index']['_type'])
176
+ end
177
+
178
+ def test_writes_to_speficied_host
179
+ driver.configure("host 192.168.33.50\n")
180
+ stub_elastic_ping("http://192.168.33.50:9200")
181
+ elastic_request = stub_elastic("http://192.168.33.50:9200/_bulk")
182
+ driver.emit(sample_record)
183
+ driver.run
184
+ assert_requested(elastic_request)
185
+ end
186
+
187
+ def test_writes_to_speficied_port
188
+ driver.configure("port 9201\n")
189
+ stub_elastic_ping("http://localhost:9201")
190
+ elastic_request = stub_elastic("http://localhost:9201/_bulk")
191
+ driver.emit(sample_record)
192
+ driver.run
193
+ assert_requested(elastic_request)
194
+ end
195
+
196
+ def test_writes_to_multi_hosts
197
+ hosts = [['192.168.33.50', 9201], ['192.168.33.51', 9201], ['192.168.33.52', 9201]]
198
+ hosts_string = hosts.map {|x| "#{x[0]}:#{x[1]}"}.compact.join(',')
199
+
200
+ driver.configure("hosts #{hosts_string}")
201
+
202
+ hosts.each do |host_info|
203
+ host, port = host_info
204
+ stub_elastic_ping("http://#{host}:#{port}")
205
+ stub_elastic_with_store_index_command_counts("http://#{host}:#{port}/_bulk")
206
+ end
207
+
208
+ 1000.times do
209
+ driver.emit(sample_record.merge('age'=>rand(100)))
210
+ end
211
+
212
+ driver.run
213
+
214
+ # @note: we cannot make multi chunks with options (flush_interval, buffer_chunk_limit)
215
+ # it's Fluentd test driver's constraint
216
+ # so @index_command_counts.size is always 1
217
+
218
+ assert(@index_command_counts.size > 0, "not working with hosts options")
219
+
220
+ total = 0
221
+ @index_command_counts.each do |url, count|
222
+ total += count
223
+ end
224
+ assert_equal(2000, total)
225
+ end
226
+
227
+ def test_makes_bulk_request
228
+ stub_elastic_ping
229
+ stub_elastic
230
+ driver.emit(sample_record)
231
+ driver.emit(sample_record.merge('age' => 27))
232
+ driver.run
233
+ assert_equal(4, index_cmds.count)
234
+ end
235
+
236
+ def test_all_records_are_preserved_in_bulk
237
+ stub_elastic_ping
238
+ stub_elastic
239
+ driver.emit(sample_record)
240
+ driver.emit(sample_record.merge('age' => 27))
241
+ driver.run
242
+ assert_equal(26, index_cmds[1]['age'])
243
+ assert_equal(27, index_cmds[3]['age'])
244
+ end
245
+
246
+ def test_writes_to_logstash_index
247
+ driver.configure("logstash_format true\n")
248
+ time = Time.parse Date.today.to_s
249
+ logstash_index = "logstash-#{time.getutc.strftime("%Y.%m.%d")}"
250
+ stub_elastic_ping
251
+ stub_elastic
252
+ driver.emit(sample_record, time)
253
+ driver.run
254
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
255
+ end
256
+
257
+ def test_writes_to_logstash_utc_index
258
+ driver.configure("logstash_format true
259
+ utc_index false")
260
+ time = Time.parse Date.today.to_s
261
+ utc_index = "logstash-#{time.strftime("%Y.%m.%d")}"
262
+ stub_elastic_ping
263
+ stub_elastic
264
+ driver.emit(sample_record, time)
265
+ driver.run
266
+ assert_equal(utc_index, index_cmds.first['index']['_index'])
267
+ end
268
+
269
+ def test_writes_to_logstash_index_with_specified_prefix
270
+ driver.configure("logstash_format true
271
+ logstash_prefix myprefix")
272
+ time = Time.parse Date.today.to_s
273
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
274
+ stub_elastic_ping
275
+ stub_elastic
276
+ driver.emit(sample_record, time)
277
+ driver.run
278
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
279
+ end
280
+
281
+ def test_writes_to_logstash_index_with_specified_dateformat
282
+ driver.configure("logstash_format true
283
+ logstash_dateformat %Y.%m")
284
+ time = Time.parse Date.today.to_s
285
+ logstash_index = "logstash-#{time.getutc.strftime("%Y.%m")}"
286
+ stub_elastic_ping
287
+ stub_elastic
288
+ driver.emit(sample_record, time)
289
+ driver.run
290
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
291
+ end
292
+
293
+ def test_writes_to_logstash_index_with_specified_prefix_and_dateformat
294
+ driver.configure("logstash_format true
295
+ logstash_prefix myprefix
296
+ logstash_dateformat %Y.%m")
297
+ time = Time.parse Date.today.to_s
298
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m")}"
299
+ stub_elastic_ping
300
+ stub_elastic
301
+ driver.emit(sample_record, time)
302
+ driver.run
303
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
304
+ end
305
+
306
+ def test_doesnt_add_logstash_timestamp_by_default
307
+ stub_elastic_ping
308
+ stub_elastic
309
+ driver.emit(sample_record)
310
+ driver.run
311
+ assert_nil(index_cmds[1]['@timestamp'])
312
+ end
313
+
314
+ def test_adds_logstash_timestamp_when_configured
315
+ driver.configure("logstash_format true\n")
316
+ stub_elastic_ping
317
+ stub_elastic
318
+ ts = DateTime.now.to_s
319
+ driver.emit(sample_record)
320
+ driver.run
321
+ assert(index_cmds[1].has_key? '@timestamp')
322
+ assert_equal(index_cmds[1]['@timestamp'], ts)
323
+ end
324
+
325
+ def test_uses_custom_timestamp_when_included_in_record
326
+ driver.configure("logstash_format true\n")
327
+ stub_elastic_ping
328
+ stub_elastic
329
+ ts = DateTime.new(2001,2,3).to_s
330
+ driver.emit(sample_record.merge!('@timestamp' => ts))
331
+ driver.run
332
+ assert(index_cmds[1].has_key? '@timestamp')
333
+ assert_equal(index_cmds[1]['@timestamp'], ts)
334
+ end
335
+
336
+ def test_uses_custom_time_key
337
+ driver.configure("logstash_format true
338
+ time_key vtm\n")
339
+ stub_elastic_ping
340
+ stub_elastic
341
+ ts = DateTime.new(2001,2,3).to_s
342
+ driver.emit(sample_record.merge!('vtm' => ts))
343
+ driver.run
344
+ assert(index_cmds[1].has_key? '@timestamp')
345
+ assert_equal(index_cmds[1]['@timestamp'], ts)
346
+ end
347
+
348
+ def test_doesnt_add_tag_key_by_default
349
+ stub_elastic_ping
350
+ stub_elastic
351
+ driver.emit(sample_record)
352
+ driver.run
353
+ assert_nil(index_cmds[1]['tag'])
354
+ end
355
+
356
+ def test_adds_tag_key_when_configured
357
+ driver('mytag').configure("include_tag_key true\n")
358
+ stub_elastic_ping
359
+ stub_elastic
360
+ driver.emit(sample_record)
361
+ driver.run
362
+ assert(index_cmds[1].has_key?('tag'))
363
+ assert_equal(index_cmds[1]['tag'], 'mytag')
364
+ end
365
+
366
+ def test_adds_id_key_when_configured
367
+ driver.configure("id_key request_id\n")
368
+ stub_elastic_ping
369
+ stub_elastic
370
+ driver.emit(sample_record)
371
+ driver.run
372
+ assert_equal(index_cmds[0]['index']['_id'], '42')
373
+ end
374
+
375
+ def test_doesnt_add_id_key_if_missing_when_configured
376
+ driver.configure("id_key another_request_id\n")
377
+ stub_elastic_ping
378
+ stub_elastic
379
+ driver.emit(sample_record)
380
+ driver.run
381
+ assert(!index_cmds[0]['index'].has_key?('_id'))
382
+ end
383
+
384
+ def test_adds_id_key_when_not_configured
385
+ stub_elastic_ping
386
+ stub_elastic
387
+ driver.emit(sample_record)
388
+ driver.run
389
+ assert(!index_cmds[0]['index'].has_key?('_id'))
390
+ end
391
+
392
+ def test_adds_parent_key_when_configured
393
+ driver.configure("parent_key parent_id\n")
394
+ stub_elastic_ping
395
+ stub_elastic
396
+ driver.emit(sample_record)
397
+ driver.run
398
+ assert_equal(index_cmds[0]['index']['_parent'], 'parent')
399
+ end
400
+
401
+ def test_doesnt_add_parent_key_if_missing_when_configured
402
+ driver.configure("parent_key another_parent_id\n")
403
+ stub_elastic_ping
404
+ stub_elastic
405
+ driver.emit(sample_record)
406
+ driver.run
407
+ assert(!index_cmds[0]['index'].has_key?('_parent'))
408
+ end
409
+
410
+ def test_adds_parent_key_when_not_configured
411
+ stub_elastic_ping
412
+ stub_elastic
413
+ driver.emit(sample_record)
414
+ driver.run
415
+ assert(!index_cmds[0]['index'].has_key?('_parent'))
416
+ end
417
+
418
+ def test_request_error
419
+ stub_elastic_ping
420
+ stub_elastic_unavailable
421
+ driver.emit(sample_record)
422
+ assert_raise(Elasticsearch::Transport::Transport::Errors::ServiceUnavailable) {
423
+ driver.run
424
+ }
425
+ end
426
+
427
+ def test_garbage_record_error
428
+ stub_elastic_ping
429
+ stub_elastic
430
+ driver.emit("some garbage string")
431
+ driver.run
432
+ end
433
+
434
+ def test_connection_failed_retry
435
+ connection_resets = 0
436
+
437
+ stub_elastic_ping(url="http://localhost:9200").with do |req|
438
+ connection_resets += 1
439
+ end
440
+
441
+ stub_request(:post, "http://localhost:9200/_bulk").with do |req|
442
+ raise Faraday::ConnectionFailed, "Test message"
443
+ end
444
+
445
+ driver.emit(sample_record)
446
+
447
+ assert_raise(Fluent::ElasticsearchOutput::ConnectionFailure) {
448
+ driver.run
449
+ }
450
+ assert_equal(connection_resets, 3)
451
+ end
452
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-elasticsearch-check-size
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nao Akechi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.43
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.43
27
+ - !ruby/object:Gem::Dependency
28
+ name: excon
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: elasticsearch
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1'
83
+ description: ElasticSearch output plugin for Fluent event collector
84
+ email:
85
+ - nao.akechi@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .editorconfig
91
+ - .gitignore
92
+ - .travis.yml
93
+ - Gemfile
94
+ - History.md
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - fluent-plugin-elasticsearch.gemspec
99
+ - lib/fluent/plugin/out_elasticsearch.rb
100
+ - test/helper.rb
101
+ - test/plugin/test_out_elasticsearch.rb
102
+ homepage: https://github.com/nakc/fluent-plugin-elasticsearch
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.0.14
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: ElasticSearch output plugin for Fluent event collector
126
+ test_files:
127
+ - test/helper.rb
128
+ - test/plugin/test_out_elasticsearch.rb