fluent-plugin-out-falcon 0.1.5

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 93262b579cc60c929f865d81171a46b4d610738d
4
+ data.tar.gz: 6d0e4885faaebce8db8a1ca12488f9f0fd426a3c
5
+ SHA512:
6
+ metadata.gz: 00d5bc6bb7e9ed15148858bc792a3aed8290cea197e7f66c8d22cfe2579667583df53e79edcbd8a3b2c7ff3b7e2e026b184ddc48f063703c8d8e51c2b1764aef
7
+ data.tar.gz: 6d8d6d3b27bc2cdbca11cd8238d127a90ecc5b14337bad1360d479e0e5bb5abb8d7bd62549b3b3a0610ce1fed8a8ec217193de2cd39bbfdc2bb811c52f664d27
@@ -0,0 +1,8 @@
1
+ *~
2
+ \#*
3
+ .\#*
4
+ *.gem
5
+ .bundle
6
+ .ruby-version
7
+ Gemfile.lock
8
+ vendor
@@ -0,0 +1,21 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1
5
+ - 2.2
6
+ - ruby-head
7
+ - rbx-2
8
+
9
+ os:
10
+ - linux
11
+ - osx
12
+
13
+ gemfile:
14
+ - Gemfile
15
+
16
+ script: bundle exec rake test
17
+
18
+ matrix:
19
+ allow_failures:
20
+ - rvm: ruby-head
21
+ - rvm: rbx-2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-out-falcon.gemspec
4
+ gemspec
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
@@ -0,0 +1,24 @@
1
+ # fluent-plugin-out-falcon, a plugin for [Fluentd](http://fluentd.org)
2
+
3
+ A [fluentd][1] output plugin for sending logs to [falcon][2]'s push api.
4
+
5
+ ## Configuration options
6
+
7
+ <match *>
8
+ type falcon
9
+ endpoint_url http://localhost.local/api/
10
+ rate_limit_msec 100 # default: 0 = no rate limiting
11
+ raise_on_error false # default: true
12
+ authentication basic # default: none
13
+ username alice # default: ''
14
+ password bobpop # default: '', secret: true
15
+ </match>
16
+
17
+
18
+ ----
19
+
20
+ Heavily based on [fluent-plugin-out-http][3]
21
+
22
+ [1]: http://fluentd.org/
23
+ [2]: http://open-falcon.org/
24
+ [3]: https://github.com/https://github.com/ento/fluent-plugin-out-http
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,147 @@
1
+ class Fluent::FalconOutput < Fluent::Output
2
+ Fluent::Plugin.register_output('falcon', self)
3
+
4
+ def initialize
5
+ super
6
+ require 'net/http'
7
+ require 'uri'
8
+ require 'yajl'
9
+ end
10
+
11
+ # Map which record field to falcon's value filed
12
+ #config_param :value_mapping, :string
13
+
14
+ # Endpoint URL ex. localhost.local/api/
15
+ config_param :endpoint_url, :string
16
+
17
+ # HTTP method
18
+ config_param :http_method, :string, :default => :post
19
+
20
+ # form | json
21
+ config_param :serializer, :string, :default => :json
22
+
23
+ # Simple rate limiting: ignore any records within `rate_limit_msec`
24
+ # since the last one.
25
+ config_param :rate_limit_msec, :integer, :default => 0
26
+
27
+ # Raise errors that were rescued during HTTP requests?
28
+ config_param :raise_on_error, :bool, :default => true
29
+
30
+ # nil | 'none' | 'basic'
31
+ config_param :authentication, :string, :default => nil
32
+ config_param :username, :string, :default => ''
33
+ config_param :password, :string, :default => '', :secret => true
34
+
35
+ def configure(conf)
36
+ super
37
+
38
+ serializers = [:json, :form]
39
+ @serializer = if serializers.include? @serializer.intern
40
+ @serializer.intern
41
+ else
42
+ :form
43
+ end
44
+
45
+ http_methods = [:get, :put, :post, :delete]
46
+ @http_method = if http_methods.include? @http_method.intern
47
+ @http_method.intern
48
+ else
49
+ :post
50
+ end
51
+
52
+ @auth = case @authentication
53
+ when 'basic' then :basic
54
+ else
55
+ :none
56
+ end
57
+ end
58
+
59
+ def start
60
+ super
61
+ end
62
+
63
+ def shutdown
64
+ super
65
+ end
66
+
67
+ def format_url(tag, time, record)
68
+ @endpoint_url
69
+ end
70
+
71
+ def set_body(req, tag, time, record)
72
+ if @serializer == :json
73
+ set_json_body(req, record)
74
+ else
75
+ req.set_form_data(record)
76
+ end
77
+ req
78
+ end
79
+
80
+ def set_header(req, tag, time, record)
81
+ req
82
+ end
83
+
84
+ def set_json_body(req, data)
85
+ # TODO remove record_modifier
86
+ #req.body = Yajl.dump([data].map do |record|
87
+ # temp = record[@value_mapping]
88
+ # data.clear
89
+ # data['value'] = temp
90
+ # data['time'] = Time.now.to_i
91
+ #end)
92
+ req.body = Yajl.dump([data])
93
+ req['Content-Type'] = 'application/json'
94
+ end
95
+
96
+ def create_request(tag, time, record)
97
+ url = format_url(tag, time, record)
98
+ uri = URI.parse(url)
99
+ req = Net::HTTP.const_get(@http_method.to_s.capitalize).new(uri.path)
100
+ set_body(req, tag, time, record)
101
+ set_header(req, tag, time, record)
102
+ return req, uri
103
+ end
104
+
105
+ def send_request(req, uri)
106
+ is_rate_limited = (@rate_limit_msec != 0 and not @last_request_time.nil?)
107
+ if is_rate_limited and ((Time.now.to_f - @last_request_time) * 1000.0 < @rate_limit_msec)
108
+ $log.info('Dropped request due to rate limiting')
109
+ return
110
+ end
111
+
112
+ res = nil
113
+
114
+ begin
115
+ if @auth and @auth == :basic
116
+ req.basic_auth(@username, @password)
117
+ end
118
+ @last_request_time = Time.now.to_f
119
+ res = Net::HTTP.new(uri.host, uri.port).start {|http| http.request(req) }
120
+ rescue => e # rescue all StandardErrors
121
+ # server didn't respond
122
+ $log.warn "Net::HTTP.#{req.method.capitalize} raises exception: #{e.class}, '#{e.message}'"
123
+ raise e if @raise_on_error
124
+ else
125
+ unless res and res.is_a?(Net::HTTPSuccess)
126
+ res_summary = if res
127
+ "#{res.code} #{res.message} #{res.body}"
128
+ else
129
+ "res=nil"
130
+ end
131
+ $log.warn "failed to #{req.method} #{uri} (#{res_summary})"
132
+ end #end unless
133
+ end # end begin
134
+ end # end send_request
135
+
136
+ def handle_record(tag, time, record)
137
+ req, uri = create_request(tag, time, record)
138
+ send_request(req, uri)
139
+ end
140
+
141
+ def emit(tag, es, chain)
142
+ es.each do |time, record|
143
+ handle_record(tag, time, record)
144
+ end
145
+ chain.next
146
+ end
147
+ end
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+
17
+ require 'fluent/test'
18
+
19
+ unless ENV.has_key?('VERBOSE')
20
+ nulllogger = Object.new
21
+ nulllogger.instance_eval {|obj|
22
+ def method_missing(method, *args)
23
+ # pass
24
+ end
25
+ }
26
+ $log = nulllogger
27
+ end
28
+
29
+ class Test::Unit::TestCase
30
+ end
31
+
32
+ require 'webrick'
33
+
34
+ # to handle POST/PUT/DELETE ...
35
+ module WEBrick::HTTPServlet
36
+ class ProcHandler < AbstractServlet
37
+ alias do_POST do_GET
38
+ alias do_PUT do_GET
39
+ alias do_DELETE do_GET
40
+ end
41
+ end
42
+
43
+ def get_code(server, port, path, headers={})
44
+ require 'net/http'
45
+ Net::HTTP.start(server, port){|http|
46
+ http.get(path, headers).code
47
+ }
48
+ end
49
+ def get_content(server, port, path, headers={})
50
+ require 'net/http'
51
+ Net::HTTP.start(server, port){|http|
52
+ http.get(path, headers).body
53
+ }
54
+ end
@@ -0,0 +1,320 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'uri'
3
+ require 'yajl'
4
+ require 'fluent/test/falcon_output_test'
5
+ require 'fluent/plugin/out_falcon'
6
+
7
+
8
+ TEST_LISTEN_PORT = 5126
9
+
10
+
11
+ class FalconOutputTestBase < Test::Unit::TestCase
12
+ # setup / teardown for servers
13
+ def setup
14
+ Fluent::Test.setup
15
+ @posts = []
16
+ @puts = []
17
+ @prohibited = 0
18
+ @requests = 0
19
+ @auth = false
20
+ @dummy_server_thread = Thread.new do
21
+ srv = if ENV['VERBOSE']
22
+ WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => TEST_LISTEN_PORT})
23
+ else
24
+ logger = WEBrick::Log.new('/dev/null', WEBrick::BasicLog::DEBUG)
25
+ WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => TEST_LISTEN_PORT, :Logger => logger, :AccessLog => []})
26
+ end
27
+ begin
28
+ allowed_methods = %w(POST PUT)
29
+ srv.mount_proc('/api/') { |req,res|
30
+ @requests += 1
31
+ unless allowed_methods.include? req.request_method
32
+ res.status = 405
33
+ res.body = 'request method mismatch'
34
+ next
35
+ end
36
+ if @auth and req.header['authorization'][0] == 'Basic YWxpY2U6c2VjcmV0IQ==' # pattern of user='alice' passwd='secret!'
37
+ # ok, authorized
38
+ elsif @auth
39
+ res.status = 403
40
+ @prohibited += 1
41
+ next
42
+ else
43
+ # ok, authorization not required
44
+ end
45
+
46
+ record = {:auth => nil}
47
+ if req.content_type == 'application/json'
48
+ record[:json] = Yajl.load(req.body)
49
+ else
50
+ record[:form] = Hash[*(req.body.split('&').map{|kv|kv.split('=')}.flatten)]
51
+ end
52
+
53
+ instance_variable_get("@#{req.request_method.downcase}s").push(record)
54
+
55
+ res.status = 200
56
+ }
57
+ srv.mount_proc('/') { |req,res|
58
+ res.status = 200
59
+ res.body = 'running'
60
+ }
61
+ srv.start
62
+ ensure
63
+ srv.shutdown
64
+ end
65
+ end
66
+
67
+ # to wait completion of dummy server.start()
68
+ require 'thread'
69
+ cv = ConditionVariable.new
70
+ watcher = Thread.new {
71
+ connected = false
72
+ while not connected
73
+ begin
74
+ get_content('localhost', TEST_LISTEN_PORT, '/')
75
+ connected = true
76
+ rescue Errno::ECONNREFUSED
77
+ sleep 0.1
78
+ rescue StandardError => e
79
+ p e
80
+ sleep 0.1
81
+ end
82
+ end
83
+ cv.signal
84
+ }
85
+ mutex = Mutex.new
86
+ mutex.synchronize {
87
+ cv.wait(mutex)
88
+ }
89
+ end
90
+
91
+ def test_dummy_server
92
+ host = '127.0.0.1'
93
+ port = TEST_LISTEN_PORT
94
+ client = Net::HTTP.start(host, port)
95
+
96
+ assert_equal '200', client.request_get('/').code
97
+ assert_equal '200', client.request_post('/api/service/metrics/hoge', 'number=1&mode=gauge').code
98
+
99
+ assert_equal 1, @posts.size
100
+
101
+ assert_equal '1', @posts[0][:form]['number']
102
+ assert_equal 'gauge', @posts[0][:form]['mode']
103
+ assert_nil @posts[0][:auth]
104
+
105
+ @auth = true
106
+
107
+ assert_equal '403', client.request_post('/api/service/metrics/pos', 'number=30&mode=gauge').code
108
+
109
+ req_with_auth = lambda do |number, mode, user, pass|
110
+ url = URI.parse("http://#{host}:#{port}/api/service/metrics/pos")
111
+ req = Net::HTTP::Post.new(url.path)
112
+ req.basic_auth user, pass
113
+ req.set_form_data({'number'=>number, 'mode'=>mode})
114
+ req
115
+ end
116
+
117
+ assert_equal '403', client.request(req_with_auth.call(500, 'count', 'alice', 'wrong password!')).code
118
+
119
+ assert_equal '403', client.request(req_with_auth.call(500, 'count', 'alice', 'wrong password!')).code
120
+
121
+ assert_equal 1, @posts.size
122
+
123
+ assert_equal '200', client.request(req_with_auth.call(500, 'count', 'alice', 'secret!')).code
124
+
125
+ assert_equal 2, @posts.size
126
+
127
+ end
128
+
129
+ def teardown
130
+ @dummy_server_thread.kill
131
+ @dummy_server_thread.join
132
+ end
133
+ end
134
+
135
+ class FalconOutputTest < FalconOutputTestBase
136
+ CONFIG_FORM = %[
137
+ endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
138
+ serializer form
139
+ ]
140
+
141
+ CONFIG_JSON = %[
142
+ endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
143
+ serializer json
144
+ ]
145
+
146
+ CONFIG_PUT = %[
147
+ endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
148
+ serializer form
149
+ http_method put
150
+ ]
151
+
152
+ CONFIG_HTTP_ERROR = %[
153
+ endpoint_url https://127.0.0.1:#{TEST_LISTEN_PORT + 1}/api/
154
+ serializer form
155
+ ]
156
+
157
+ CONFIG_HTTP_ERROR_SUPPRESSED = %[
158
+ endpoint_url https://127.0.0.1:#{TEST_LISTEN_PORT + 1}/api/
159
+ serializer form
160
+ raise_on_error false
161
+ ]
162
+
163
+ RATE_LIMIT_MSEC = 1200
164
+
165
+ CONFIG_RATE_LIMIT = %[
166
+ endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
167
+ serializer form
168
+ rate_limit_msec #{RATE_LIMIT_MSEC}
169
+ ]
170
+
171
+ def create_driver(conf=CONFIG_FORM, tag='test.metrics')
172
+ Fluent::Test::OutputTestDriver.new(Fluent::FalconOutput, tag).configure(conf)
173
+ end
174
+
175
+ def test_configure
176
+ d = create_driver
177
+ assert_equal "http://127.0.0.1:#{TEST_LISTEN_PORT}/api/", d.instance.endpoint_url
178
+ assert_equal :form, d.instance.serializer
179
+
180
+ d = create_driver CONFIG_JSON
181
+ assert_equal "http://127.0.0.1:#{TEST_LISTEN_PORT}/api/", d.instance.endpoint_url
182
+ assert_equal :json, d.instance.serializer
183
+ end
184
+
185
+ def test_emit_form
186
+ d = create_driver
187
+ d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1, 'binary' => "\xe3\x81\x82".force_encoding("ascii-8bit") })
188
+ d.run
189
+
190
+ assert_equal 1, @posts.size
191
+ record = @posts[0]
192
+
193
+ assert_equal '50', record[:form]['field1']
194
+ assert_equal '20', record[:form]['field2']
195
+ assert_equal '10', record[:form]['field3']
196
+ assert_equal '1', record[:form]['otherfield']
197
+ assert_equal URI.encode_www_form_component("あ").upcase, record[:form]['binary'].upcase
198
+ assert_nil record[:auth]
199
+
200
+ d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
201
+ d.run
202
+
203
+ assert_equal 2, @posts.size
204
+ end
205
+
206
+ def test_emit_form_put
207
+ d = create_driver CONFIG_PUT
208
+ d.emit({ 'field1' => 50 })
209
+ d.run
210
+
211
+ assert_equal 0, @posts.size
212
+ assert_equal 1, @puts.size
213
+ record = @puts[0]
214
+
215
+ assert_equal '50', record[:form]['field1']
216
+ assert_nil record[:auth]
217
+
218
+ d.emit({ 'field1' => 50 })
219
+ d.run
220
+
221
+ assert_equal 0, @posts.size
222
+ assert_equal 2, @puts.size
223
+ end
224
+
225
+ def test_emit_json
226
+ binary_string = "\xe3\x81\x82".force_encoding("ascii-8bit")
227
+ d = create_driver CONFIG_JSON
228
+ d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1, 'binary' => binary_string })
229
+ d.run
230
+
231
+ assert_equal 1, @posts.size
232
+ record = @posts[0]
233
+
234
+ assert_equal 50, record[:json][0]['field1']
235
+ assert_equal 20, record[:json][0]['field2']
236
+ assert_equal 10, record[:json][0]['field3']
237
+ assert_equal 1, record[:json][0]['otherfield']
238
+ assert_equal binary_string, record[:json][0]['binary'].force_encoding("ascii-8bit")
239
+ assert_nil record[:auth]
240
+ end
241
+
242
+ def test_http_error_is_raised
243
+ d = create_driver CONFIG_HTTP_ERROR
244
+ assert_raise Errno::ECONNREFUSED do
245
+ d.emit({ 'field1' => 50 })
246
+ end
247
+ end
248
+
249
+ def test_http_error_is_suppressed_with_raise_on_error_false
250
+ d = create_driver CONFIG_HTTP_ERROR_SUPPRESSED
251
+ d.emit({ 'field1' => 50 })
252
+ d.run
253
+ # drive asserts the next output chain is called;
254
+ # so no exception means our plugin handled the error
255
+
256
+ assert_equal 0, @requests
257
+ end
258
+
259
+ def test_rate_limiting
260
+ d = create_driver CONFIG_RATE_LIMIT
261
+ record = { :k => 1 }
262
+
263
+ last_emit = _current_msec
264
+ d.emit(record)
265
+ d.run
266
+
267
+ assert_equal 1, @posts.size
268
+
269
+ d.emit({})
270
+ d.run
271
+ assert last_emit + RATE_LIMIT_MSEC > _current_msec, "Still under rate limiting interval"
272
+ assert_equal 1, @posts.size
273
+
274
+ wait_msec = 500
275
+ sleep (last_emit + RATE_LIMIT_MSEC - _current_msec + wait_msec) * 0.001
276
+
277
+ assert last_emit + RATE_LIMIT_MSEC < _current_msec, "No longer under rate limiting interval"
278
+ d.emit(record)
279
+ d.run
280
+ assert_equal 2, @posts.size
281
+ end
282
+
283
+ def _current_msec
284
+ Time.now.to_f * 1000
285
+ end
286
+
287
+ def test_auth
288
+ @auth = true # enable authentication of dummy server
289
+
290
+ d = create_driver(CONFIG_FORM, 'test.metrics')
291
+ d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
292
+ d.run # failed in background, and output warn log
293
+
294
+ assert_equal 0, @posts.size
295
+ assert_equal 1, @prohibited
296
+
297
+ d = create_driver(CONFIG_FORM + %[
298
+ authentication basic
299
+ username alice
300
+ password wrong_password
301
+ ], 'test.metrics')
302
+ d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
303
+ d.run # failed in background, and output warn log
304
+
305
+ assert_equal 0, @posts.size
306
+ assert_equal 2, @prohibited
307
+
308
+ d = create_driver(CONFIG_FORM + %[
309
+ authentication basic
310
+ username alice
311
+ password secret!
312
+ ], 'test.metrics')
313
+ d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
314
+ d.run # failed in background, and output warn log
315
+
316
+ assert_equal 1, @posts.size
317
+ assert_equal 2, @prohibited
318
+ end
319
+
320
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-out-falcon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Marica Odagaki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: yajl-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fluentd
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.10.0
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '2'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.10.0
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: test-unit
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 3.1.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.1.0
89
+ description: A Fluentd output plugin to send logs to falcon's push api
90
+ email:
91
+ - ento.entotto@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - ".gitignore"
97
+ - ".travis.yml"
98
+ - Gemfile
99
+ - LICENSE.txt
100
+ - README.md
101
+ - Rakefile
102
+ - lib/fluent/plugin/out_falcon.rb
103
+ - lib/fluent/test/falcon_output_test.rb
104
+ - test/plugin/test_out_falcon.rb
105
+ homepage: https://github.com/tsingakbar/fluent-plugin-out-falcon
106
+ licenses:
107
+ - Apache-2.0
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.5.1
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: A Fluentd output plugin to send logs to falcon's push api
129
+ test_files:
130
+ - test/plugin/test_out_falcon.rb