fluent-plugin-machinist 0.1.0

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
+ SHA256:
3
+ metadata.gz: 02f43bc747c5bd41cad3df6747d1b622ddf94649ec5026f0921976ad1fa0229c
4
+ data.tar.gz: 6db613f11cf3223fdb011bdd7d839262ea17c4f02154245cb12b03e41e5a8fc2
5
+ SHA512:
6
+ metadata.gz: 80f598d5491ee42fe2239945b1db42faa398a60bf3667e6c9cddc42f786d6694b887a00d343d8475c815d424c696a7e6b8c2de490a94159839e99b644eedaf41
7
+ data.tar.gz: 1fe1c7d18c5c1465d584e9189e78d003fd346de65cb6ec24f0a783af5a5ae9c9c87721693e1d7cd775da131e1ac22475f94f0aea932fd1905df14b75d7300983
data/.gitignore ADDED
@@ -0,0 +1,17 @@
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
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Naoya Kaneko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # Fluent::Plugin::Machinist
2
+
3
+ ## Overview
4
+
5
+
6
+ [Fluentd](http://fluentd.org/) input plugin that forwards record to Machinist
7
+
8
+ - [Machinist](https://machinist.iij.jp/)
9
+
10
+
11
+ ## Installation
12
+
13
+ install from rubygems
14
+
15
+ ```
16
+ gem install fluent-plugin-machinist
17
+ or
18
+ fluent-gem install fluent-plugin-machinist
19
+ ```
20
+
21
+ or build and install
22
+
23
+ ```
24
+ git clone https://github.com/iij/fluent-plugin-machinist.git
25
+ cd fluent-plugin-machinist
26
+ rake build
27
+ gem install pkg/fluent-plugin-machinist-0.1.0.gem
28
+ ```
29
+
30
+ ## Configuration
31
+
32
+ ```
33
+ <match test.***>
34
+ @type machinist
35
+
36
+ endpoint_url https://gw.machinist.iij.jp/gateway
37
+ agent_id WHATEVER_AGENT_ID_HERE
38
+ api_key WHATEVER_API_KEY_HERE
39
+ use_ssl true
40
+ verify_ssl true
41
+
42
+ value_key temp
43
+
44
+ # optional parameters
45
+ namespace mydesk
46
+ tags floor:17F,sensor:wionode
47
+ </match>
48
+ ```
49
+
50
+ ```
51
+ <match test.***>
52
+ @type machinist
53
+
54
+ endpoint_url https://gw.machinist.iij.jp/gateway
55
+ agent_id WHATEVER_AGENT_ID_HERE
56
+ api_key WHATEVER_API_KEY_HERE
57
+ use_ssl true
58
+ verify_ssl true
59
+
60
+ value_keys temp,humid
61
+
62
+ # optional parameters
63
+ namespace_key location
64
+ tag_keys floor,sensor
65
+ </match>
66
+ ```
67
+
68
+
69
+ **endpoint\_url**
70
+
71
+ URL where the plugin does POST record (required).
72
+
73
+ **agent\_id**
74
+
75
+ Agent ID is used to authenticate to endpoint\_url (required).
76
+
77
+ **api_key**
78
+
79
+ Key used to authenticate to endpoint\_url (required).
80
+
81
+ **use\_ssl**
82
+
83
+ Whether the plugin use ssl to communicate endpoint\_url. Required to be true if
84
+ endpoint\_url is "https://".
85
+ (Default: false)
86
+
87
+ **value\_key**
88
+
89
+ Specifying which key and value to be used as Machinist metric.
90
+ The plugin extracts entry with matching key in record and expand key,value into "name","value" hash.
91
+
92
+ ```
93
+ Example:
94
+ if
95
+ recored is {"hoge":"fuga", "temp": "28.0", "humid": "50.0" }
96
+ "value_key" is "temp"
97
+ then
98
+ generates metrics as [{"name": "temp", "value": 28.0}]
99
+ ```
100
+
101
+ Either value\_key or value\_keys is mutually required.
102
+
103
+ **value\_keys**
104
+
105
+ Specifying which keys and values to be used as Machinist metric.
106
+ Unlike value\_key, this accepts array of keys.
107
+
108
+ ```
109
+ Example:
110
+ if
111
+ recored is {"hoge":"fuga", "temp": "28.0", "humid": "50.0" }
112
+ "value_keys" is "temp,humid"
113
+ then
114
+ generates metrics as [{"name": "temp", "value": 28.0}, {"name": "humid", "value": 50.0}]
115
+ ```
116
+
117
+ value\_keys is mutually exclusive with value\_key.
118
+
119
+ **namespace**
120
+
121
+ Specifying static namespace to be used in metric (string).
122
+
123
+
124
+ ```
125
+ if
126
+ namespace is "mydesk"
127
+ recored is {"hoge":"fuga", "temp": "28.0", "humid": "50.0" }
128
+ "value_key" is "temp"
129
+ then
130
+ generates metrics as [{"name":"temp", "value":28.0, "namespace":"mydesk"]
131
+ ```
132
+
133
+ **namespace\_key**
134
+
135
+ Extracts namespace from value for specified key in record (array).
136
+
137
+ ```
138
+ if
139
+ namespace_key is "location"
140
+ recored is {"hoge":"fuga", "temp": "28.0", "humid": "50.0", "location":"myhome" }
141
+ "value_key" is "temp"
142
+ then
143
+ generates metrics as [{"name":"temp", "value":28.0, "namespace":"myhome"]
144
+ ```
145
+
146
+ **tags**
147
+
148
+ Specifying static tags to be used in metric (hash).
149
+
150
+ ```
151
+ if
152
+ tags is "floor:17F,sensor:wionode"
153
+ recored is {"hoge":"fuga", "temp": "28.0", "humid": "50.0", "location":"myhome" }
154
+ "value_key" is "temp"
155
+ then
156
+ generates metrics as [{"name":"temp", "value":28.0, "tags":{"floor":"17F", "sensor":"wionode"}}]
157
+ ```
158
+
159
+ **tag\_keys**
160
+
161
+ Extracts tags from specified keys in record (array).
162
+
163
+ ```
164
+ if
165
+ tag_keys is "floor,sensor"
166
+ recored is {"hoge":"fuga", "temp": "28.0", "humid": "50.0", "location":"myhome", "floor":"18F", "sensor":"wionode" }
167
+ "value\_key" is "temp"
168
+ then
169
+ generates metrics as [{"name":"temp", "value":28.0, "tags":{"floor":"18F", "sensor":"wionode"}}]
170
+ ```
171
+
172
+ ## TODO
173
+
174
+ - "meta" support
175
+
176
+ ## Contributing
177
+
178
+ Bug reports and pull requests are welcome on GitHub at https://github.com/iij/fluent-plugin-machinist
179
+
180
+
181
+ ## License
182
+
183
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
184
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs.push("lib", "test")
8
+ t.test_files = FileList["test/**/test_*.rb"]
9
+ t.verbose = true
10
+ t.warning = true
11
+ end
12
+
13
+ task default: [:test]
@@ -0,0 +1,27 @@
1
+ <source>
2
+ @type exec
3
+ tag airport
4
+ command /bin/sh test.sh
5
+ format json
6
+ run_interval 5s
7
+ </source>
8
+
9
+ <match airport.**>
10
+ @type copy
11
+ <store>
12
+ @type stdout
13
+ </store>
14
+ <store>
15
+ @type machinist
16
+
17
+ endpoint_url https://gw.machinist.iij.jp/gateway
18
+ agent_id XXXXXXXXXX
19
+ api_key XXXXXX
20
+
21
+ value_keys rssi,noise
22
+
23
+ namespace macbookpro01
24
+
25
+ tag_keys ssid
26
+ </store>
27
+ </match>
data/example/test.sh ADDED
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # This is Wi-Fi scanning script for testing
3
+ # Example {"rssi": -47, "noise": -96, "ssid": "test_ssid"}
4
+ airport -I | awk '{gsub(/ /,"", $0);print $1}' | awk -F ':' '/^agrCtlRSSI/{rssi = int($2)} /^agrCtlNoise/{noise = int($2)} /^SSID/{ssid = $2} END {printf "{\"rssi\": %d, \"noise\": %d, \"ssid\": \"%s\"}", rssi, noise, ssid}'
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "fluent-plugin-machinist"
6
+ spec.version = "0.1.0"
7
+ spec.authors = ["Naoya Kaneko"]
8
+ spec.email = ["enukane@glenda9.org"]
9
+
10
+ spec.summary = %q{Fluent output plugin for IIJ Machinist}
11
+ spec.description = %q{Fluent output plubin for IIJ Machinist}
12
+ spec.homepage = "https://github.com/iij/fluent-plugin-machinist"
13
+ spec.license = "MIT"
14
+
15
+ test_files, files = `git ls-files -z`.split("\x0").partition do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.files = files
19
+ spec.executables = files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = test_files
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.14"
24
+ spec.add_development_dependency "rake", "~> 12.0"
25
+ spec.add_development_dependency "test-unit", "~> 3.0"
26
+ spec.add_runtime_dependency "fluentd", [">= 0.14.10", "< 2"]
27
+ end
@@ -0,0 +1,127 @@
1
+ #
2
+ # Copyright 2019- Naoya Kaneko
3
+ #
4
+
5
+ require "fluent/plugin/output"
6
+
7
+ module Fluent
8
+ module Plugin
9
+ class MachinistOutput < Fluent::Plugin::Output
10
+ Fluent::Plugin.register_output("machinist", self)
11
+
12
+ def initialize
13
+ super
14
+ require "net/http"
15
+ require "uri"
16
+ end
17
+
18
+ # authentication and access requirements
19
+ config_param :endpoint_url, :string
20
+ config_param :agent_id, :string
21
+ config_param :api_key, :string
22
+ config_param :use_ssl, :bool, :default => true
23
+ config_param :verify_ssl, :bool, :default => true
24
+
25
+ # name & value selection
26
+ config_param :value_key, :string, :default => nil
27
+ config_param :value_keys, :array, value_type: :string, :default => nil
28
+
29
+ # specifying statistically
30
+ ## namespace
31
+ config_param :namespace, :string, :default => nil # namespace string (static)
32
+ config_param :namespace_key, :string, :default => nil #TBD: use value for specified hash entry for namespace
33
+ config_param :tags, :hash, :default => nil # specify tags hash (static)
34
+ config_param :tag_keys, :array, value_type: :string, :default => nil #
35
+
36
+ def start
37
+ super
38
+ end
39
+
40
+ def shutdown
41
+ super
42
+ end
43
+
44
+ def process(tag, es)
45
+ es.each do |time, record|
46
+ handle_record(tag, time, record)
47
+ end
48
+ end
49
+
50
+ def handle_record(tag, time, record)
51
+ data = create_payload(tag, time, record)
52
+
53
+ send_request(data)
54
+ end
55
+
56
+ def create_payload(tag, time, record)
57
+ metrics = []
58
+ @value_keys = [@value_key] if @value_key
59
+ ns = if @namespace
60
+ @namespace
61
+ elsif @namespace_key
62
+ record[@namespace_key]
63
+ else
64
+ nil
65
+ end
66
+ tags = if @tags
67
+ @tags
68
+ elsif @tag_keys
69
+ @tag_keys.map{|key|
70
+ [key, record[key].to_s]
71
+ }.to_h
72
+ else
73
+ nil
74
+ end
75
+
76
+ metrics += @value_keys.map{|key|
77
+ metric = {
78
+ :name => key,
79
+ :value => record[key].to_f
80
+ }
81
+ metric[:namespace] = ns if ns
82
+ metric[:tags] = tags if tags
83
+ metric
84
+ }
85
+
86
+ json = {
87
+ :agent_id => @agent_id,
88
+ :api_key => @api_key,
89
+ :metrics => metrics
90
+ }
91
+
92
+ return JSON.dump(json)
93
+ end
94
+
95
+ def send_request(data)
96
+ url = URI(@endpoint_url)
97
+ http = Net::HTTP.new(url.host, url.port)
98
+ if @use_ssl
99
+ http.use_ssl = true
100
+ http.ca_file = OpenSSL::X509::DEFAULT_CERT_FILE
101
+ unless @verify_ssl
102
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
103
+ end
104
+ end
105
+
106
+ req = Net::HTTP::Post.new(url)
107
+ req["content-type"] = 'application/json'
108
+
109
+ req.body = data
110
+ res = http.request(req)
111
+
112
+ unless res and res.is_a?(Net::HTTPSuccess)
113
+ summary = if res
114
+ "#{res.code} #{res.message} #{res.body}"
115
+ else
116
+ "res=nil"
117
+ end
118
+ $log.warn "failed to #{req.method} #{url} #{summary}"
119
+ end
120
+ rescue => e
121
+ $log.warn "Net::HTTP.#{req.method.capitalize} raises exception : #{e.class}, '#{e.message}'"
122
+ raise e
123
+ end
124
+
125
+ end
126
+ end
127
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.expand_path("../../", __FILE__))
2
+ require "test-unit"
3
+ require "fluent/test"
4
+ require "fluent/test/driver/output"
5
+ require "fluent/test/helpers"
6
+
7
+ Test::Unit::TestCase.include(Fluent::Test::Helpers)
8
+ Test::Unit::TestCase.extend(Fluent::Test::Helpers)
@@ -0,0 +1,46 @@
1
+ require "helper"
2
+ require "fluent/plugin/out_machinist.rb"
3
+
4
+ class MachinistOutputTest < Test::Unit::TestCase
5
+ setup do
6
+ Fluent::Test.setup
7
+ end
8
+
9
+ CONFIG = %[
10
+ endpoint_url https://example.org/gateway
11
+ agent_id THIS_IS_AGENTID
12
+ api_key THIS_IS_API_KEY
13
+ use_ssl true
14
+ verify_ssl true
15
+
16
+ value_key VALUE_KEY
17
+ value_keys VALUE_KEY0,VALUE_KEY1
18
+
19
+ namespace NAMESPACE
20
+ namespace_key NAMESPACE_KEY
21
+
22
+ tags TAG_KEY0:TAG_VALUE0,TAG_KEY1:TAG_VALUE1
23
+ tag_keys TAG_KEY2,TAG_KEY3
24
+ ]
25
+
26
+ test "configure" do
27
+ d = create_driver(CONFIG)
28
+
29
+ assert_equal "https://example.org/gateway", d.instance.endpoint_url
30
+ assert_equal "THIS_IS_AGENTID", d.instance.agent_id
31
+ assert_equal "THIS_IS_API_KEY", d.instance.api_key
32
+ assert_true d.instance.use_ssl
33
+ assert_true d.instance.verify_ssl
34
+ assert_equal "VALUE_KEY", d.instance.value_key
35
+ assert_equal ["VALUE_KEY0","VALUE_KEY1"], d.instance.value_keys
36
+ assert_equal "NAMESPACE", d.instance.namespace
37
+ assert_equal({"TAG_KEY0"=>"TAG_VALUE0", "TAG_KEY1"=>"TAG_VALUE1"}, d.instance.tags)
38
+ assert_equal ["TAG_KEY2", "TAG_KEY3"], d.instance.tag_keys
39
+ end
40
+
41
+ private
42
+
43
+ def create_driver(conf)
44
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::MachinistOutput).configure(conf)
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-machinist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Naoya Kaneko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-09 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.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.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.14.10
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '2'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 0.14.10
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '2'
75
+ description: Fluent output plubin for IIJ Machinist
76
+ email:
77
+ - enukane@glenda9.org
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".gitignore"
83
+ - Gemfile
84
+ - LICENSE
85
+ - README.md
86
+ - Rakefile
87
+ - example/test-fluentd.conf
88
+ - example/test.sh
89
+ - fluent-plugin-machinist.gemspec
90
+ - lib/fluent/plugin/out_machinist.rb
91
+ - test/helper.rb
92
+ - test/plugin/test_out_machinist.rb
93
+ homepage: https://github.com/iij/fluent-plugin-machinist
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.0.6
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Fluent output plugin for IIJ Machinist
116
+ test_files:
117
+ - test/helper.rb
118
+ - test/plugin/test_out_machinist.rb