fluent-plugin-mackerel 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.
@@ -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