fluent-plugin-growthforecast 0.1.6 → 0.2.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.
- checksums.yaml +7 -0
- data/README.md +11 -0
- data/fluent-plugin-growthforecast.gemspec +1 -1
- data/lib/fluent/plugin/out_growthforecast.rb +68 -16
- data/test/plugin/test_out_growthforecast.rb +44 -3
- metadata +13 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ec668da8275088e03eff43e7a2af96f2f36d367f
|
4
|
+
data.tar.gz: 772aa71eec3488cbd39e938da961849345c6e2ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3283857ee36842f64a8af77b75486caf5f93827d452b8d912d0e1f829a4d7517d694f441914a69d8b2faa916bfa5d27d3ecfffab7fd743ecd1fadbacce69ae10
|
7
|
+
data.tar.gz: ce10e80a9991f8aba61a65e56dceb6156ed44c0c399ee08c483f4c31ab8684b0acbaef96bbff35015b7ccda3e28eab6387116654c0b94b9d65894ac1093519f9
|
data/README.md
CHANGED
@@ -71,6 +71,17 @@ If your GrowthForecast protected with basic authentication, specify `authenticat
|
|
71
71
|
password secret!
|
72
72
|
</match>
|
73
73
|
|
74
|
+
Version v0.2.0 or later, this plugin uses HTTP connection keep-alive for a batch emitted events. To disable this, specify `keepalive` option:
|
75
|
+
|
76
|
+
<match metrics.**>
|
77
|
+
type growthforecast
|
78
|
+
gfapi_url http://growthforecast.protected.anywhere.example.com/api/
|
79
|
+
service yourservice
|
80
|
+
tag_for section
|
81
|
+
name_keys fieldname
|
82
|
+
keepalive no
|
83
|
+
</match>
|
84
|
+
|
74
85
|
## TODO
|
75
86
|
|
76
87
|
* patches welcome!
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.name = "fluent-plugin-growthforecast"
|
5
|
-
gem.version = "0.
|
5
|
+
gem.version = "0.2.0"
|
6
6
|
gem.authors = ["TAGOMORI Satoshi"]
|
7
7
|
gem.email = ["tagomoris@gmail.com"]
|
8
8
|
gem.summary = %q{Fluentd output plugin to post numbers to GrowthForecast (by kazeburo)}
|
@@ -21,7 +21,9 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
21
21
|
|
22
22
|
config_param :remove_prefix, :string, :default => nil
|
23
23
|
config_param :tag_for, :string, :default => 'name_prefix' # or 'ignore' or 'section' or 'service'
|
24
|
-
|
24
|
+
|
25
|
+
config_param :keepalive, :bool, :default => true
|
26
|
+
|
25
27
|
config_param :authentication, :string, :default => nil # nil or 'none' or 'basic'
|
26
28
|
config_param :username, :string, :default => ''
|
27
29
|
config_param :password, :string, :default => ''
|
@@ -104,23 +106,42 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
109
|
+
def connect_to(tag, name)
|
110
|
+
url = URI.parse(format_url(tag,name))
|
111
|
+
return url.host, url.port
|
112
|
+
end
|
113
|
+
|
114
|
+
def http_connection(host, port)
|
115
|
+
http = Net::HTTP.new(host, port)
|
116
|
+
if @ssl
|
117
|
+
http.use_ssl = true
|
118
|
+
unless @verify_ssl
|
119
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
120
|
+
end
|
121
|
+
end
|
122
|
+
http
|
123
|
+
end
|
124
|
+
|
125
|
+
def post_request(tag, name, value)
|
126
|
+
url = URI.parse(format_url(tag,name))
|
127
|
+
req = Net::HTTP::Post.new(url.path)
|
128
|
+
if @auth and @auth == :basic
|
129
|
+
req.basic_auth(@username, @password)
|
130
|
+
end
|
131
|
+
if @keepalive
|
132
|
+
req['Connection'] = 'Keep-Alive'
|
133
|
+
end
|
134
|
+
req.set_form_data({'number' => value.to_i, 'mode' => @mode.to_s})
|
135
|
+
req
|
136
|
+
end
|
137
|
+
|
107
138
|
def post(tag, name, value)
|
108
139
|
url = format_url(tag,name)
|
109
140
|
res = nil
|
110
141
|
begin
|
111
|
-
|
112
|
-
req =
|
113
|
-
|
114
|
-
req.basic_auth(@username, @password)
|
115
|
-
end
|
116
|
-
req.set_form_data({'number' => value.to_i, 'mode' => @mode.to_s})
|
117
|
-
http = Net::HTTP.new(url.host, url.port)
|
118
|
-
if @ssl
|
119
|
-
http.use_ssl = true
|
120
|
-
unless @verify_ssl
|
121
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
122
|
-
end
|
123
|
-
end
|
142
|
+
host,port = connect_to(tag, name)
|
143
|
+
req = post_request(tag, name, value)
|
144
|
+
http = http_connection(host, port)
|
124
145
|
res = http.start {|http| http.request(req) }
|
125
146
|
rescue IOError, EOFError, SystemCallError
|
126
147
|
# server didn't respond
|
@@ -131,12 +152,35 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
131
152
|
end
|
132
153
|
end
|
133
154
|
|
155
|
+
def post_keepalive(events) # [{:tag=>'',:name=>'',:value=>X}]
|
156
|
+
return if events.size < 1
|
157
|
+
|
158
|
+
# gf host/port is same for all events (host is from configuration)
|
159
|
+
host,port = connect_to(events.first[:tag], events.first[:name])
|
160
|
+
|
161
|
+
requests = events.map{|e| post_request(e[:tag], e[:name], e[:value])}
|
162
|
+
begin
|
163
|
+
http = http_connection(host, port)
|
164
|
+
http.start do |http|
|
165
|
+
requests.each do |req|
|
166
|
+
res = http.request(req)
|
167
|
+
unless res and res.is_a?(Net::HTTPSuccess)
|
168
|
+
$log.warn "failed to post to growthforecast: #{host}:#{port}#{req.path}, post_data: #{req.body} code: #{res && res.code}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
rescue IOError, EOFError, SystemCallError
|
173
|
+
$log.warn "Net::HTTP.post_form raises exception: #{$!.class}, '#{$!.message}'"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
134
177
|
def emit(tag, es, chain)
|
178
|
+
events = []
|
135
179
|
if @name_keys
|
136
180
|
es.each {|time,record|
|
137
181
|
@name_keys.each {|name|
|
138
182
|
if record[name]
|
139
|
-
|
183
|
+
events.push({:tag => tag, :name => name, :value => record[name]})
|
140
184
|
end
|
141
185
|
}
|
142
186
|
}
|
@@ -144,11 +188,19 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
144
188
|
es.each {|time,record|
|
145
189
|
record.keys.each {|key|
|
146
190
|
if @name_key_pattern.match(key) and record[key]
|
147
|
-
|
191
|
+
events.push({:tag => tag, :name => key, :value => record[key]})
|
148
192
|
end
|
149
193
|
}
|
150
194
|
}
|
151
195
|
end
|
196
|
+
if @keepalive
|
197
|
+
post_keepalive(events)
|
198
|
+
else
|
199
|
+
events.each do |event|
|
200
|
+
post(event[:tag], event[:name], event[:value])
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
152
204
|
chain.next
|
153
205
|
end
|
154
206
|
end
|
@@ -37,7 +37,7 @@ class GrowthForecastOutputTest < Test::Unit::TestCase
|
|
37
37
|
tag_for service
|
38
38
|
remove_prefix test
|
39
39
|
]
|
40
|
-
|
40
|
+
|
41
41
|
CONFIG_SPACE = %[
|
42
42
|
gfapi_url http://127.0.0.1:5125/api/
|
43
43
|
service service x
|
@@ -46,6 +46,15 @@ class GrowthForecastOutputTest < Test::Unit::TestCase
|
|
46
46
|
tag_for ignore
|
47
47
|
]
|
48
48
|
|
49
|
+
CONFIG_NON_KEEPALIVE = %[
|
50
|
+
gfapi_url http://127.0.0.1:5125/api/
|
51
|
+
service service
|
52
|
+
section metrics
|
53
|
+
name_keys field1,field2,otherfield
|
54
|
+
tag_for name_prefix
|
55
|
+
keepalive false
|
56
|
+
]
|
57
|
+
|
49
58
|
def create_driver(conf=CONFIG1, tag='test.metrics')
|
50
59
|
Fluent::Test::OutputTestDriver.new(Fluent::GrowthForecastOutput, tag).configure(conf)
|
51
60
|
end
|
@@ -278,6 +287,38 @@ class GrowthForecastOutputTest < Test::Unit::TestCase
|
|
278
287
|
assert_equal 'field z', v[:name]
|
279
288
|
end
|
280
289
|
|
290
|
+
# CONFIG_NON_KEEPALIVE = %[
|
291
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
292
|
+
# service service
|
293
|
+
# section metrics
|
294
|
+
# name_keys field1,field2,otherfield
|
295
|
+
# tag_for name_prefix
|
296
|
+
# keepalive false
|
297
|
+
# ]
|
298
|
+
def test_non_keepalive
|
299
|
+
d = create_driver(CONFIG_NON_KEEPALIVE, 'test.metrics')
|
300
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
301
|
+
d.run
|
302
|
+
|
303
|
+
assert_equal 3, @posted.size
|
304
|
+
v1st = @posted[0]
|
305
|
+
v2nd = @posted[1]
|
306
|
+
v3rd = @posted[2]
|
307
|
+
|
308
|
+
assert_equal 50, v1st[:data][:number]
|
309
|
+
assert_equal 'gauge', v1st[:data][:mode]
|
310
|
+
assert_nil v1st[:auth]
|
311
|
+
assert_equal 'service', v1st[:service]
|
312
|
+
assert_equal 'metrics', v1st[:section]
|
313
|
+
assert_equal 'test.metrics_field1', v1st[:name]
|
314
|
+
|
315
|
+
assert_equal 20, v2nd[:data][:number]
|
316
|
+
assert_equal 'test.metrics_field2', v2nd[:name]
|
317
|
+
|
318
|
+
assert_equal 1, v3rd[:data][:number]
|
319
|
+
assert_equal 'test.metrics_otherfield', v3rd[:name]
|
320
|
+
end
|
321
|
+
|
281
322
|
# setup / teardown for servers
|
282
323
|
def setup
|
283
324
|
Fluent::Test.setup
|
@@ -351,11 +392,11 @@ class GrowthForecastOutputTest < Test::Unit::TestCase
|
|
351
392
|
end
|
352
393
|
end
|
353
394
|
cv.signal
|
354
|
-
}
|
395
|
+
}
|
355
396
|
mutex = Mutex.new
|
356
397
|
mutex.synchronize {
|
357
398
|
cv.wait(mutex)
|
358
|
-
}
|
399
|
+
}
|
359
400
|
end
|
360
401
|
|
361
402
|
def test_dummy_server
|
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-growthforecast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- TAGOMORI Satoshi
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-05-15 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: fluentd
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: fluent-mixin-config-placeholders
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
description: For GrowthForecast, see http://kazeburo.github.com/GrowthForecast/
|
@@ -80,27 +73,26 @@ files:
|
|
80
73
|
- test/plugin/test_out_growthforecast.rb
|
81
74
|
homepage: https://github.com/tagomoris/fluent-plugin-growthforecast
|
82
75
|
licenses: []
|
76
|
+
metadata: {}
|
83
77
|
post_install_message:
|
84
78
|
rdoc_options: []
|
85
79
|
require_paths:
|
86
80
|
- lib
|
87
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
-
none: false
|
89
82
|
requirements:
|
90
|
-
- -
|
83
|
+
- - '>='
|
91
84
|
- !ruby/object:Gem::Version
|
92
85
|
version: '0'
|
93
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
-
none: false
|
95
87
|
requirements:
|
96
|
-
- -
|
88
|
+
- - '>='
|
97
89
|
- !ruby/object:Gem::Version
|
98
90
|
version: '0'
|
99
91
|
requirements: []
|
100
92
|
rubyforge_project:
|
101
|
-
rubygems_version:
|
93
|
+
rubygems_version: 2.0.0
|
102
94
|
signing_key:
|
103
|
-
specification_version:
|
95
|
+
specification_version: 4
|
104
96
|
summary: Fluentd output plugin to post numbers to GrowthForecast (by kazeburo)
|
105
97
|
test_files:
|
106
98
|
- test/helper.rb
|