fluent-plugin-mackerel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MTA0MzM4MTQ2MTk3OTM4ZTUxNzA3YTBiYmFjOGNiZmY2NjI1MDc4MQ==
5
+ data.tar.gz: !binary |-
6
+ NTE3NDRiNDM3MzQ5YTA4MGEzOTIwMmY1NTE1NGE5NzJhOGExNWJjYw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YmQxN2IyZGY0OGEzODJmMzYzYTgyNzM1MzI3OGI1ZTBiNmRjMGQ4MTY4OGNm
10
+ N2U0MzE4MjZmMjM2OTJmNzM3MDBiNTAyZDIwYzdiNzJlYzg2OGQzN2NiNTNk
11
+ ZTZmYjEwMTI5Njk0ZGU3NGZhNmFkN2NhYzYyNGFiNmYzMzEzMDQ=
12
+ data.tar.gz: !binary |-
13
+ ODRhN2I4YzhjMmQxMmFjZWFjNTg4NjMzNmViNDQ0N2QwYTNhNTBkNjhkOWUw
14
+ MmEwZjRiMTJjN2QwMDU4ZWYwYmM0NWQ4Y2Y3NjE4ZTQ0M2ZiM2Y2MGU4MTFl
15
+ Yjg1NDc0MThkNzQxYzJiM2RjNjQ2YTZlOTI3ODdlOTY3YTEyY2E=
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
19
+ vendor/bundle
20
+ test_out_mackerel_send.rb
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-mackerel.gemspec
4
+ gemspec
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2014- SOMEDA Takashi
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,69 @@
1
+ # fluent-plugin-mackerel
2
+
3
+ ## Overview
4
+
5
+ [Fluentd](http://fluentd.org) plugin to send metrics to [mackerel](http://mackerel.io/).
6
+
7
+ ## Installation
8
+
9
+ Install with gem or fluent-gem command as:
10
+
11
+ ```
12
+ # for fluentd
13
+ $ gem install fluent-plugin-typetalk
14
+
15
+ # for td-agent
16
+ $ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-typetalk
17
+ ```
18
+
19
+ ## Configuration
20
+
21
+ ### Usage
22
+
23
+ This plugin uses [APIv0](http://help-ja.mackerel.io/entry/spec/api/v0) of mackerel.io.
24
+ ```
25
+ <match ...>
26
+ type mackerel
27
+ api_key 123456
28
+ hostid xyz
29
+ metrics_prefix http_status
30
+ out_keys 2xx_count,3xx_count,4xx_count,5xx_count
31
+ </match>
32
+ ```
33
+
34
+ Then the sent metric data will look like this:
35
+ ```
36
+ {
37
+ "hostId": "xyz",
38
+ "name": "http_status.2xx_count",
39
+ "time": 1399997498,
40
+ "value": 100.0
41
+ }
42
+ ```
43
+ As shown above, metric name will be a concatenation of metrics_prefix and out_keys values.
44
+
45
+ ## TODO
46
+
47
+ Pull requests are very welcome!!
48
+
49
+ ## For developers
50
+
51
+ You have to run the command below when starting development.
52
+ ```
53
+ $ bundle install --path vendor/bundle
54
+ ```
55
+
56
+ To run tests, do the following.
57
+ ```
58
+ $ VERBOSE=1 bundle exec rake test
59
+ ```
60
+
61
+ When releasing, call rake release as follows.
62
+ ```
63
+ $ bundle exec rake release
64
+ ```
65
+
66
+ ## Copyright
67
+
68
+ * Copyright (c) 2014- Takashi Someda ([@tksmd](http://twitter.com/tksmd/))
69
+ * Apache License, Version 2.0
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-mackerel"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["tksmd"]
9
+ spec.email = ["someda@isenshi.com"]
10
+ spec.description = %q{fluent plugin to send metrics to mackerel.io}
11
+ spec.summary = spec.description
12
+ spec.homepage = "https://github.com/tksmd/fluent-plugin-mackerel"
13
+ spec.license = "Apache-2.0"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rr", ">= 1.0.0"
23
+ spec.add_runtime_dependency "fluentd"
24
+
25
+ spec.required_ruby_version = '>= 1.9.3'
26
+ end
@@ -0,0 +1,109 @@
1
+ module Fluent
2
+ class MackerelOutput < Fluent::BufferedOutput
3
+ Fluent::Plugin.register_output('mackerel', self)
4
+
5
+ config_param :api_key, :string
6
+ config_param :hostid, :string, :default => nil
7
+ config_param :hostid_path, :string, :default => nil
8
+ config_param :metrics_prefix, :string
9
+ config_param :out_keys, :string
10
+
11
+ config_param :flush_interval, :time, :default => 1
12
+
13
+ attr_reader :mackerel
14
+
15
+ # Define `log` method for v0.10.42 or earlier
16
+ unless method_defined?(:log)
17
+ define_method("log") { $log }
18
+ end
19
+
20
+ def initialize
21
+ super
22
+ end
23
+
24
+ def configure(conf)
25
+ super
26
+
27
+ @mackerel = Mackerel.new(conf['api_key'])
28
+ @out_keys = @out_keys.split(',')
29
+
30
+ if @hostid.nil? and @hostid_path.nil?
31
+ raise Fluent::ConfigError, "Either 'hostid' or 'hostid_path' must be specifed."
32
+ end
33
+
34
+ unless @hostid_path.nil?
35
+ @hostid = File.open(@hostid_path).read
36
+ end
37
+
38
+ end
39
+
40
+ def start
41
+ super
42
+ end
43
+
44
+ def shutdown
45
+ super
46
+ end
47
+
48
+ def format(tag, time, record)
49
+ [tag, time, record].to_msgpack
50
+ end
51
+
52
+ def write(chunk)
53
+ metrics = []
54
+ chunk.msgpack_each do |(tag,time,record)|
55
+ out_keys.map do |key|
56
+ metrics << {
57
+ 'hostId' => @hostid,
58
+ 'value' => record[key].to_f,
59
+ 'time' => time,
60
+ 'name' => "%s.%s" % [@metrics_prefix, key]
61
+ }
62
+ end
63
+ end
64
+
65
+ begin
66
+ @mackerel.post_metrics(metrics)
67
+ rescue => e
68
+ log.error("out_mackerel:", :error_class => e.class, :error => e.message)
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ class Mackerel
75
+
76
+ USER_AGENT = "fluent-plugin-mackerel Ruby/#{RUBY_VERSION}"
77
+
78
+ def initialize(api_key)
79
+ require 'net/http'
80
+ require 'json'
81
+
82
+ @api_key = api_key
83
+ @http = Net::HTTP.new('mackerel.io', 443)
84
+ @http.use_ssl = true
85
+ end
86
+
87
+ def post_metrics(metrics)
88
+ req = Net::HTTP::Post.new('/api/v0/tsdb', initheader = {
89
+ 'X-Api-Key' => @api_key,
90
+ 'Content-Type' =>'application/json',
91
+ 'User-Agent' => USER_AGENT
92
+ })
93
+ req.body = metrics.to_json
94
+ res = @http.request(req)
95
+
96
+ if res.is_a?(Net::HTTPUnauthorized)
97
+ raise MackerelError, "invalid api key used. check api_key in your configuration."
98
+ end
99
+
100
+ unless res and res.is_a?(Net::HTTPSuccess)
101
+ raise MackerelError, "failed to post, code: #{res.code}"
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ class MackerelError < RuntimeError; end
108
+
109
+ end
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'rr'
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_mackerel'
27
+
28
+ class Test::Unit::TestCase
29
+ end
@@ -0,0 +1,64 @@
1
+ require 'helper'
2
+
3
+ class MackerelOutputTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ CONFIG = %[
10
+ type mackerel
11
+ api_key 123456
12
+ hostid xyz
13
+ metrics_prefix service
14
+ out_keys val1,val2,val3
15
+ ]
16
+
17
+ CONFIG_NOHOST = %[
18
+ type mackerel
19
+ api_key 123456
20
+ metrics_prefix service
21
+ out_keys val1,val2,val3
22
+ ]
23
+
24
+ def create_driver(conf = CONFIG, tag='test')
25
+ Fluent::Test::BufferedOutputTestDriver.new(Fluent::MackerelOutput, tag).configure(conf)
26
+ end
27
+
28
+ def test_configure
29
+
30
+ assert_raise(Fluent::ConfigError) {
31
+ d = create_driver('')
32
+ }
33
+
34
+ assert_raise(Fluent::ConfigError) {
35
+ d = create_driver(CONFIG_NOHOST)
36
+ }
37
+
38
+ d = create_driver()
39
+ assert_equal d.instance.instance_variable_get(:@api_key), '123456'
40
+ assert_equal d.instance.instance_variable_get(:@hostid), 'xyz'
41
+ assert_equal d.instance.instance_variable_get(:@metrics_prefix), 'service'
42
+ assert_equal d.instance.instance_variable_get(:@out_keys), ['val1','val2','val3']
43
+ end
44
+
45
+ def test_write
46
+ d = create_driver()
47
+ stub(d.instance.mackerel).post_metrics([
48
+ {"hostId"=>"xyz", "value"=>1.0, "time"=>1399997498, "name"=>"service.val1"},
49
+ {"hostId"=>"xyz", "value"=>2.0, "time"=>1399997498, "name"=>"service.val2"},
50
+ {"hostId"=>"xyz", "value"=>3.0, "time"=>1399997498, "name"=>"service.val3"},
51
+ {"hostId"=>"xyz", "value"=>5.0, "time"=>1399997498, "name"=>"service.val1"},
52
+ {"hostId"=>"xyz", "value"=>6.0, "time"=>1399997498, "name"=>"service.val2"},
53
+ {"hostId"=>"xyz", "value"=>7.0, "time"=>1399997498, "name"=>"service.val3"},
54
+ ])
55
+
56
+ ENV["TZ"]="Asia/Tokyo"
57
+ t = Time.strptime('2014-05-14 01:11:38', '%Y-%m-%d %T')
58
+ d.emit({'val1' => 1, 'val2' => 2, 'val3' => 3, 'val4' => 4}, t)
59
+ d.emit({'val1' => 5, 'val2' => 6, 'val3' => 7, 'val4' => 8}, t)
60
+ d.run()
61
+ end
62
+
63
+
64
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-mackerel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - tksmd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
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: rr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: fluentd
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: fluent plugin to send metrics to mackerel.io
70
+ email:
71
+ - someda@isenshi.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - fluent-plugin-mackerel.gemspec
83
+ - lib/fluent/plugin/out_mackerel.rb
84
+ - test/helper.rb
85
+ - test/plugin/test_out_mackerel.rb
86
+ homepage: https://github.com/tksmd/fluent-plugin-mackerel
87
+ licenses:
88
+ - Apache-2.0
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: 1.9.3
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.2
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: fluent plugin to send metrics to mackerel.io
110
+ test_files:
111
+ - test/helper.rb
112
+ - test/plugin/test_out_mackerel.rb