fluent-plugin-out-http 0.1.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.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +11 -0
- data/README.md +23 -0
- data/Rakefile +11 -0
- data/fluent-plugin-out-http.gemspec +21 -0
- data/lib/fluent/plugin/out_http.rb +127 -0
- data/lib/fluent/test/http_output_test.rb +54 -0
- data/test/plugin/test_out_http.rb +281 -0
- metadata +101 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# fluent-plugin-out-http
|
2
|
+
|
3
|
+
A generic [fluentd][1] output plugin for sending logs to an HTTP endpoint.
|
4
|
+
|
5
|
+
## Configs
|
6
|
+
|
7
|
+
<match *>
|
8
|
+
type http
|
9
|
+
endpoint_url http://localhost.local/api/
|
10
|
+
http_method put
|
11
|
+
serializer json
|
12
|
+
rate_limit_msec 100
|
13
|
+
authentication basic
|
14
|
+
username alice
|
15
|
+
password bobpop
|
16
|
+
</match>
|
17
|
+
|
18
|
+
----
|
19
|
+
|
20
|
+
Heavily based on [fluent-plugin-growthforecast][2]
|
21
|
+
|
22
|
+
[1]: http://fluentd.org/
|
23
|
+
[2]: https://github.com/tagomoris/fluent-plugin-growthforecast
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "fluent-plugin-out-http"
|
5
|
+
gem.version = "0.1.0"
|
6
|
+
gem.authors = ["Marica Odagaki"]
|
7
|
+
gem.email = ["ento.entotto@gmail.com"]
|
8
|
+
gem.summary = %q{A generic Fluentd output plugin to send logs to an HTTP endpoint}
|
9
|
+
gem.description = gem.summary
|
10
|
+
gem.homepage = "https://github.com/ento/fluent-plugin-out-http"
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
|
17
|
+
gem.add_development_dependency "bundler"
|
18
|
+
gem.add_development_dependency "json"
|
19
|
+
gem.add_development_dependency "fluentd"
|
20
|
+
gem.add_runtime_dependency "fluentd"
|
21
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
class Fluent::HTTPOutput < Fluent::Output
|
4
|
+
Fluent::Plugin.register_output('http', self)
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
require 'net/http'
|
9
|
+
require 'uri'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Endpoint URL ex. localhost.local/api/
|
13
|
+
config_param :endpoint_url, :string
|
14
|
+
|
15
|
+
# HTTP method
|
16
|
+
config_param :http_method, :string, :default => :post
|
17
|
+
|
18
|
+
# form | json
|
19
|
+
config_param :serializer, :string, :default => :form
|
20
|
+
|
21
|
+
# Simple rate limiting: ignore any records within `rate_limit_msec`
|
22
|
+
# since the last one.
|
23
|
+
config_param :rate_limit_msec, :integer, :default => 0
|
24
|
+
|
25
|
+
# nil | 'none' | 'basic'
|
26
|
+
config_param :authentication, :string, :default => nil
|
27
|
+
config_param :username, :string, :default => ''
|
28
|
+
config_param :password, :string, :default => ''
|
29
|
+
|
30
|
+
def configure(conf)
|
31
|
+
super
|
32
|
+
|
33
|
+
serializers = [:json, :form]
|
34
|
+
@serializer = if serializers.include? @serializer.intern
|
35
|
+
@serializer.intern
|
36
|
+
else
|
37
|
+
:form
|
38
|
+
end
|
39
|
+
|
40
|
+
http_methods = [:get, :put, :post, :delete]
|
41
|
+
@http_method = if http_methods.include? @http_method.intern
|
42
|
+
@http_method.intern
|
43
|
+
else
|
44
|
+
:post
|
45
|
+
end
|
46
|
+
|
47
|
+
@auth = case @authentication
|
48
|
+
when 'basic' then :basic
|
49
|
+
else
|
50
|
+
:none
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def start
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
58
|
+
def shutdown
|
59
|
+
super
|
60
|
+
end
|
61
|
+
|
62
|
+
def format_url(tag, time, record)
|
63
|
+
@endpoint_url
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_body(req, tag, time, record)
|
67
|
+
if @serializer == :json
|
68
|
+
set_json_body(req, record)
|
69
|
+
else
|
70
|
+
req.set_form_data(record)
|
71
|
+
end
|
72
|
+
req
|
73
|
+
end
|
74
|
+
|
75
|
+
def set_header(req, tag, time, record)
|
76
|
+
req
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_json_body(req, data)
|
80
|
+
req.body = JSON.dump(data)
|
81
|
+
req['Content-Type'] = 'application/json'
|
82
|
+
end
|
83
|
+
|
84
|
+
def create_request(tag, time, record)
|
85
|
+
url = format_url(tag, time, record)
|
86
|
+
uri = URI.parse(url)
|
87
|
+
req = Net::HTTP.const_get(@http_method.to_s.capitalize).new(uri.path)
|
88
|
+
set_body(req, tag, time, record)
|
89
|
+
set_header(req, tag, time, record)
|
90
|
+
return req, uri
|
91
|
+
end
|
92
|
+
|
93
|
+
def send_request(req, uri)
|
94
|
+
is_rate_limited = (@rate_limit_msec != 0 and not @last_request_time.nil?)
|
95
|
+
if is_rate_limited and ((Time.now.to_f - @last_request_time) * 1000.0 < @rate_limit_msec)
|
96
|
+
$log.info('Dropped request due to rate limiting')
|
97
|
+
return
|
98
|
+
end
|
99
|
+
|
100
|
+
res = nil
|
101
|
+
begin
|
102
|
+
if @auth and @auth == :basic
|
103
|
+
req.basic_auth(@username, @password)
|
104
|
+
end
|
105
|
+
@last_request_time = Time.now.to_f
|
106
|
+
res = Net::HTTP.new(uri.host, uri.port).start {|http| http.request(req) }
|
107
|
+
rescue IOError, EOFError, SystemCallError
|
108
|
+
# server didn't respond
|
109
|
+
$log.warn "Net::HTTP.#{req.method.capitalize} raises exception: #{$!.class}, '#{$!.message}'"
|
110
|
+
end
|
111
|
+
unless res and res.is_a?(Net::HTTPSuccess)
|
112
|
+
$log.warn "failed to #{req.method} #{uri} (#{res.code} #{res.message} #{res.body})"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def handle_record(tag, time, record)
|
117
|
+
req, uri = create_request(tag, time, record)
|
118
|
+
send_request(req, uri)
|
119
|
+
end
|
120
|
+
|
121
|
+
def emit(tag, es, chain)
|
122
|
+
es.each do |time, record|
|
123
|
+
handle_record(tag, time, record)
|
124
|
+
end
|
125
|
+
chain.next
|
126
|
+
end
|
127
|
+
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,281 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'fluent/test/http_output_test'
|
3
|
+
require 'fluent/plugin/out_http'
|
4
|
+
|
5
|
+
|
6
|
+
TEST_LISTEN_PORT = 5126
|
7
|
+
|
8
|
+
|
9
|
+
class HTTPOutputTestBase < Test::Unit::TestCase
|
10
|
+
# setup / teardown for servers
|
11
|
+
def setup
|
12
|
+
Fluent::Test.setup
|
13
|
+
@posts = []
|
14
|
+
@puts = []
|
15
|
+
@prohibited = 0
|
16
|
+
@auth = false
|
17
|
+
@dummy_server_thread = Thread.new do
|
18
|
+
srv = if ENV['VERBOSE']
|
19
|
+
WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => TEST_LISTEN_PORT})
|
20
|
+
else
|
21
|
+
logger = WEBrick::Log.new('/dev/null', WEBrick::BasicLog::DEBUG)
|
22
|
+
WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => TEST_LISTEN_PORT, :Logger => logger, :AccessLog => []})
|
23
|
+
end
|
24
|
+
begin
|
25
|
+
allowed_methods = %w(POST PUT)
|
26
|
+
srv.mount_proc('/api/') { |req,res|
|
27
|
+
unless allowed_methods.include? req.request_method
|
28
|
+
res.status = 405
|
29
|
+
res.body = 'request method mismatch'
|
30
|
+
next
|
31
|
+
end
|
32
|
+
if @auth and req.header['authorization'][0] == 'Basic YWxpY2U6c2VjcmV0IQ==' # pattern of user='alice' passwd='secret!'
|
33
|
+
# ok, authorized
|
34
|
+
elsif @auth
|
35
|
+
res.status = 403
|
36
|
+
@prohibited += 1
|
37
|
+
next
|
38
|
+
else
|
39
|
+
# ok, authorization not required
|
40
|
+
end
|
41
|
+
|
42
|
+
record = {:auth => nil}
|
43
|
+
if req.content_type == 'application/json'
|
44
|
+
record[:json] = JSON.parse(req.body)
|
45
|
+
else
|
46
|
+
record[:form] = Hash[*(req.body.split('&').map{|kv|kv.split('=')}.flatten)]
|
47
|
+
end
|
48
|
+
|
49
|
+
instance_variable_get("@#{req.request_method.downcase}s").push(record)
|
50
|
+
|
51
|
+
res.status = 200
|
52
|
+
}
|
53
|
+
srv.mount_proc('/') { |req,res|
|
54
|
+
res.status = 200
|
55
|
+
res.body = 'running'
|
56
|
+
}
|
57
|
+
srv.start
|
58
|
+
ensure
|
59
|
+
srv.shutdown
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# to wait completion of dummy server.start()
|
64
|
+
require 'thread'
|
65
|
+
cv = ConditionVariable.new
|
66
|
+
watcher = Thread.new {
|
67
|
+
connected = false
|
68
|
+
while not connected
|
69
|
+
begin
|
70
|
+
get_content('localhost', TEST_LISTEN_PORT, '/')
|
71
|
+
connected = true
|
72
|
+
rescue Errno::ECONNREFUSED
|
73
|
+
sleep 0.1
|
74
|
+
rescue StandardError => e
|
75
|
+
p e
|
76
|
+
sleep 0.1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
cv.signal
|
80
|
+
}
|
81
|
+
mutex = Mutex.new
|
82
|
+
mutex.synchronize {
|
83
|
+
cv.wait(mutex)
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_dummy_server
|
88
|
+
host = '127.0.0.1'
|
89
|
+
port = TEST_LISTEN_PORT
|
90
|
+
client = Net::HTTP.start(host, port)
|
91
|
+
|
92
|
+
assert_equal '200', client.request_get('/').code
|
93
|
+
assert_equal '200', client.request_post('/api/service/metrics/hoge', 'number=1&mode=gauge').code
|
94
|
+
|
95
|
+
assert_equal 1, @posts.size
|
96
|
+
|
97
|
+
assert_equal '1', @posts[0][:form]['number']
|
98
|
+
assert_equal 'gauge', @posts[0][:form]['mode']
|
99
|
+
assert_nil @posts[0][:auth]
|
100
|
+
|
101
|
+
@auth = true
|
102
|
+
|
103
|
+
assert_equal '403', client.request_post('/api/service/metrics/pos', 'number=30&mode=gauge').code
|
104
|
+
|
105
|
+
req_with_auth = lambda do |number, mode, user, pass|
|
106
|
+
url = URI.parse("http://#{host}:#{port}/api/service/metrics/pos")
|
107
|
+
req = Net::HTTP::Post.new(url.path)
|
108
|
+
req.basic_auth user, pass
|
109
|
+
req.set_form_data({'number'=>number, 'mode'=>mode})
|
110
|
+
req
|
111
|
+
end
|
112
|
+
|
113
|
+
assert_equal '403', client.request(req_with_auth.call(500, 'count', 'alice', 'wrong password!')).code
|
114
|
+
|
115
|
+
assert_equal '403', client.request(req_with_auth.call(500, 'count', 'alice', 'wrong password!')).code
|
116
|
+
|
117
|
+
assert_equal 1, @posts.size
|
118
|
+
|
119
|
+
assert_equal '200', client.request(req_with_auth.call(500, 'count', 'alice', 'secret!')).code
|
120
|
+
|
121
|
+
assert_equal 2, @posts.size
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
def teardown
|
126
|
+
@dummy_server_thread.kill
|
127
|
+
@dummy_server_thread.join
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class HTTPOutputTest < HTTPOutputTestBase
|
132
|
+
CONFIG = %[
|
133
|
+
endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
|
134
|
+
]
|
135
|
+
|
136
|
+
CONFIG_JSON = %[
|
137
|
+
endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
|
138
|
+
serializer json
|
139
|
+
]
|
140
|
+
|
141
|
+
CONFIG_PUT = %[
|
142
|
+
endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
|
143
|
+
http_method put
|
144
|
+
]
|
145
|
+
|
146
|
+
RATE_LIMIT_MSEC = 1200
|
147
|
+
|
148
|
+
CONFIG_RATE_LIMIT = %[
|
149
|
+
endpoint_url http://127.0.0.1:#{TEST_LISTEN_PORT}/api/
|
150
|
+
rate_limit_msec #{RATE_LIMIT_MSEC}
|
151
|
+
]
|
152
|
+
|
153
|
+
def create_driver(conf=CONFIG, tag='test.metrics')
|
154
|
+
Fluent::Test::OutputTestDriver.new(Fluent::HTTPOutput, tag).configure(conf)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_configure
|
158
|
+
d = create_driver
|
159
|
+
assert_equal "http://127.0.0.1:#{TEST_LISTEN_PORT}/api/", d.instance.endpoint_url
|
160
|
+
assert_equal :form, d.instance.serializer
|
161
|
+
|
162
|
+
d = create_driver CONFIG_JSON
|
163
|
+
assert_equal "http://127.0.0.1:#{TEST_LISTEN_PORT}/api/", d.instance.endpoint_url
|
164
|
+
assert_equal :json, d.instance.serializer
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_emit_form
|
168
|
+
d = create_driver
|
169
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
170
|
+
d.run
|
171
|
+
|
172
|
+
assert_equal 1, @posts.size
|
173
|
+
record = @posts[0]
|
174
|
+
|
175
|
+
assert_equal '50', record[:form]['field1']
|
176
|
+
assert_equal '20', record[:form]['field2']
|
177
|
+
assert_equal '10', record[:form]['field3']
|
178
|
+
assert_equal '1', record[:form]['otherfield']
|
179
|
+
assert_nil record[:auth]
|
180
|
+
|
181
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
182
|
+
d.run
|
183
|
+
|
184
|
+
assert_equal 2, @posts.size
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_emit_form_put
|
188
|
+
d = create_driver CONFIG_PUT
|
189
|
+
d.emit({ 'field1' => 50 })
|
190
|
+
d.run
|
191
|
+
|
192
|
+
assert_equal 0, @posts.size
|
193
|
+
assert_equal 1, @puts.size
|
194
|
+
record = @puts[0]
|
195
|
+
|
196
|
+
assert_equal '50', record[:form]['field1']
|
197
|
+
assert_nil record[:auth]
|
198
|
+
|
199
|
+
d.emit({ 'field1' => 50 })
|
200
|
+
d.run
|
201
|
+
|
202
|
+
assert_equal 0, @posts.size
|
203
|
+
assert_equal 2, @puts.size
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_emit_json
|
207
|
+
d = create_driver CONFIG_JSON
|
208
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
209
|
+
d.run
|
210
|
+
|
211
|
+
assert_equal 1, @posts.size
|
212
|
+
record = @posts[0]
|
213
|
+
|
214
|
+
assert_equal 50, record[:json]['field1']
|
215
|
+
assert_equal 20, record[:json]['field2']
|
216
|
+
assert_equal 10, record[:json]['field3']
|
217
|
+
assert_equal 1, record[:json]['otherfield']
|
218
|
+
assert_nil record[:auth]
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_rate_limiting
|
222
|
+
d = create_driver CONFIG_RATE_LIMIT
|
223
|
+
record = { :k => 1 }
|
224
|
+
|
225
|
+
last_emit = _current_msec
|
226
|
+
d.emit(record)
|
227
|
+
d.run
|
228
|
+
|
229
|
+
assert_equal 1, @posts.size
|
230
|
+
|
231
|
+
d.emit({})
|
232
|
+
d.run
|
233
|
+
assert last_emit + RATE_LIMIT_MSEC > _current_msec, "Still under rate limiting interval"
|
234
|
+
assert_equal 1, @posts.size
|
235
|
+
|
236
|
+
sleep (last_emit + RATE_LIMIT_MSEC - _current_msec) * 0.001
|
237
|
+
|
238
|
+
assert last_emit + RATE_LIMIT_MSEC < _current_msec, "No longer under rate limiting interval"
|
239
|
+
d.emit(record)
|
240
|
+
d.run
|
241
|
+
assert_equal 2, @posts.size
|
242
|
+
end
|
243
|
+
|
244
|
+
def _current_msec
|
245
|
+
Time.now.to_f * 1000
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_auth
|
249
|
+
@auth = true # enable authentication of dummy server
|
250
|
+
|
251
|
+
d = create_driver(CONFIG, 'test.metrics')
|
252
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
253
|
+
d.run # failed in background, and output warn log
|
254
|
+
|
255
|
+
assert_equal 0, @posts.size
|
256
|
+
assert_equal 1, @prohibited
|
257
|
+
|
258
|
+
d = create_driver(CONFIG + %[
|
259
|
+
authentication basic
|
260
|
+
username alice
|
261
|
+
password wrong_password
|
262
|
+
], 'test.metrics')
|
263
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
264
|
+
d.run # failed in background, and output warn log
|
265
|
+
|
266
|
+
assert_equal 0, @posts.size
|
267
|
+
assert_equal 2, @prohibited
|
268
|
+
|
269
|
+
d = create_driver(CONFIG + %[
|
270
|
+
authentication basic
|
271
|
+
username alice
|
272
|
+
password secret!
|
273
|
+
], 'test.metrics')
|
274
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
275
|
+
d.run # failed in background, and output warn log
|
276
|
+
|
277
|
+
assert_equal 1, @posts.size
|
278
|
+
assert_equal 2, @prohibited
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-out-http
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marica Odagaki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-14 00:00:00.000000000 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bundler
|
17
|
+
requirement: &70205234747520 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70205234747520
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: json
|
28
|
+
requirement: &70205234747080 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70205234747080
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: fluentd
|
39
|
+
requirement: &70205234746660 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70205234746660
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: fluentd
|
50
|
+
requirement: &70205234746240 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70205234746240
|
59
|
+
description: A generic Fluentd output plugin to send logs to an HTTP endpoint
|
60
|
+
email:
|
61
|
+
- ento.entotto@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- fluent-plugin-out-http.gemspec
|
72
|
+
- lib/fluent/plugin/out_http.rb
|
73
|
+
- lib/fluent/test/http_output_test.rb
|
74
|
+
- test/plugin/test_out_http.rb
|
75
|
+
has_rdoc: true
|
76
|
+
homepage: https://github.com/ento/fluent-plugin-out-http
|
77
|
+
licenses: []
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.6.2
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: A generic Fluentd output plugin to send logs to an HTTP endpoint
|
100
|
+
test_files:
|
101
|
+
- test/plugin/test_out_http.rb
|