fluent-plugin-growthforecast 0.1.6 → 0.2.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: 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.1.6"
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
- url = URI.parse(url)
112
- req = Net::HTTP::Post.new(url.path)
113
- if @auth and @auth == :basic
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
- post(tag, name, record[name])
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
- post(tag, key, record[key])
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.1.6
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-04-08 00:00:00.000000000 Z
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: 1.8.23
93
+ rubygems_version: 2.0.0
102
94
  signing_key:
103
- specification_version: 3
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