fluent-plugin-growthforecast 0.1.4 → 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.
- data/Gemfile +3 -15
- data/README.md +82 -0
- data/Rakefile +2 -43
- data/fluent-plugin-growthforecast.gemspec +17 -70
- data/lib/fluent/plugin/out_growthforecast.rb +44 -13
- data/test/helper.rb +34 -1
- data/test/plugin/test_out_growthforecast.rb +417 -3
- metadata +20 -88
- data/README.rdoc +0 -59
data/Gemfile
CHANGED
@@ -1,16 +1,4 @@
|
|
1
|
-
source
|
2
|
-
# Add dependencies required to use your gem here.
|
3
|
-
# Example:
|
4
|
-
# gem "activesupport", ">= 2.3.5"
|
1
|
+
source 'https://rubygems.org'
|
5
2
|
|
6
|
-
#
|
7
|
-
|
8
|
-
group :development do
|
9
|
-
gem "shoulda", ">= 0"
|
10
|
-
gem "bundler", "~> 1.0.0"
|
11
|
-
gem "jeweler", "~> 1.6.4"
|
12
|
-
gem "simplecov", ">= 0"
|
13
|
-
end
|
14
|
-
|
15
|
-
gem "fluentd"
|
16
|
-
gem "rdoc"
|
3
|
+
# Specify your gem's dependencies in fluent-plugin-growthforecast.gemspec
|
4
|
+
gemspec
|
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# fluent-plugin-growthforecast
|
2
|
+
|
3
|
+
## GrowthForecastOutput
|
4
|
+
|
5
|
+
Plugin to output numbers(metrics) to 'GrowthForecast', metrics drawing tool over HTTP.
|
6
|
+
|
7
|
+
About GrowthForecast, see:
|
8
|
+
* Github: https://github.com/kazeburo/growthforecast
|
9
|
+
* Product site (japanese): http://kazeburo.github.com/GrowthForecast/
|
10
|
+
* Japanese blog post by @kazeburo: http://blog.nomadscafe.jp/2011/12/growthforecast.html
|
11
|
+
|
12
|
+
GrowthForecast is very simple and powerful tool to draw graphs what we want, with GrowthForecastOutput and Fluentd.
|
13
|
+
|
14
|
+
### Configuration
|
15
|
+
|
16
|
+
For messages such as:
|
17
|
+
tag:metrics {"field1":300, "field2":20, "field3diff":-30}
|
18
|
+
|
19
|
+
Configuration example for graphs in growthforecast with POST api url 'http://growthforecast.local/api/service1/metrics1/metrics_FIELDNAME'.
|
20
|
+
|
21
|
+
<match metrics>
|
22
|
+
type growthforecast
|
23
|
+
gfapi_url http://growthforecast.local/api/
|
24
|
+
service service1
|
25
|
+
section metrics1
|
26
|
+
name_keys field1,field2,field3diff
|
27
|
+
</match>
|
28
|
+
|
29
|
+
With this configuration, out_growthforecast posts urls below.
|
30
|
+
|
31
|
+
http://growthforecast.local/api/service1/metrics1/metrics_field1
|
32
|
+
http://growthforecast.local/api/service1/metrics1/metrics_field2
|
33
|
+
http://growthforecast.local/api/service1/metrics1/metrics_field3diff
|
34
|
+
|
35
|
+
If you want to use tags for `section` or `service` in GrowthForecast, use `tag_for` options and `remove_prefix` (and not to set the `section` or `service` that the value of 'tag_for' used to.).
|
36
|
+
|
37
|
+
<match metrics.**>
|
38
|
+
type growthforecast
|
39
|
+
gfapi_url http://growthforecast.local/api/
|
40
|
+
service service1
|
41
|
+
name_keys field1,field2,field3diff
|
42
|
+
tag_for section # or 'name_prefix'(default) or 'ignore' or 'service'
|
43
|
+
remove_prefix metrics
|
44
|
+
</match>
|
45
|
+
|
46
|
+
`mode` option available with `gauge`(default), `count`, `modified`, just same as `mode` of GrowthForecast POST parameter.
|
47
|
+
|
48
|
+
`name_key_pattern REGEXP` available instead of `name_keys` like this:
|
49
|
+
|
50
|
+
<match metrics.**>
|
51
|
+
type growthforecast
|
52
|
+
gfapi_url http://growthforecast.local/api/
|
53
|
+
service service1
|
54
|
+
tag_for section # or 'name_prefix'(default) or 'ignore' or 'service'
|
55
|
+
remove_prefix metrics
|
56
|
+
name_key_pattern ^(field|key)\d+$
|
57
|
+
</match>
|
58
|
+
|
59
|
+
This configuration matches only with metrics.field1, metrics.key20, .... and doesn't match with metrics.field or metrics.foo.
|
60
|
+
|
61
|
+
If your GrowthForecast protected with basic authentication, specify `authentication` option:
|
62
|
+
|
63
|
+
<match metrics.**>
|
64
|
+
type growthforecast
|
65
|
+
gfapi_url http://growthforecast.protected.anywhere.example.com/api/
|
66
|
+
service yourservice
|
67
|
+
tag_for section
|
68
|
+
name_keys fieldname
|
69
|
+
authentication basic
|
70
|
+
username yourusername
|
71
|
+
password secret!
|
72
|
+
</match>
|
73
|
+
|
74
|
+
## TODO
|
75
|
+
|
76
|
+
* patches welcome!
|
77
|
+
|
78
|
+
## Copyright
|
79
|
+
|
80
|
+
* Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
|
81
|
+
* License
|
82
|
+
* Apache License, Version 2.0
|
data/Rakefile
CHANGED
@@ -1,36 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
require 'rake'
|
13
|
-
|
14
|
-
require 'jeweler'
|
15
|
-
Jeweler::Tasks.new do |gem|
|
16
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
-
gem.name = "fluent-plugin-growthforecast"
|
18
|
-
gem.description = "Plugin to post numbers to GrowthForecast (by kazeburo)"
|
19
|
-
gem.homepage = "http://github.com/tagomoris/fluent-plugin-growthforecast"
|
20
|
-
gem.summary = gem.description
|
21
|
-
gem.email = "tagomoris@gmail.com"
|
22
|
-
gem.authors = ["TAGOMORI Satoshi"]
|
23
|
-
gem.has_rdoc = "false"
|
24
|
-
# dependencies defined in Gemfile
|
25
|
-
gem.files = `git ls-files`.split("\n")
|
26
|
-
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
27
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
28
|
-
gem.require_paths = ['lib']
|
29
|
-
gem.add_dependency "fluentd", "~> 0.10.8"
|
30
|
-
gem.add_development_dependency "rake", ">= 0.9.2"
|
31
|
-
gem.add_development_dependency "simplecov", ">= 0.5.4"
|
32
|
-
end
|
33
|
-
Jeweler::RubygemsDotOrgTasks.new
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
34
3
|
|
35
4
|
require 'rake/testtask'
|
36
5
|
Rake::TestTask.new(:test) do |test|
|
@@ -40,13 +9,3 @@ Rake::TestTask.new(:test) do |test|
|
|
40
9
|
end
|
41
10
|
|
42
11
|
task :default => :test
|
43
|
-
|
44
|
-
require 'rdoc/task'
|
45
|
-
Rake::RDocTask.new do |rdoc|
|
46
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
-
|
48
|
-
rdoc.rdoc_dir = 'rdoc'
|
49
|
-
rdoc.title = "fluent-plugin-growthforecast #{version}"
|
50
|
-
rdoc.rdoc_files.include('README*')
|
51
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
-
end
|
@@ -1,75 +1,22 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
5
2
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "fluent-plugin-growthforecast"
|
5
|
+
gem.version = "0.1.5"
|
6
|
+
gem.authors = ["TAGOMORI Satoshi"]
|
7
|
+
gem.email = ["tagomoris@gmail.com"]
|
8
|
+
gem.summary = %q{Fluentd output plugin to post numbers to GrowthForecast (by kazeburo)}
|
9
|
+
gem.description = %q{For GrowthForecast, see http://kazeburo.github.com/GrowthForecast/}
|
10
|
+
gem.homepage = "https://github.com/tagomoris/fluent-plugin-growthforecast"
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
s.email = "tagomoris@gmail.com"
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE.txt",
|
17
|
-
"README.rdoc"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".document",
|
21
|
-
".gitignore",
|
22
|
-
"AUTHORS",
|
23
|
-
"Gemfile",
|
24
|
-
"LICENSE.txt",
|
25
|
-
"README.rdoc",
|
26
|
-
"Rakefile",
|
27
|
-
"VERSION",
|
28
|
-
"fluent-plugin-growthforecast.gemspec",
|
29
|
-
"lib/fluent/plugin/out_growthforecast.rb",
|
30
|
-
"test/helper.rb",
|
31
|
-
"test/plugin/test_out_growthforecast.rb"
|
32
|
-
]
|
33
|
-
s.homepage = "http://github.com/tagomoris/fluent-plugin-growthforecast"
|
34
|
-
s.require_paths = ["lib"]
|
35
|
-
s.rubygems_version = "1.8.21"
|
36
|
-
s.summary = "Plugin to post numbers to GrowthForecast (by kazeburo)"
|
37
|
-
s.test_files = ["test/helper.rb", "test/plugin/test_out_growthforecast.rb"]
|
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"]
|
38
16
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
s.add_runtime_dependency(%q<rdoc>, [">= 0"])
|
45
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
46
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
47
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
48
|
-
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
49
|
-
s.add_runtime_dependency(%q<fluentd>, ["~> 0.10.8"])
|
50
|
-
s.add_development_dependency(%q<rake>, [">= 0.9.2"])
|
51
|
-
s.add_development_dependency(%q<simplecov>, [">= 0.5.4"])
|
52
|
-
else
|
53
|
-
s.add_dependency(%q<fluentd>, [">= 0"])
|
54
|
-
s.add_dependency(%q<rdoc>, [">= 0"])
|
55
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
56
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
57
|
-
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
58
|
-
s.add_dependency(%q<simplecov>, [">= 0"])
|
59
|
-
s.add_dependency(%q<fluentd>, ["~> 0.10.8"])
|
60
|
-
s.add_dependency(%q<rake>, [">= 0.9.2"])
|
61
|
-
s.add_dependency(%q<simplecov>, [">= 0.5.4"])
|
62
|
-
end
|
63
|
-
else
|
64
|
-
s.add_dependency(%q<fluentd>, [">= 0"])
|
65
|
-
s.add_dependency(%q<rdoc>, [">= 0"])
|
66
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
|
-
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
69
|
-
s.add_dependency(%q<simplecov>, [">= 0"])
|
70
|
-
s.add_dependency(%q<fluentd>, ["~> 0.10.8"])
|
71
|
-
s.add_dependency(%q<rake>, [">= 0.9.2"])
|
72
|
-
s.add_dependency(%q<simplecov>, [">= 0.5.4"])
|
73
|
-
end
|
17
|
+
gem.add_development_dependency "bundler"
|
18
|
+
gem.add_development_dependency "fluentd"
|
19
|
+
gem.add_development_dependency "fluent-mixin-config-placeholders"
|
20
|
+
gem.add_runtime_dependency "fluentd"
|
21
|
+
gem.add_runtime_dependency "fluent-mixin-config-placeholders"
|
74
22
|
end
|
75
|
-
|
@@ -8,24 +8,30 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
8
8
|
end
|
9
9
|
|
10
10
|
config_param :gfapi_url, :string # growth.forecast.local/api/
|
11
|
-
config_param :service, :string
|
11
|
+
config_param :service, :string, :default => nil
|
12
12
|
config_param :section, :string, :default => nil
|
13
13
|
|
14
|
+
config_param :ssl, :bool, :default => false
|
15
|
+
config_param :verify_ssl, :bool, :default => false
|
16
|
+
|
14
17
|
config_param :name_keys, :string, :default => nil
|
15
18
|
config_param :name_key_pattern, :string, :default => nil
|
16
19
|
|
17
20
|
config_param :mode, :string, :default => 'gauge' # or count/modified
|
18
21
|
|
19
22
|
config_param :remove_prefix, :string, :default => nil
|
20
|
-
config_param :tag_for, :string, :default => 'name_prefix' # or 'ignore' or 'section'
|
23
|
+
config_param :tag_for, :string, :default => 'name_prefix' # or 'ignore' or 'section' or 'service'
|
21
24
|
|
25
|
+
config_param :authentication, :string, :default => nil # nil or 'none' or 'basic'
|
26
|
+
config_param :username, :string, :default => ''
|
27
|
+
config_param :password, :string, :default => ''
|
28
|
+
|
22
29
|
def configure(conf)
|
23
30
|
super
|
24
31
|
|
25
32
|
if @gfapi_url !~ /\/api\/\Z/
|
26
33
|
raise Fluent::ConfigError, "gfapi_url must end with /api/"
|
27
34
|
end
|
28
|
-
@gfurl = @gfapi_url + @service + '/'
|
29
35
|
|
30
36
|
if @name_keys.nil? and @name_key_pattern.nil?
|
31
37
|
raise Fluent::ConfigError, "missing both of name_keys and name_key_pattern"
|
@@ -49,17 +55,27 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
49
55
|
@tag_for = case @tag_for
|
50
56
|
when 'ignore' then :ignore
|
51
57
|
when 'section' then :section
|
58
|
+
when 'service' then :service
|
52
59
|
else
|
53
60
|
:name_prefix
|
54
61
|
end
|
55
62
|
if @tag_for != :section and @section.nil?
|
56
63
|
raise Fluent::ConfigError, "section parameter is needed when tag_for is not 'section'"
|
57
64
|
end
|
65
|
+
if @tag_for != :service and @service.nil?
|
66
|
+
raise Fluent::ConfigError, "service parameter is needed when tag_for is not 'service'"
|
67
|
+
end
|
58
68
|
|
59
69
|
if @remove_prefix
|
60
70
|
@removed_prefix_string = @remove_prefix + '.'
|
61
71
|
@removed_length = @removed_prefix_string.length
|
62
72
|
end
|
73
|
+
|
74
|
+
@auth = case @authentication
|
75
|
+
when 'basic' then :basic
|
76
|
+
else
|
77
|
+
:none
|
78
|
+
end
|
63
79
|
end
|
64
80
|
|
65
81
|
def start
|
@@ -71,25 +87,44 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
71
87
|
end
|
72
88
|
|
73
89
|
def format_url(tag, name)
|
74
|
-
|
90
|
+
if @remove_prefix and
|
91
|
+
( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @remove_prefix)
|
92
|
+
tag = tag[@removed_length..-1]
|
93
|
+
end
|
94
|
+
|
75
95
|
case @tag_for
|
76
96
|
when :ignore
|
77
|
-
@
|
97
|
+
@gfapi_url + URI.escape(@service + '/' + @section + '/' + name)
|
78
98
|
when :section
|
79
|
-
@
|
99
|
+
@gfapi_url + URI.escape(@service + '/' + tag + '/' + name)
|
100
|
+
when :service
|
101
|
+
@gfapi_url + URI.escape(tag + '/' + @section + '/' + name)
|
80
102
|
when :name_prefix
|
81
|
-
@
|
103
|
+
@gfapi_url + URI.escape(@service + '/' + @section + '/' + tag + '_' + name)
|
82
104
|
end
|
83
105
|
end
|
84
106
|
|
85
107
|
def post(tag, name, value)
|
86
108
|
url = format_url(tag,name)
|
109
|
+
res = nil
|
87
110
|
begin
|
88
|
-
|
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
|
124
|
+
res = http.start {|http| http.request(req) }
|
89
125
|
rescue IOError, EOFError, SystemCallError
|
90
126
|
# server didn't respond
|
91
127
|
$log.warn "Net::HTTP.post_form raises exception: #{$!.class}, '#{$!.message}'"
|
92
|
-
res = nil
|
93
128
|
end
|
94
129
|
unless res and res.is_a?(Net::HTTPSuccess)
|
95
130
|
$log.warn "failed to post to growthforecast: #{url}, number: #{value}, code: #{res && res.code}"
|
@@ -97,10 +132,6 @@ class Fluent::GrowthForecastOutput < Fluent::Output
|
|
97
132
|
end
|
98
133
|
|
99
134
|
def emit(tag, es, chain)
|
100
|
-
if @remove_prefix and
|
101
|
-
( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @remove_prefix)
|
102
|
-
tag = tag[@removed_length..-1]
|
103
|
-
end
|
104
135
|
if @name_keys
|
105
136
|
es.each {|time,record|
|
106
137
|
@name_keys.each {|name|
|
data/test/helper.rb
CHANGED
@@ -8,12 +8,45 @@ rescue Bundler::BundlerError => e
|
|
8
8
|
exit e.status_code
|
9
9
|
end
|
10
10
|
require 'test/unit'
|
11
|
-
require 'shoulda'
|
12
11
|
|
13
12
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
13
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
14
|
require 'fluent/test'
|
15
|
+
unless ENV.has_key?('VERBOSE')
|
16
|
+
nulllogger = Object.new
|
17
|
+
nulllogger.instance_eval {|obj|
|
18
|
+
def method_missing(method, *args)
|
19
|
+
# pass
|
20
|
+
end
|
21
|
+
}
|
22
|
+
$log = nulllogger
|
23
|
+
end
|
24
|
+
|
16
25
|
require 'fluent/plugin/out_growthforecast'
|
17
26
|
|
18
27
|
class Test::Unit::TestCase
|
19
28
|
end
|
29
|
+
|
30
|
+
require 'webrick'
|
31
|
+
|
32
|
+
# to handle POST/PUT/DELETE ...
|
33
|
+
module WEBrick::HTTPServlet
|
34
|
+
class ProcHandler < AbstractServlet
|
35
|
+
alias do_POST do_GET
|
36
|
+
alias do_PUT do_GET
|
37
|
+
alias do_DELETE do_GET
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_code(server, port, path, headers={})
|
42
|
+
require 'net/http'
|
43
|
+
Net::HTTP.start(server, port){|http|
|
44
|
+
http.get(path, headers).code
|
45
|
+
}
|
46
|
+
end
|
47
|
+
def get_content(server, port, path, headers={})
|
48
|
+
require 'net/http'
|
49
|
+
Net::HTTP.start(server, port){|http|
|
50
|
+
http.get(path, headers).body
|
51
|
+
}
|
52
|
+
end
|
@@ -1,7 +1,421 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
class
|
4
|
-
|
5
|
-
|
3
|
+
class GrowthForecastOutputTest < Test::Unit::TestCase
|
4
|
+
# setup/teardown and tests of dummy growthforecast server defined at the end of this class...
|
5
|
+
GF_TEST_LISTEN_PORT = 5125
|
6
|
+
|
7
|
+
CONFIG1 = %[
|
8
|
+
gfapi_url http://127.0.0.1:5125/api/
|
9
|
+
service service
|
10
|
+
section metrics
|
11
|
+
name_keys field1,field2,otherfield
|
12
|
+
tag_for name_prefix
|
13
|
+
]
|
14
|
+
|
15
|
+
CONFIG2 = %[
|
16
|
+
gfapi_url http://127.0.0.1:5125/api/
|
17
|
+
service service
|
18
|
+
section metrics
|
19
|
+
tag_for ignore
|
20
|
+
name_keys field1,field2,otherfield
|
21
|
+
mode count
|
22
|
+
]
|
23
|
+
|
24
|
+
CONFIG3 = %[
|
25
|
+
gfapi_url http://127.0.0.1:5125/api/
|
26
|
+
service service
|
27
|
+
tag_for section
|
28
|
+
remove_prefix test
|
29
|
+
name_key_pattern ^(field|key)\\d+$
|
30
|
+
mode modified
|
31
|
+
]
|
32
|
+
|
33
|
+
CONFIG4 = %[
|
34
|
+
gfapi_url http://127.0.0.1:5125/api/
|
35
|
+
section metrics
|
36
|
+
name_keys field1,field2,otherfield
|
37
|
+
tag_for service
|
38
|
+
remove_prefix test
|
39
|
+
]
|
40
|
+
|
41
|
+
CONFIG_SPACE = %[
|
42
|
+
gfapi_url http://127.0.0.1:5125/api/
|
43
|
+
service service x
|
44
|
+
section metrics y
|
45
|
+
name_keys field z
|
46
|
+
tag_for ignore
|
47
|
+
]
|
48
|
+
|
49
|
+
def create_driver(conf=CONFIG1, tag='test.metrics')
|
50
|
+
Fluent::Test::OutputTestDriver.new(Fluent::GrowthForecastOutput, tag).configure(conf)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_configure_and_format_url
|
54
|
+
d = create_driver
|
55
|
+
assert_equal 'http://127.0.0.1:5125/api/', d.instance.gfapi_url
|
56
|
+
assert_equal 'service', d.instance.service
|
57
|
+
assert_equal 'metrics', d.instance.section
|
58
|
+
assert_equal ['field1', 'field2', 'otherfield'], d.instance.name_keys
|
59
|
+
assert_nil d.instance.remove_prefix
|
60
|
+
assert_equal :name_prefix, d.instance.tag_for
|
61
|
+
assert_equal :gauge, d.instance.mode
|
62
|
+
|
63
|
+
assert_equal 'http://127.0.0.1:5125/api/service/metrics/test.data1_field1', d.instance.format_url('test.data1', 'field1')
|
64
|
+
|
65
|
+
d = create_driver(CONFIG2)
|
66
|
+
assert_equal 'http://127.0.0.1:5125/api/', d.instance.gfapi_url
|
67
|
+
assert_equal 'service', d.instance.service
|
68
|
+
assert_equal 'metrics', d.instance.section
|
69
|
+
assert_equal ['field1', 'field2', 'otherfield'], d.instance.name_keys
|
70
|
+
assert_nil d.instance.remove_prefix
|
71
|
+
assert_equal :ignore, d.instance.tag_for
|
72
|
+
assert_equal :count, d.instance.mode
|
73
|
+
|
74
|
+
assert_equal 'http://127.0.0.1:5125/api/service/metrics/field1', d.instance.format_url('test.data1', 'field1')
|
75
|
+
|
76
|
+
d = create_driver(CONFIG3)
|
77
|
+
assert_equal 'http://127.0.0.1:5125/api/', d.instance.gfapi_url
|
78
|
+
assert_equal 'service', d.instance.service
|
79
|
+
assert_nil d.instance.section
|
80
|
+
assert_equal Regexp.new('^(field|key)\d+$'), d.instance.name_key_pattern
|
81
|
+
assert_equal 'test', d.instance.remove_prefix
|
82
|
+
assert_equal :section, d.instance.tag_for
|
83
|
+
assert_equal 'test.', d.instance.instance_eval{ @removed_prefix_string }
|
84
|
+
assert_equal :modified, d.instance.mode
|
85
|
+
|
86
|
+
assert_equal 'http://127.0.0.1:5125/api/service/data1/field1', d.instance.format_url('test.data1', 'field1')
|
87
|
+
end
|
88
|
+
|
89
|
+
# CONFIG1 = %[
|
90
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
91
|
+
# service service
|
92
|
+
# section metrics
|
93
|
+
# name_keys field1,field2,otherfield
|
94
|
+
# tag_for name_prefix
|
95
|
+
# ]
|
96
|
+
def test_emit_1
|
97
|
+
d = create_driver(CONFIG1, 'test.metrics')
|
98
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
99
|
+
d.run
|
100
|
+
|
101
|
+
assert_equal 3, @posted.size
|
102
|
+
v1st = @posted[0]
|
103
|
+
v2nd = @posted[1]
|
104
|
+
v3rd = @posted[2]
|
105
|
+
|
106
|
+
assert_equal 50, v1st[:data][:number]
|
107
|
+
assert_equal 'gauge', v1st[:data][:mode]
|
108
|
+
assert_nil v1st[:auth]
|
109
|
+
assert_equal 'service', v1st[:service]
|
110
|
+
assert_equal 'metrics', v1st[:section]
|
111
|
+
assert_equal 'test.metrics_field1', v1st[:name]
|
112
|
+
|
113
|
+
assert_equal 20, v2nd[:data][:number]
|
114
|
+
assert_equal 'test.metrics_field2', v2nd[:name]
|
115
|
+
|
116
|
+
assert_equal 1, v3rd[:data][:number]
|
117
|
+
assert_equal 'test.metrics_otherfield', v3rd[:name]
|
118
|
+
end
|
119
|
+
|
120
|
+
# CONFIG2 = %[
|
121
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
122
|
+
# service service
|
123
|
+
# section metrics
|
124
|
+
# tag_for ignore
|
125
|
+
# name_keys field1,field2,otherfield
|
126
|
+
# mode count
|
127
|
+
# ]
|
128
|
+
def test_emit_2
|
129
|
+
d = create_driver(CONFIG2, 'test.metrics')
|
130
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
131
|
+
d.run
|
132
|
+
|
133
|
+
assert_equal 3, @posted.size
|
134
|
+
v1st = @posted[0]
|
135
|
+
v2nd = @posted[1]
|
136
|
+
v3rd = @posted[2]
|
137
|
+
|
138
|
+
assert_equal 50, v1st[:data][:number]
|
139
|
+
assert_equal 'count', v1st[:data][:mode]
|
140
|
+
assert_nil v1st[:auth]
|
141
|
+
assert_equal 'service', v1st[:service]
|
142
|
+
assert_equal 'metrics', v1st[:section]
|
143
|
+
assert_equal 'field1', v1st[:name]
|
144
|
+
|
145
|
+
assert_equal 20, v2nd[:data][:number]
|
146
|
+
assert_equal 'field2', v2nd[:name]
|
147
|
+
|
148
|
+
assert_equal 1, v3rd[:data][:number]
|
149
|
+
assert_equal 'otherfield', v3rd[:name]
|
150
|
+
end
|
151
|
+
|
152
|
+
# CONFIG3 = %[
|
153
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
154
|
+
# service service
|
155
|
+
# tag_for section
|
156
|
+
# remove_prefix test
|
157
|
+
# name_key_pattern ^(field|key)\\d+$
|
158
|
+
# mode modified
|
159
|
+
# ]
|
160
|
+
def test_emit_3
|
161
|
+
d = create_driver(CONFIG3, 'test.metrics')
|
162
|
+
# recent ruby's Hash saves elements order....
|
163
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
164
|
+
d.run
|
165
|
+
|
166
|
+
assert_equal 3, @posted.size
|
167
|
+
v1st = @posted[0]
|
168
|
+
v2nd = @posted[1]
|
169
|
+
v3rd = @posted[2]
|
170
|
+
|
171
|
+
assert_equal 50, v1st[:data][:number]
|
172
|
+
assert_equal 'modified', v1st[:data][:mode]
|
173
|
+
assert_nil v1st[:auth]
|
174
|
+
assert_equal 'service', v1st[:service]
|
175
|
+
assert_equal 'metrics', v1st[:section]
|
176
|
+
assert_equal 'field1', v1st[:name]
|
177
|
+
|
178
|
+
assert_equal 20, v2nd[:data][:number]
|
179
|
+
assert_equal 'field2', v2nd[:name]
|
180
|
+
|
181
|
+
assert_equal 10, v3rd[:data][:number]
|
182
|
+
assert_equal 'field3', v3rd[:name]
|
183
|
+
end
|
184
|
+
|
185
|
+
# CONFIG1 = %[
|
186
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
187
|
+
# service service
|
188
|
+
# section metrics
|
189
|
+
# name_keys field1,field2,otherfield
|
190
|
+
# tag_for name_prefix
|
191
|
+
# ]
|
192
|
+
def test_emit_4_auth
|
193
|
+
@auth = true # enable authentication of dummy server
|
194
|
+
|
195
|
+
d = create_driver(CONFIG1, 'test.metrics')
|
196
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
197
|
+
d.run # failed in background, and output warn log
|
198
|
+
|
199
|
+
assert_equal 0, @posted.size
|
200
|
+
assert_equal 3, @prohibited
|
201
|
+
|
202
|
+
d = create_driver(CONFIG1 + %[
|
203
|
+
authentication basic
|
204
|
+
username alice
|
205
|
+
password wrong_password
|
206
|
+
], 'test.metrics')
|
207
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
208
|
+
d.run # failed in background, and output warn log
|
209
|
+
|
210
|
+
assert_equal 0, @posted.size
|
211
|
+
assert_equal 6, @prohibited
|
212
|
+
|
213
|
+
d = create_driver(CONFIG1 + %[
|
214
|
+
authentication basic
|
215
|
+
username alice
|
216
|
+
password secret!
|
217
|
+
], 'test.metrics')
|
218
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
219
|
+
d.run # failed in background, and output warn log
|
220
|
+
|
221
|
+
assert_equal 6, @prohibited
|
222
|
+
assert_equal 3, @posted.size
|
6
223
|
end
|
224
|
+
|
225
|
+
# CONFIG4 = %[
|
226
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
227
|
+
# section metrics
|
228
|
+
# name_keys field1,field2,otherfield
|
229
|
+
# tag_for service
|
230
|
+
# remove_prefix test
|
231
|
+
# ]
|
232
|
+
|
233
|
+
def test_emit_5
|
234
|
+
d = create_driver(CONFIG4, 'test.service')
|
235
|
+
# recent ruby's Hash saves elements order....
|
236
|
+
d.emit({ 'field1' => 50, 'field2' => 20, 'field3' => 10, 'otherfield' => 1 })
|
237
|
+
d.run
|
238
|
+
|
239
|
+
assert_equal 3, @posted.size
|
240
|
+
v1st = @posted[0]
|
241
|
+
v2nd = @posted[1]
|
242
|
+
v3rd = @posted[2]
|
243
|
+
|
244
|
+
assert_equal 50, v1st[:data][:number]
|
245
|
+
assert_equal 'gauge', v1st[:data][:mode]
|
246
|
+
assert_nil v1st[:auth]
|
247
|
+
assert_equal 'service', v1st[:service]
|
248
|
+
assert_equal 'metrics', v1st[:section]
|
249
|
+
assert_equal 'field1', v1st[:name]
|
250
|
+
|
251
|
+
assert_equal 20, v2nd[:data][:number]
|
252
|
+
assert_equal 'field2', v2nd[:name]
|
253
|
+
|
254
|
+
assert_equal 1, v3rd[:data][:number]
|
255
|
+
assert_equal 'otherfield', v3rd[:name]
|
256
|
+
end
|
257
|
+
|
258
|
+
# CONFIG_SPACE = %[
|
259
|
+
# gfapi_url http://127.0.0.1:5125/api/
|
260
|
+
# service service x
|
261
|
+
# section metrics y
|
262
|
+
# name_keys field z
|
263
|
+
# tag_for ignore
|
264
|
+
# ]
|
265
|
+
def test_with_space_1
|
266
|
+
d = create_driver(CONFIG_SPACE, 'test.foo')
|
267
|
+
d.emit({ 'field z' => 3 })
|
268
|
+
d.run
|
269
|
+
|
270
|
+
assert_equal 1, @posted.size
|
271
|
+
v = @posted[0]
|
272
|
+
|
273
|
+
assert_equal 3, v[:data][:number]
|
274
|
+
assert_equal 'gauge', v[:data][:mode]
|
275
|
+
assert_nil v[:auth]
|
276
|
+
assert_equal 'service x', v[:service]
|
277
|
+
assert_equal 'metrics y', v[:section]
|
278
|
+
assert_equal 'field z', v[:name]
|
279
|
+
end
|
280
|
+
|
281
|
+
# setup / teardown for servers
|
282
|
+
def setup
|
283
|
+
Fluent::Test.setup
|
284
|
+
@posted = []
|
285
|
+
@prohibited = 0
|
286
|
+
@auth = false
|
287
|
+
@dummy_server_thread = Thread.new do
|
288
|
+
srv = if ENV['VERBOSE']
|
289
|
+
WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => GF_TEST_LISTEN_PORT})
|
290
|
+
else
|
291
|
+
logger = WEBrick::Log.new('/dev/null', WEBrick::BasicLog::DEBUG)
|
292
|
+
WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => GF_TEST_LISTEN_PORT, :Logger => logger, :AccessLog => []})
|
293
|
+
end
|
294
|
+
begin
|
295
|
+
srv.mount_proc('/api') { |req,res| # /api/:service/:section/:name
|
296
|
+
unless req.request_method == 'POST'
|
297
|
+
res.status = 405
|
298
|
+
res.body = 'request method mismatch'
|
299
|
+
next
|
300
|
+
end
|
301
|
+
if @auth and req.header['authorization'][0] == 'Basic YWxpY2U6c2VjcmV0IQ==' # pattern of user='alice' passwd='secret!'
|
302
|
+
# ok, authorized
|
303
|
+
elsif @auth
|
304
|
+
res.status = 403
|
305
|
+
@prohibited += 1
|
306
|
+
next
|
307
|
+
else
|
308
|
+
# ok, authorization not required
|
309
|
+
end
|
310
|
+
|
311
|
+
req.path =~ /^\/api\/([^\/]*)\/([^\/]*)\/(.*)$/
|
312
|
+
service = $1
|
313
|
+
section = $2
|
314
|
+
graph_name = $3
|
315
|
+
post_param = Hash[*(req.body.split('&').map{|kv|kv.split('=')}.flatten)]
|
316
|
+
|
317
|
+
@posted.push({
|
318
|
+
:service => service,
|
319
|
+
:section => section,
|
320
|
+
:name => graph_name,
|
321
|
+
:auth => nil,
|
322
|
+
:data => { :number => post_param['number'].to_i, :mode => post_param['mode'] },
|
323
|
+
})
|
324
|
+
|
325
|
+
res.status = 200
|
326
|
+
}
|
327
|
+
srv.mount_proc('/') { |req,res|
|
328
|
+
res.status = 200
|
329
|
+
res.body = 'running'
|
330
|
+
}
|
331
|
+
srv.start
|
332
|
+
ensure
|
333
|
+
srv.shutdown
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# to wait completion of dummy server.start()
|
338
|
+
require 'thread'
|
339
|
+
cv = ConditionVariable.new
|
340
|
+
watcher = Thread.new {
|
341
|
+
connected = false
|
342
|
+
while not connected
|
343
|
+
begin
|
344
|
+
get_content('localhost', GF_TEST_LISTEN_PORT, '/')
|
345
|
+
connected = true
|
346
|
+
rescue Errno::ECONNREFUSED
|
347
|
+
sleep 0.1
|
348
|
+
rescue StandardError => e
|
349
|
+
p e
|
350
|
+
sleep 0.1
|
351
|
+
end
|
352
|
+
end
|
353
|
+
cv.signal
|
354
|
+
}
|
355
|
+
mutex = Mutex.new
|
356
|
+
mutex.synchronize {
|
357
|
+
cv.wait(mutex)
|
358
|
+
}
|
359
|
+
end
|
360
|
+
|
361
|
+
def test_dummy_server
|
362
|
+
d = create_driver
|
363
|
+
d.instance.gfapi_url =~ /^http:\/\/([.:a-z0-9]+)\//
|
364
|
+
server = $1
|
365
|
+
host = server.split(':')[0]
|
366
|
+
port = server.split(':')[1].to_i
|
367
|
+
client = Net::HTTP.start(host, port)
|
368
|
+
|
369
|
+
assert_equal '200', client.request_get('/').code
|
370
|
+
assert_equal '200', client.request_post('/api/service/metrics/hoge', 'number=1&mode=gauge').code
|
371
|
+
|
372
|
+
assert_equal 1, @posted.size
|
373
|
+
|
374
|
+
assert_equal 1, @posted[0][:data][:number]
|
375
|
+
assert_equal 'gauge', @posted[0][:data][:mode]
|
376
|
+
assert_nil @posted[0][:auth]
|
377
|
+
assert_equal 'service', @posted[0][:service]
|
378
|
+
assert_equal 'metrics', @posted[0][:section]
|
379
|
+
assert_equal 'hoge', @posted[0][:name]
|
380
|
+
|
381
|
+
assert_equal '200', client.request_post(URI.escape('/api/service x/metrics/hoge'), 'number=1&mode=gauge').code
|
382
|
+
|
383
|
+
assert_equal 2, @posted.size
|
384
|
+
|
385
|
+
assert_equal 1, @posted[1][:data][:number]
|
386
|
+
assert_equal 'gauge', @posted[1][:data][:mode]
|
387
|
+
assert_nil @posted[1][:auth]
|
388
|
+
assert_equal 'service x', @posted[1][:service]
|
389
|
+
assert_equal 'metrics', @posted[1][:section]
|
390
|
+
assert_equal 'hoge', @posted[1][:name]
|
391
|
+
|
392
|
+
@auth = true
|
393
|
+
|
394
|
+
assert_equal '403', client.request_post('/api/service/metrics/pos', 'number=30&mode=gauge').code
|
395
|
+
|
396
|
+
req_with_auth = lambda do |number, mode, user, pass|
|
397
|
+
url = URI.parse("http://#{host}:#{port}/api/service/metrics/pos")
|
398
|
+
req = Net::HTTP::Post.new(url.path)
|
399
|
+
req.basic_auth user, pass
|
400
|
+
req.set_form_data({'number'=>number, 'mode'=>mode})
|
401
|
+
req
|
402
|
+
end
|
403
|
+
|
404
|
+
assert_equal '403', client.request(req_with_auth.call(500, 'count', 'alice', 'wrong password!')).code
|
405
|
+
|
406
|
+
assert_equal '403', client.request(req_with_auth.call(500, 'count', 'alice', 'wrong password!')).code
|
407
|
+
|
408
|
+
assert_equal 2, @posted.size
|
409
|
+
|
410
|
+
assert_equal '200', client.request(req_with_auth.call(500, 'count', 'alice', 'secret!')).code
|
411
|
+
|
412
|
+
assert_equal 3, @posted.size
|
413
|
+
|
414
|
+
end
|
415
|
+
|
416
|
+
def teardown
|
417
|
+
@dummy_server_thread.kill
|
418
|
+
@dummy_server_thread.join
|
419
|
+
end
|
420
|
+
|
7
421
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-growthforecast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,33 +9,17 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: rdoc
|
15
|
+
name: bundler
|
32
16
|
requirement: !ruby/object:Gem::Requirement
|
33
17
|
none: false
|
34
18
|
requirements:
|
35
19
|
- - ! '>='
|
36
20
|
- !ruby/object:Gem::Version
|
37
21
|
version: '0'
|
38
|
-
type: :
|
22
|
+
type: :development
|
39
23
|
prerelease: false
|
40
24
|
version_requirements: !ruby/object:Gem::Requirement
|
41
25
|
none: false
|
@@ -44,7 +28,7 @@ dependencies:
|
|
44
28
|
- !ruby/object:Gem::Version
|
45
29
|
version: '0'
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
31
|
+
name: fluentd
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
49
33
|
none: false
|
50
34
|
requirements:
|
@@ -60,39 +44,7 @@ dependencies:
|
|
60
44
|
- !ruby/object:Gem::Version
|
61
45
|
version: '0'
|
62
46
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: 1.0.0
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 1.0.0
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: jeweler
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ~>
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: 1.6.4
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 1.6.4
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: simplecov
|
47
|
+
name: fluent-mixin-config-placeholders
|
96
48
|
requirement: !ruby/object:Gem::Requirement
|
97
49
|
none: false
|
98
50
|
requirements:
|
@@ -109,73 +61,56 @@ dependencies:
|
|
109
61
|
version: '0'
|
110
62
|
- !ruby/object:Gem::Dependency
|
111
63
|
name: fluentd
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ~>
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.10.8
|
118
|
-
type: :runtime
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ~>
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: 0.10.8
|
126
|
-
- !ruby/object:Gem::Dependency
|
127
|
-
name: rake
|
128
64
|
requirement: !ruby/object:Gem::Requirement
|
129
65
|
none: false
|
130
66
|
requirements:
|
131
67
|
- - ! '>='
|
132
68
|
- !ruby/object:Gem::Version
|
133
|
-
version: 0
|
134
|
-
type: :
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
135
71
|
prerelease: false
|
136
72
|
version_requirements: !ruby/object:Gem::Requirement
|
137
73
|
none: false
|
138
74
|
requirements:
|
139
75
|
- - ! '>='
|
140
76
|
- !ruby/object:Gem::Version
|
141
|
-
version: 0
|
77
|
+
version: '0'
|
142
78
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
79
|
+
name: fluent-mixin-config-placeholders
|
144
80
|
requirement: !ruby/object:Gem::Requirement
|
145
81
|
none: false
|
146
82
|
requirements:
|
147
83
|
- - ! '>='
|
148
84
|
- !ruby/object:Gem::Version
|
149
|
-
version: 0
|
150
|
-
type: :
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
151
87
|
prerelease: false
|
152
88
|
version_requirements: !ruby/object:Gem::Requirement
|
153
89
|
none: false
|
154
90
|
requirements:
|
155
91
|
- - ! '>='
|
156
92
|
- !ruby/object:Gem::Version
|
157
|
-
version: 0
|
158
|
-
description:
|
159
|
-
email:
|
93
|
+
version: '0'
|
94
|
+
description: For GrowthForecast, see http://kazeburo.github.com/GrowthForecast/
|
95
|
+
email:
|
96
|
+
- tagomoris@gmail.com
|
160
97
|
executables: []
|
161
98
|
extensions: []
|
162
|
-
extra_rdoc_files:
|
163
|
-
- LICENSE.txt
|
164
|
-
- README.rdoc
|
99
|
+
extra_rdoc_files: []
|
165
100
|
files:
|
166
101
|
- .document
|
167
102
|
- .gitignore
|
168
103
|
- AUTHORS
|
169
104
|
- Gemfile
|
170
105
|
- LICENSE.txt
|
171
|
-
- README.
|
106
|
+
- README.md
|
172
107
|
- Rakefile
|
173
108
|
- VERSION
|
174
109
|
- fluent-plugin-growthforecast.gemspec
|
175
110
|
- lib/fluent/plugin/out_growthforecast.rb
|
176
111
|
- test/helper.rb
|
177
112
|
- test/plugin/test_out_growthforecast.rb
|
178
|
-
homepage:
|
113
|
+
homepage: https://github.com/tagomoris/fluent-plugin-growthforecast
|
179
114
|
licenses: []
|
180
115
|
post_install_message:
|
181
116
|
rdoc_options: []
|
@@ -187,9 +122,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
187
122
|
- - ! '>='
|
188
123
|
- !ruby/object:Gem::Version
|
189
124
|
version: '0'
|
190
|
-
segments:
|
191
|
-
- 0
|
192
|
-
hash: -1202506327029138940
|
193
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
126
|
none: false
|
195
127
|
requirements:
|
@@ -201,7 +133,7 @@ rubyforge_project:
|
|
201
133
|
rubygems_version: 1.8.21
|
202
134
|
signing_key:
|
203
135
|
specification_version: 3
|
204
|
-
summary:
|
136
|
+
summary: Fluentd output plugin to post numbers to GrowthForecast (by kazeburo)
|
205
137
|
test_files:
|
206
138
|
- test/helper.rb
|
207
139
|
- test/plugin/test_out_growthforecast.rb
|
data/README.rdoc
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
= fluent-plugin-growthforecast
|
2
|
-
|
3
|
-
== Component
|
4
|
-
|
5
|
-
=== GrowthForecastOutput
|
6
|
-
|
7
|
-
Plugin to output numbers(metrics) to 'GrowthForecast', metrics drawing tool over HTTP.
|
8
|
-
|
9
|
-
About GrowthForecast, see:
|
10
|
-
- Github: https://github.com/kazeburo/growthforecast
|
11
|
-
- Japanese blog post by @kazeburo: http://blog.nomadscafe.jp/2011/12/growthforecast.html
|
12
|
-
|
13
|
-
GrowthForecast is very simple but useful tool to draw graphs what we want, with GrowthForecastOutput and Fluentd.
|
14
|
-
|
15
|
-
== Configuration
|
16
|
-
|
17
|
-
=== GrowthForecastOutput
|
18
|
-
|
19
|
-
For messages such as:
|
20
|
-
tag:metrics {"field1":300, "field2":20, "field3diff":-30}
|
21
|
-
|
22
|
-
Configuration example for graphs in growthforecast with POST api url 'http://growthforecast.local/api/service1/metrics1/metrics_FIELDNAME'.
|
23
|
-
|
24
|
-
<match metrics>
|
25
|
-
type growthforecast
|
26
|
-
gfapi_url http://growthforecast.local/api/
|
27
|
-
service service1
|
28
|
-
section metrics1
|
29
|
-
name_keys field1,field2,field3diff
|
30
|
-
</match>
|
31
|
-
|
32
|
-
With this configuration, out_growthforecast posts urls below.
|
33
|
-
- http://growthforecast.local/api/service1/metrics1/metrics_field1
|
34
|
-
- http://growthforecast.local/api/service1/metrics1/metrics_field2
|
35
|
-
- http://growthforecast.local/api/service1/metrics1/metrics_field3diff
|
36
|
-
|
37
|
-
|
38
|
-
If you want to use tags for 'section' in GrowthForecast, use 'tag_for' options and remove_prefix (and not to set 'section').
|
39
|
-
|
40
|
-
<match metrics.**>
|
41
|
-
type growthforecast
|
42
|
-
gfapi_url http://growthforecast.local/api/
|
43
|
-
service service1
|
44
|
-
name_keys field1,field2,field3diff
|
45
|
-
tag_for section # or 'name_prefix'(default) or 'ignore'
|
46
|
-
remove_prefix metrics
|
47
|
-
</match>
|
48
|
-
|
49
|
-
'mode' option available with 'gauge'(default), 'count', 'modified', just same as 'mode' of GrowthForecast POST parameter.
|
50
|
-
|
51
|
-
== TODO
|
52
|
-
|
53
|
-
- consider what to do next
|
54
|
-
- patches welcome!
|
55
|
-
|
56
|
-
== Copyright
|
57
|
-
|
58
|
-
Copyright:: Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
|
59
|
-
License:: Apache License, Version 2.0
|