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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +21 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +11 -0
- data/README.md +24 -0
- data/Rakefile +11 -0
- data/lib/fluent/plugin/out_falcon.rb +147 -0
- data/lib/fluent/test/falcon_output_test.rb +54 -0
- data/test/plugin/test_out_falcon.rb +320 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.travis.yml
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,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
|
data/Rakefile
ADDED
@@ -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
|