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.
- checksums.yaml +15 -0
- data/.gitignore +20 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +69 -0
- data/Rakefile +10 -0
- data/fluent-plugin-mackerel.gemspec +26 -0
- data/lib/fluent/plugin/out_mackerel.rb +109 -0
- data/test/helper.rb +29 -0
- data/test/plugin/test_out_mackerel.rb +64 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -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=
|
data/.gitignore
ADDED
@@ -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
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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
|
data/test/helper.rb
ADDED
@@ -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
|