fluent-plugin-graphite 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 323b32da78572ee0adebcd5a15360a33c7f9167c
4
+ data.tar.gz: 873402acdebcf5dfa4303aed4417e76f810882f4
5
+ SHA512:
6
+ metadata.gz: ba7ef1dac376cb6777707ba5fbacc29e2ad08f710da2d4e5d1785e80a4e056f385cd1d9ba22c7e8dd400d59d09deb156605021bac92fa690b23e7ead1f8036ef
7
+ data.tar.gz: 277930b5938d4db86e83d88283d5877f770ddf0c479355dbed0233ddfd61451d387c6e405fc59b66be8e2f689043e799d00125527b87ec08f3a934acdb2b4255
data/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ /*.gem
2
+ ~*
3
+ #*
4
+ *~
5
+ .bundle
6
+ Gemfile.lock
7
+ .rbenv-version
8
+ vendor
9
+ doc/*
10
+ tmp/*
11
+ coverage
12
+ .yardoc
13
+ pkg/
14
+ .ruby-version
15
+ *.gem
16
+ *.rbc
17
+ .bundle
18
+ .config
19
+ coverage
20
+ InstalledFiles
21
+ lib/bundler/man
22
+ pkg
23
+ rdoc
24
+ spec/reports
25
+ test/tmp
26
+ test/version_tmp
27
+ tmp
28
+
29
+ # YARD artifacts
30
+ .yardoc
31
+ _yardoc
32
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 studio3104
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Fluent::Plugin::Graphite
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'fluent-plugin-graphite'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install fluent-plugin-graphite
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/studio3104/fluent-plugin-graphite/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'fluent-plugin-graphite'
6
+ gem.version = '0.0.1'
7
+ gem.authors = ['Satoshi SUZUKI']
8
+ gem.email = 'studio3104.com@gmail.com'
9
+ gem.homepage = 'https://github.com/studio3104/fluent-plugin-graphite'
10
+ gem.description = 'fluentd output plugin to send metrics to graphite'
11
+ gem.summary = gem.description
12
+ gem.licenses = ['MIT']
13
+ gem.has_rdoc = false
14
+
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_runtime_dependency 'fluentd', '~> 0.10.17'
21
+ gem.add_runtime_dependency 'fluent-mixin-rewrite-tag-name'
22
+ gem.add_runtime_dependency 'graphite-api'
23
+ gem.add_development_dependency 'rake'
24
+ end
@@ -0,0 +1,88 @@
1
+ require 'fluent/mixin/rewrite_tag_name'
2
+
3
+ class Fluent::GraphiteOutput < Fluent::Output
4
+ Fluent::Plugin.register_output('graphite', self)
5
+
6
+ include Fluent::HandleTagNameMixin
7
+ include Fluent::Mixin::RewriteTagName
8
+
9
+ config_param :host, :string
10
+ config_param :port, :integer, default: 2003
11
+ config_param :tag_for, :string, default: 'prefix'
12
+ config_param :name_keys, :string, default: nil
13
+ config_param :name_key_pattern, :string, default: nil
14
+
15
+ def initialize
16
+ super
17
+ require 'graphite-api'
18
+ end
19
+
20
+ def start
21
+ super
22
+ @client = GraphiteAPI.new(graphite: "#{@host}:#{@port}")
23
+ end
24
+
25
+ def configure(conf)
26
+ super
27
+
28
+ if !['prefix', 'suffix', 'ignore'].include?(@tag_for)
29
+ raise Fluent::ConfigError, 'out_graphite: can specify to tag_for only prefix, suffix or ignore'
30
+ end
31
+
32
+ if !@name_keys && !@name_key_pattern
33
+ raise Fluent::ConfigError, 'out_graphite: missing both of name_keys and name_key_pattern'
34
+ end
35
+ if @name_keys && @name_key_pattern
36
+ raise Fluent::ConfigError, 'out_graphite: cannot specify both of name_keys and name_key_pattern'
37
+ end
38
+
39
+ if @name_keys
40
+ @name_keys = @name_keys.split(',')
41
+ end
42
+ if @name_key_pattern
43
+ @name_key_pattern = Regexp.new(@name_key_pattern)
44
+ end
45
+ end
46
+
47
+ def emit(tag, es, chain)
48
+ es.each do |time, record|
49
+ emit_tag = tag.dup
50
+ filter_record(emit_tag, time, record)
51
+ next unless metrics = format_metrics(emit_tag, record)
52
+
53
+ # implemented to immediate call post method in this loop, because graphite-api.gem has the buffers.
54
+ post(metrics, time)
55
+ end
56
+
57
+ chain.next
58
+ end
59
+
60
+ def format_metrics(tag, record)
61
+ filtered_record = if @name_keys
62
+ record.select { |k,v| @name_keys.include?(k) }
63
+ else # defined @name_key_pattern
64
+ record.select { |k,v| @name_key_pattern.match(k) }
65
+ end
66
+
67
+ return nil if filtered_record.empty?
68
+
69
+ metrics = {}
70
+ filtered_record.each do |k, v|
71
+ key = case @tag_for
72
+ when 'ignore' then k
73
+ when 'prefix' then tag + k
74
+ when 'suffix' then k + '.' + tag.sub(/\.$/, '') # include a dot at the end of the emit_tag fluent-mixin-rewrite-tag-name returns. remove it.
75
+ end
76
+
77
+ key = key.gsub(/(\s|\/)+/, '_') # cope with in the case of containing symbols or spaces in the key of the record like in_dstat.
78
+ metrics[key] = v.to_f
79
+ end
80
+ metrics
81
+ end
82
+
83
+ def post(metrics, time)
84
+ @client.metrics(metrics, time)
85
+ rescue Errno::ECONNREFUSED
86
+ $log.warn "out_graphite: connection refused by #{@host}:#{@port}"
87
+ end
88
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,29 @@
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
+ require 'test/unit'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'fluent/test'
16
+ unless ENV.has_key?('VERBOSE')
17
+ nulllogger = Object.new
18
+ nulllogger.instance_eval {|obj|
19
+ def method_missing(method, *args)
20
+ # pass
21
+ end
22
+ }
23
+ $log = nulllogger
24
+ end
25
+
26
+ require 'fluent/plugin/out_graphite'
27
+
28
+ class Test::Unit::TestCase
29
+ end
@@ -0,0 +1,112 @@
1
+ require 'helper'
2
+
3
+ class GraphiteOutputTest < Test::Unit::TestCase
4
+ TCP_PORT = 42003
5
+ CONFIG_NAME_KEY_PATTERN = %[
6
+ host localhost
7
+ port #{TCP_PORT}
8
+ name_key_pattern ^((?!hostname).)*$
9
+ ]
10
+ CONFIG_NAME_KEYS = %[
11
+ host localhost
12
+ port #{TCP_PORT}
13
+ name_keys dstat.total cpu usage.usr,dstat.total cpu usage.sys,dstat.total cpu usage.idl
14
+ ]
15
+ CONFIG_TAG_FOR_IGNORE = %[
16
+ host localhost
17
+ port #{TCP_PORT}
18
+ name_keys dstat.total cpu usage.usr,dstat.total cpu usage.sys,dstat.total cpu usage.idl
19
+ tag_for ignore
20
+ ]
21
+ CONFIG_TAG_FOR_SUFFIX = %[
22
+ host localhost
23
+ port #{TCP_PORT}
24
+ name_keys dstat.total cpu usage.usr,dstat.total cpu usage.sys,dstat.total cpu usage.idl
25
+ tag_for suffix
26
+ ]
27
+ CONFIG_INVALID_TAG_FOR = %[
28
+ host localhost
29
+ port #{TCP_PORT}
30
+ name_key_pattern ^((?!hostname).)*$
31
+ tag_for invalid
32
+ ]
33
+ CONFIG_SPECIFY_BOTH_NAME_KEYS_AND_NAME_KEY_PATTERN = %[
34
+ host localhost
35
+ port #{TCP_PORT}
36
+ name_keys dstat.total cpu usage.usr,dstat.total cpu usage.sys,dstat.total cpu usage.idl
37
+ name_key_pattern ^((?!hostname).)*$
38
+ ]
39
+
40
+ def setup
41
+ @server = TCPServer.new(TCP_PORT)
42
+ end
43
+
44
+ def teardown
45
+ @server.close
46
+ end
47
+
48
+ def create_driver(conf = CONFIG_NAME_KEY_PATTERN, tag='test')
49
+ Fluent::Test::OutputTestDriver.new(Fluent::GraphiteOutput, tag).configure(conf)
50
+ end
51
+
52
+ def test_configure
53
+ d = create_driver
54
+ assert_equal d.instance.host, 'localhost'
55
+ assert_equal d.instance.port, TCP_PORT
56
+ assert_equal d.instance.tag_for, 'prefix'
57
+ assert_equal d.instance.name_keys, nil
58
+ assert_equal d.instance.name_key_pattern, /^((?!hostname).)*$/
59
+
60
+ d = create_driver(CONFIG_NAME_KEYS)
61
+ assert_equal d.instance.host, 'localhost'
62
+ assert_equal d.instance.port, TCP_PORT
63
+ assert_equal d.instance.tag_for, 'prefix'
64
+ assert_equal d.instance.name_keys, ['dstat.total cpu usage.usr', 'dstat.total cpu usage.sys', 'dstat.total cpu usage.idl']
65
+ assert_equal d.instance.name_key_pattern, nil
66
+
67
+ d = create_driver(CONFIG_TAG_FOR_IGNORE)
68
+ assert_equal d.instance.host, 'localhost'
69
+ assert_equal d.instance.port, TCP_PORT
70
+ assert_equal d.instance.tag_for, 'ignore'
71
+ assert_equal d.instance.name_keys, ['dstat.total cpu usage.usr', 'dstat.total cpu usage.sys', 'dstat.total cpu usage.idl']
72
+ assert_equal d.instance.name_key_pattern, nil
73
+
74
+ d = create_driver(CONFIG_TAG_FOR_SUFFIX)
75
+ assert_equal d.instance.host, 'localhost'
76
+ assert_equal d.instance.port, TCP_PORT
77
+ assert_equal d.instance.tag_for, 'suffix'
78
+ assert_equal d.instance.name_keys, ['dstat.total cpu usage.usr', 'dstat.total cpu usage.sys', 'dstat.total cpu usage.idl']
79
+ assert_equal d.instance.name_key_pattern, nil
80
+
81
+ assert_raise(Fluent::ConfigError) { d = create_driver(CONFIG_INVALID_TAG_FOR) }
82
+ assert_raise(Fluent::ConfigError) { d = create_driver(CONFIG_SPECIFY_BOTH_NAME_KEYS_AND_NAME_KEY_PATTERN) }
83
+ end
84
+
85
+ def test_format_metrics
86
+ record = {
87
+ 'hostname' => 'localhost.localdomain',
88
+ 'dstat.total cpu usage.usr' => '0.0',
89
+ 'dstat.total cpu usage.sys' => '0.0',
90
+ 'dstat.total cpu usage.idl' => '100.0',
91
+ 'dstat.total cpu usage.wai' => '0.0',
92
+ 'dstat.total cpu usage.hiq' => '0.0',
93
+ 'dstat.total cpu usage.siq' => '0.0'
94
+ }
95
+
96
+ d = create_driver
97
+ m1 = d.instance.format_metrics('test.', record)
98
+ assert_equal m1, { 'test.dstat.total_cpu_usage.usr' => 0.0, 'test.dstat.total_cpu_usage.sys' => 0.0, 'test.dstat.total_cpu_usage.idl' => 100.0, 'test.dstat.total_cpu_usage.wai' => 0.0, 'test.dstat.total_cpu_usage.hiq' => 0.0, 'test.dstat.total_cpu_usage.siq' => 0.0 }
99
+
100
+ d = create_driver(CONFIG_NAME_KEYS)
101
+ m1 = d.instance.format_metrics('test.', record)
102
+ assert_equal m1, { 'test.dstat.total_cpu_usage.usr' => 0.0, 'test.dstat.total_cpu_usage.sys' => 0.0, 'test.dstat.total_cpu_usage.idl' => 100.0 }
103
+
104
+ d = create_driver(CONFIG_TAG_FOR_IGNORE)
105
+ m1 = d.instance.format_metrics('test.', record)
106
+ assert_equal m1, { 'dstat.total_cpu_usage.usr' => 0.0, 'dstat.total_cpu_usage.sys' => 0.0, 'dstat.total_cpu_usage.idl' => 100.0 }
107
+
108
+ d = create_driver(CONFIG_TAG_FOR_SUFFIX)
109
+ m1 = d.instance.format_metrics('test.', record)
110
+ assert_equal m1, { 'dstat.total_cpu_usage.usr.test' => 0.0, 'dstat.total_cpu_usage.sys.test' => 0.0, 'dstat.total_cpu_usage.idl.test' => 100.0 }
111
+ end
112
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-graphite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Satoshi SUZUKI
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.17
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.17
27
+ - !ruby/object:Gem::Dependency
28
+ name: fluent-mixin-rewrite-tag-name
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: graphite-api
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: fluentd output plugin to send metrics to graphite
70
+ email: studio3104.com@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".gitignore"
76
+ - Gemfile
77
+ - LICENSE
78
+ - README.md
79
+ - Rakefile
80
+ - fluent-plugin-graphite.gemspec
81
+ - lib/fluent/plugin/out_graphite.rb
82
+ - test/helper.rb
83
+ - test/plugin/test_out_graphite.rb
84
+ homepage: https://github.com/studio3104/fluent-plugin-graphite
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.2.2
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: fluentd output plugin to send metrics to graphite
108
+ test_files:
109
+ - test/helper.rb
110
+ - test/plugin/test_out_graphite.rb