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.
@@ -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