fluent-plugin-wendelin 0.1.alpha1
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 +7 -0
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +49 -0
- data/example/to_wendelin.conf +90 -0
- data/fluent-plugin-wendelin.gemspec +17 -0
- data/lib/fluent/plugin/out_wendelin.rb +88 -0
- data/lib/fluent/plugin/wendelin_client.rb +98 -0
- data/test/ingest-torture.rb +20 -0
- data/test/ingest.rb +11 -0
- data/test/wendelin_test.rb +22 -0
- metadata +69 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 690acc01d3867ddd46c6cb0709553e512aeafad6
|
4
|
+
data.tar.gz: 3186bc8fe9cb69b7700d13a4b907e6b3a78f0553
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74bcf2e5e9aecb28cb4966d49382b73d6ec803337e0e6cdaaf022c1a86aaf00ab2287c5cb1610d23eddd6220ea71129b84cb9f851bfa25934662f5ab2f5ffae2
|
7
|
+
data.tar.gz: 09b83cf665ee08f06b1114e717b169e14660d3de01bfac97679cfb951b600f68b5d24eb18f574e882ca69578ad3ee417ccb45ec3b80072f856239ba1105c81c8
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (C) 2015 Nexedi SA and Contributors
|
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,49 @@
|
|
1
|
+
fluent-plugin-wendelin
|
2
|
+
======================
|
3
|
+
|
4
|
+
This is output plugin for [Fluentd][] to forward data to [Wendelin][] system.
|
5
|
+
|
6
|
+
[Fluentd]: http://fluentd.org/
|
7
|
+
[Wendelin]: http://wendelin.io/
|
8
|
+
|
9
|
+
|
10
|
+
Configuration
|
11
|
+
-------------
|
12
|
+
|
13
|
+
A sample configuration to setup ingestion of data for a tag to Wendelin:
|
14
|
+
|
15
|
+
```apache
|
16
|
+
<match your.sensor.tag>
|
17
|
+
@type wendelin
|
18
|
+
@id wendelin_out
|
19
|
+
|
20
|
+
streamtool_uri <Wendelin_URL>/erp5/portal_ingestion_policies/<YOUR_INGESTION_POLICY_ID>
|
21
|
+
user <your_wendelin_user>
|
22
|
+
password <your_wendelin_password>
|
23
|
+
|
24
|
+
# all parameters of BufferedOutput & Output classes are supported too, e.g.
|
25
|
+
# `buffer_type`, `flush_interval`, `num_threads`, `log_level`, etc - see
|
26
|
+
# their code near:
|
27
|
+
#
|
28
|
+
# https://github.com/fluent/fluentd/blob/master/lib/fluent/output.rb#L182
|
29
|
+
#
|
30
|
+
# logging setup description:
|
31
|
+
#
|
32
|
+
# http://docs.fluentd.org/articles/logging
|
33
|
+
|
34
|
+
buffer_type memory
|
35
|
+
#buffer_path "#{ENV['HOME']/var}"
|
36
|
+
flush_interval 5s
|
37
|
+
</match>
|
38
|
+
```
|
39
|
+
|
40
|
+
See *example/to_wendelin.conf* for fully setup example.
|
41
|
+
|
42
|
+
|
43
|
+
TODO
|
44
|
+
----
|
45
|
+
|
46
|
+
- make content to be posted over HTTP as raw (instead of urlencode data).
|
47
|
+
- HTTPS certificates are currently not verified.
|
48
|
+
- X.509 certificates instead of user / password.
|
49
|
+
- cleanup
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Example configuration of Wendelin output for Fluentd
|
2
|
+
|
3
|
+
## built-in TCP input, so we can accept messages from other fluentd(s) and so
|
4
|
+
## that fluent-cat works:
|
5
|
+
## $ echo <json|msgpack> | fluent-cat <tag>
|
6
|
+
<source>
|
7
|
+
@type forward
|
8
|
+
@id forward_input
|
9
|
+
</source>
|
10
|
+
|
11
|
+
|
12
|
+
# HTTP input
|
13
|
+
# http://localhost:8888/<tag>?json=<json>
|
14
|
+
<source>
|
15
|
+
@type http
|
16
|
+
@id http_input
|
17
|
+
port 8888
|
18
|
+
</source>
|
19
|
+
|
20
|
+
|
21
|
+
## output tag=sensor.** to Wendelin
|
22
|
+
<match <YOUR_SENSOR_TAG>.**>
|
23
|
+
@type wendelin
|
24
|
+
@id wendelin_out
|
25
|
+
|
26
|
+
streamtool_uri <Wendelin_URL>/erp5/portal_ingestion_policies/<YOUR_INGESTION_POLICY_ID>
|
27
|
+
# TODO ^^^ do not check peer's certificate
|
28
|
+
user <your_wendelin_user>
|
29
|
+
password <your_wendelin_password>
|
30
|
+
|
31
|
+
# all parameters of BufferedOutput & Output classes are supported too, e.g.
|
32
|
+
# `buffer_type`, `flush_interval`, `num_threads`, `log_level`, etc - see
|
33
|
+
# their code near:
|
34
|
+
#
|
35
|
+
# https://github.com/fluent/fluentd/blob/master/lib/fluent/output.rb#L182
|
36
|
+
#
|
37
|
+
# logging setup description:
|
38
|
+
#
|
39
|
+
# http://docs.fluentd.org/articles/logging
|
40
|
+
|
41
|
+
buffer_type memory
|
42
|
+
#buffer_path "#{ENV['HOME']/var}"
|
43
|
+
flush_interval 5s
|
44
|
+
</match>
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
# ---- monitoring & debugging ----
|
50
|
+
|
51
|
+
|
52
|
+
# Listen HTTP for monitoring
|
53
|
+
# http://localhost:24220/api/plugins
|
54
|
+
# http://localhost:24220/api/plugins?type=TYPE
|
55
|
+
# http://localhost:24220/api/plugins?tag=MYTAG
|
56
|
+
<source>
|
57
|
+
@type monitor_agent
|
58
|
+
@id monitor_agent_input
|
59
|
+
|
60
|
+
port 24220
|
61
|
+
</source>
|
62
|
+
|
63
|
+
# Listen DRb for debug
|
64
|
+
<source>
|
65
|
+
@type debug_agent
|
66
|
+
@id debug_agent_input
|
67
|
+
|
68
|
+
bind 127.0.0.1
|
69
|
+
port 24230
|
70
|
+
</source>
|
71
|
+
|
72
|
+
|
73
|
+
## match tag=debug.** and dump to console
|
74
|
+
<match debug.**>
|
75
|
+
@type stdout
|
76
|
+
@id stdout_output
|
77
|
+
</match>
|
78
|
+
|
79
|
+
|
80
|
+
## match fluent's internal events
|
81
|
+
#<match fluent.**>
|
82
|
+
# @type null
|
83
|
+
#</match>
|
84
|
+
|
85
|
+
## match not matched logs and write to file
|
86
|
+
#<match **>
|
87
|
+
# @type file
|
88
|
+
# path /var/log/fluent/else
|
89
|
+
# compress gz
|
90
|
+
#</match>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = "fluent-plugin-wendelin"
|
3
|
+
gem.version = "0.1.alpha1"
|
4
|
+
gem.authors = ["Kirill Smelkov"]
|
5
|
+
gem.email = ["kirr@nexedi.com"]
|
6
|
+
gem.summary = %q{Fluentd output to Wendelin}
|
7
|
+
gem.description = %q{Fluentd output plugin to forward data to Wendelin system}
|
8
|
+
gem.homepage = "https://lab.nexedi.cn/nexedi/fluent-plugin-wendelin"
|
9
|
+
gem.license = "APLv2"
|
10
|
+
|
11
|
+
gem.files = `git ls-files -z`.split("\x0")
|
12
|
+
gem.require_paths = ["lib"]
|
13
|
+
|
14
|
+
gem.add_runtime_dependency "fluentd", "~> 0"
|
15
|
+
# ? net/http
|
16
|
+
# ? openssl
|
17
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Fluentd output plugin to ingest data to Wendelin system
|
2
|
+
# Copyright (C) 2015 Nexedi SA and Contributors.
|
3
|
+
# Kirill Smelkov <kirr@nexedi.com>
|
4
|
+
#
|
5
|
+
# This program is free software: you can Use, Study, Modify and Redistribute
|
6
|
+
# it under the terms of the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
|
19
|
+
# This plugin hooks into Fluentd in a way similiar to out_forward and
|
20
|
+
# out_secure_forward and outputs event stream to a Wendelin HTTP endpoint.
|
21
|
+
|
22
|
+
require 'fluent/output'
|
23
|
+
require_relative 'wendelin_client'
|
24
|
+
|
25
|
+
|
26
|
+
module Fluent
|
27
|
+
|
28
|
+
class WendelinOutput < ObjectBufferedOutput # XXX verify base class
|
29
|
+
Plugin.register_output('wendelin', self)
|
30
|
+
|
31
|
+
# where Wendelin's Input Stream Tool is located,
|
32
|
+
# ex http://example.com/erp5/portal_ingestion_policies/example_ingestion
|
33
|
+
config_param :streamtool_uri, :string
|
34
|
+
|
35
|
+
# credentials to authenticate this fluentd to wendelin
|
36
|
+
# by default credentials are not used
|
37
|
+
# TODO user/password -> certificate
|
38
|
+
config_param :user, :string, :default => nil
|
39
|
+
config_param :password, :string, :default => nil
|
40
|
+
|
41
|
+
|
42
|
+
def configure(conf)
|
43
|
+
super
|
44
|
+
|
45
|
+
credentials = {}
|
46
|
+
if @user
|
47
|
+
credentials['user'] = @user
|
48
|
+
credentials['password'] = @password
|
49
|
+
end
|
50
|
+
@wendelin = WendelinClient.new(@streamtool_uri, credentials)
|
51
|
+
end
|
52
|
+
|
53
|
+
def start
|
54
|
+
super
|
55
|
+
# TODO
|
56
|
+
end
|
57
|
+
|
58
|
+
def shutdown
|
59
|
+
super
|
60
|
+
# TODO
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# hooked to ObjectBufferedOutput - write out records from a buffer chunk for a tag.
|
65
|
+
#
|
66
|
+
# NOTE this is called from a separate thread (see OutputThread and BufferedOutput)
|
67
|
+
def write_objects(tag, chunk)
|
68
|
+
# NOTE if this fail and raises -> it will unroll to BufferedOutput#try_flush
|
69
|
+
# which detects errors and retries outputting logs up to retry maxcount
|
70
|
+
# times and aborts outputting current logs if all try fail.
|
71
|
+
#
|
72
|
+
# This way, we don't need to code rescue here.
|
73
|
+
|
74
|
+
# NOTE tag is 1, and chunk stores an event stream, usually [] of
|
75
|
+
# (timestamp, record) in msgpack, but it general it could be arbitrary
|
76
|
+
# data - we send it as-is.
|
77
|
+
data_chunk = chunk.read()
|
78
|
+
|
79
|
+
# for input_stream_ref use tag as-is - it will be processed/translated
|
80
|
+
# further on server by Wendelin
|
81
|
+
reference = tag
|
82
|
+
|
83
|
+
@wendelin.ingest(reference, data_chunk)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# module to ingest data to a Wendelin through HTTP endpoint
|
2
|
+
# Copyright (C) 2015 Nexedi SA and Contributors.
|
3
|
+
# Kirill Smelkov <kirr@nexedi.com>
|
4
|
+
#
|
5
|
+
# This program is free software: you can Use, Study, Modify and Redistribute
|
6
|
+
# it under the terms of the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
|
19
|
+
require 'net/http'
|
20
|
+
require 'openssl'
|
21
|
+
|
22
|
+
# show request/response traces or not
|
23
|
+
$trace = false
|
24
|
+
|
25
|
+
|
26
|
+
# class representing a Wendelin client
|
27
|
+
class WendelinClient
|
28
|
+
|
29
|
+
# `streamtool_uri` - URI pointing to portal_input_data_stream "mountpoint"
|
30
|
+
# `credentials` # {'user' => _, 'password' => _} TODO change to certificate
|
31
|
+
def initialize(streamtool_uri, credentials)
|
32
|
+
@streamtool_uri = streamtool_uri
|
33
|
+
@credentials = credentials
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# ingest `data_chunk` to a stream referenced as `reference`
|
38
|
+
def ingest(reference, data_chunk)
|
39
|
+
uri = URI("#{@streamtool_uri}/ingest?reference=#{reference}")
|
40
|
+
req = Net::HTTP::Post.new(uri)
|
41
|
+
if @credentials.has_key?('user')
|
42
|
+
req.basic_auth @credentials['user'], @credentials['password']
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO ensure content-type is 'raw', e.g. this way
|
46
|
+
# (but then querystring ?reference=... is lost)
|
47
|
+
# req.body = data_chunk
|
48
|
+
# req.content_type = 'application/octet-stream'
|
49
|
+
req.set_form_data('data_chunk' => data_chunk)
|
50
|
+
|
51
|
+
if $trace
|
52
|
+
puts '>>> REQUEST'
|
53
|
+
puts "method\t=> #{req.method}"
|
54
|
+
puts "path\t=> #{req.path}"
|
55
|
+
puts "uri\t=> #{req.uri}"
|
56
|
+
puts "body\t=> #{req.body}"
|
57
|
+
puts "body_stream\t=> #{req.body_stream}"
|
58
|
+
req.each {|h| puts "#{h}:\t#{req[h]}"}
|
59
|
+
puts
|
60
|
+
end
|
61
|
+
|
62
|
+
begin
|
63
|
+
# TODO keep connection open (so that every new ingest does not do
|
64
|
+
# full connect again)
|
65
|
+
res = Net::HTTP.start(uri.hostname, uri.port,
|
66
|
+
:use_ssl => (uri.scheme == 'https'),
|
67
|
+
# NOTE = "do not check server cert"
|
68
|
+
# TODO move this out to conf parameters
|
69
|
+
:verify_mode => OpenSSL::SSL::VERIFY_NONE
|
70
|
+
) do |http|
|
71
|
+
http.request(req)
|
72
|
+
end
|
73
|
+
|
74
|
+
rescue
|
75
|
+
# some http/ssl/other connection error
|
76
|
+
puts "HTTP ERROR:"
|
77
|
+
raise
|
78
|
+
|
79
|
+
else
|
80
|
+
if $trace
|
81
|
+
puts '>>> RESPONSE'
|
82
|
+
res.each {|h| puts "#{h}:\t#{res[h]}"}
|
83
|
+
puts "code\t=> #{res.code}"
|
84
|
+
puts "msg\t=> #{res.message}"
|
85
|
+
puts "class\t=> #{res.class}"
|
86
|
+
puts "body:", res.body
|
87
|
+
end
|
88
|
+
|
89
|
+
if res.kind_of?(Net::HTTPSuccess) # res.code is 2XX
|
90
|
+
#puts "ingested ok"
|
91
|
+
else
|
92
|
+
puts "FAIL:"
|
93
|
+
res.value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# ingest several data streams concurently forever
|
3
|
+
require_relative 'wendelin_test'
|
4
|
+
|
5
|
+
def runingest(stream_ref)
|
6
|
+
i = 0
|
7
|
+
while true
|
8
|
+
data_chunk = ", #{i} (#{stream_ref})"
|
9
|
+
#puts "ingest #{stream_ref}, #{data_chunk}"
|
10
|
+
ingest stream_ref, data_chunk
|
11
|
+
i = i + 1
|
12
|
+
sleep 0.1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
t31 = Thread.new { runingest 'ABC-HELLO-01.cat' }
|
18
|
+
t32 = Thread.new { runingest 'ABC-HELLO-01.tac' }
|
19
|
+
|
20
|
+
t31.join # wait forever
|
data/test/ingest.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# manually test erp5_data_streams ingestion via Ruby HTTP lib
|
3
|
+
# XXX draft/stub
|
4
|
+
|
5
|
+
require_relative 'wendelin_test'
|
6
|
+
require 'msgpack'
|
7
|
+
|
8
|
+
#puts [1,2,'hello'].to_msgpack
|
9
|
+
ingest 'ABC-HELLO-01.cat', [1,2,'hello'].to_msgpack
|
10
|
+
#ingest 'ABC-HELLO-01.cat', ', hello'
|
11
|
+
#ingest 'ABC-HELLO-01.tac', ', magic'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# simple ingest() for wendelin tests
|
2
|
+
# (without need for providing streamtool uri, credentials, etc)
|
3
|
+
|
4
|
+
# load wendelin_clinet.rb from in-tree
|
5
|
+
here = File.dirname(__FILE__)
|
6
|
+
$LOAD_PATH << File.expand_path(File.join(here, '../lib'))
|
7
|
+
require 'fluent/plugin/wendelin_client'
|
8
|
+
|
9
|
+
# FIXME hardcoded
|
10
|
+
$user = 'user'
|
11
|
+
$password = 'password'
|
12
|
+
|
13
|
+
# FIXME hardcoded & shortcut for tests
|
14
|
+
$erp5 = "https://example.com/erp5" # erp5 root
|
15
|
+
$streamtool = "#{$erp5}/portal_input_data_streams" # where Input Stream Tool is mounted
|
16
|
+
|
17
|
+
$wendelin = WendelinClient.new($streamtool, {'user' => $user, 'password' => $password})
|
18
|
+
|
19
|
+
|
20
|
+
def ingest(input_stream_ref, data_chunk)
|
21
|
+
$wendelin.ingestDataChunk(input_stream_ref, data_chunk)
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-wendelin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.alpha1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kirill Smelkov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-25 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'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Fluentd output plugin to forward data to Wendelin system
|
28
|
+
email:
|
29
|
+
- kirr@nexedi.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- Gemfile
|
36
|
+
- LICENSE.txt
|
37
|
+
- README.md
|
38
|
+
- example/to_wendelin.conf
|
39
|
+
- fluent-plugin-wendelin.gemspec
|
40
|
+
- lib/fluent/plugin/out_wendelin.rb
|
41
|
+
- lib/fluent/plugin/wendelin_client.rb
|
42
|
+
- test/ingest-torture.rb
|
43
|
+
- test/ingest.rb
|
44
|
+
- test/wendelin_test.rb
|
45
|
+
homepage: https://lab.nexedi.cn/nexedi/fluent-plugin-wendelin
|
46
|
+
licenses:
|
47
|
+
- APLv2
|
48
|
+
metadata: {}
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.3.1
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 2.2.2
|
66
|
+
signing_key:
|
67
|
+
specification_version: 4
|
68
|
+
summary: Fluentd output to Wendelin
|
69
|
+
test_files: []
|