fluent-plugin-websocket 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-websocket.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2013 IZAWA Tetsu (@moccos)
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,79 @@
1
+ # Fluent::Plugin::Websocket
2
+
3
+ Fluentd websocket output plugin.
4
+
5
+ ## Installation
6
+
7
+ Copy __out_websocket.rb__ into your fluentd plugin directory.
8
+
9
+ Default plugin directory is _/etc/fluent/plugin_. You can specify additional location by _-p_ option. (Please see _fluentd -h_)
10
+
11
+ This plugin depends on [__em-websocket__](https://github.com/igrigorik/em-websocket) module. You can install it by _gem install em-websocket_.
12
+
13
+
14
+ ## Configuration
15
+ <match foo.**>
16
+ type websocket
17
+ host 192.168.1.1 # default: 0.0.0.0 (ANY)
18
+ port 8080 # default: 8080
19
+ use_msgpack false # default: false
20
+ add_time false # default: false
21
+ add_tag true # default: true
22
+ </match>
23
+
24
+ - __host__: WebSocket server IP address.
25
+ - __port__: WebSocket server port.
26
+ - __use\_msgpack__: Send [MessagePack](http://msgpack.org/) format binary. Otherwise, you send JSON format text.
27
+ - __add\_time__: Add timestamp to the data.
28
+ - __add\_tag__: Add fluentd tag to the data.
29
+
30
+ If there are no websocket connections, this plugin silently discards data. You may use _out\_copy_ plugin like this:
31
+
32
+ <match foo.**>
33
+ type copy
34
+ <store>
35
+ type file
36
+ path /var/log/foo/bar.log
37
+ </store>
38
+ <store>
39
+ type websocket
40
+ port 8080
41
+ </store>
42
+ </match>
43
+
44
+ ## Data format
45
+ [tag, timestamp, data_object]
46
+
47
+ - tag is appended when _add\_tag_ option is true.
48
+ - timespamp is appended when _add\_time_ option is true.
49
+
50
+ ### Example
51
+ curl -X POST -d 'json={"action":"login","user":6}' http://localhost:8888/foo/bar
52
+
53
+ ["foo.bar",1364699026,{"action":"login","user":6}]
54
+
55
+ ## Client sample
56
+ ### JSON format (use_msgpack: false)
57
+ function onMessage(evt) {
58
+ data = JSON.parse(evt.data);
59
+ ...
60
+ }
61
+
62
+ ### Msgpack format binary (use_msgpack: true)
63
+ Extract data by [msgpack.js](https://github.com/msgpack/msgpack-javascript).
64
+
65
+ websocket.binaryType = "arraybuffer"
66
+ ...
67
+ function onMessage(evt) {
68
+ data = msgpack.unpack(new Uint8Array(evt.data))
69
+ ...
70
+ }
71
+
72
+ ## Contributing
73
+
74
+ 1. Fork it
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create new Pull Request
79
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/plugin/test*.rb']
8
+ t.verbose = true
9
+ end
10
+ task :default => :test
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "fluent-plugin-websocket"
6
+ gem.version = "0.1.2"
7
+ gem.authors = ["IZAWA Tetsu (@moccos)"]
8
+ gem.email = ["tt.izawa@gmail.com"]
9
+ gem.homepage = "https://github.com/moccos/fluent-plugin-websocket"
10
+ gem.summary = %q{Fluentd websocket output plugin}
11
+ gem.description = %q{Fluentd websocket output plugin}
12
+ gem.required_ruby_version = ">= 1.9.2"
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_development_dependency "rake"
20
+ gem.add_development_dependency "fluentd"
21
+ gem.add_development_dependency "websocket-ocket-eventmachine-client"
22
+ gem.add_development_dependency "msgpack"
23
+ gem.add_runtime_dependency "fluentd"
24
+ gem.add_runtime_dependency "em-websocket"
25
+ end
@@ -0,0 +1,82 @@
1
+ # Copyright (C) 2013 IZAWA Tetsu (@moccos)
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.
14
+
15
+ require 'em-websocket'
16
+ require 'thread'
17
+
18
+ module Fluent
19
+ $lock = Mutex::new
20
+ $channel = EM::Channel.new
21
+
22
+ class WebSocketOutput < Fluent::Output
23
+ Fluent::Plugin.register_output('websocket', self)
24
+ config_param :use_msgpack, :bool, :default => false
25
+ config_param :host, :string, :default => "0.0.0.0"
26
+ config_param :port, :integer, :default => 8080
27
+ config_param :add_time, :bool, :default => false
28
+ config_param :add_tag, :bool, :default => true
29
+
30
+ def configure(conf)
31
+ super
32
+ $thread = Thread.new do
33
+ $log.trace "Started em-websocket thread."
34
+ $log.info "WebSocket server #{@host}:#{@port} [msgpack: #{@use_msgpack}]"
35
+ EM.run {
36
+ EM::WebSocket.run(:host => @host, :port => @port) do |ws|
37
+ ws.onopen { |handshake|
38
+ callback = @use_msgpack ? proc{|msg| ws.send_binary(msg)} : proc{|msg| ws.send(msg)}
39
+ $lock.synchronize do
40
+ sid = $channel.subscribe callback
41
+ $log.trace "WebSocket connection: ID " + sid.to_s
42
+ ws.onclose {
43
+ $log.trace "Connection closed: ID " + sid.to_s
44
+ $lock.synchronize do
45
+ $channel.unsubscribe(sid)
46
+ end
47
+ }
48
+ end
49
+
50
+ #ws.onmessage { |msg|
51
+ #}
52
+ }
53
+ end
54
+ }
55
+ end
56
+ end
57
+
58
+ def start
59
+ super
60
+ end
61
+
62
+ def shutdown
63
+ super
64
+ EM.stop
65
+ Thread::kill($thread)
66
+ $log.trace "Killed em-websocket thread."
67
+ end
68
+
69
+ def emit(tag, es, chain)
70
+ chain.next
71
+ es.each {|time,record|
72
+ data = [record]
73
+ if (@add_time) then data.unshift(time) end
74
+ if (@add_tag) then data.unshift(tag) end
75
+ output = @use_msgpack ? data.to_msgpack : data.to_json
76
+ $lock.synchronize do
77
+ $channel.push output
78
+ end
79
+ }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,76 @@
1
+ require 'json'
2
+ require 'msgpack'
3
+ require 'fluent/test'
4
+ require 'fluent/plugin/out_websocket'
5
+ require 'websocket-eventmachine-client'
6
+
7
+ class WebSocketForTest
8
+ def initialize(key, n)
9
+ @n_received = 0
10
+ @v_received = []
11
+
12
+ @ws = WebSocket::EventMachine::Client.connect(:uri => 'ws://localhost:8080')
13
+ @ws.onmessage do |msg, type|
14
+ #puts "Received message: #{msg.to_s} / #{type.to_s}"
15
+ data = type == :text ? JSON.parse(msg): MessagePack.unpack(msg)
16
+ @v_received.push(data[0][key])
17
+ @n_received += 1
18
+ if (n == @n_received)
19
+ @ws.close()
20
+ end
21
+ end
22
+ end
23
+
24
+ attr_reader :n_received, :v_received
25
+ end
26
+
27
+ class WebSocketOutputTest < Test::Unit::TestCase
28
+ def setup
29
+ Fluent::Test.setup
30
+ v_str = "sekaiichi kawaiiyo"
31
+ v_int = -1234567
32
+ v_double = -123.4567
33
+ @key = "key"
34
+ @values = [v_str, v_int, v_double]
35
+ end
36
+
37
+ CONFIG = %[
38
+ ]
39
+
40
+ def create_driver(conf = CONFIG)
41
+ Fluent::Test::OutputTestDriver.new(Fluent::WebSocketOutput).configure(conf)
42
+ end
43
+
44
+ def impl_test(d)
45
+ sleep(0.2)
46
+ ws = WebSocketForTest.new(@key, @values.length)
47
+ sleep(0.2)
48
+ for v in @values
49
+ d.emit({@key => v}, 0)
50
+ end
51
+ sleep(0.5)
52
+ assert_equal(@values.length, ws.n_received)
53
+ result = ws.v_received
54
+ for i in 0 .. @values.length
55
+ assert_equal(@values[i], result[i])
56
+ end
57
+ end
58
+
59
+ # TODO: How to test another configuration?
60
+ #def test_json_out
61
+ #d = create_driver %[
62
+ #use_msgpack false
63
+ #add_tag false
64
+ #]
65
+ #impl_test(d)
66
+ #end
67
+
68
+ def test_msgpack_out
69
+ d = create_driver %[
70
+ use_msgpack true
71
+ add_tag false
72
+ ]
73
+ impl_test(d)
74
+ end
75
+
76
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-websocket
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - IZAWA Tetsu (@moccos)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: fluentd
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: websocket-ocket-eventmachine-client
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: msgpack
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: fluentd
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: em-websocket
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: Fluentd websocket output plugin
111
+ email:
112
+ - tt.izawa@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - Gemfile
119
+ - LICENSE.txt
120
+ - README.md
121
+ - Rakefile
122
+ - fluent-plugin-websocket.gemspec
123
+ - lib/fluent/plugin/out_websocket.rb
124
+ - test/plugin/test_out_websocket.rb
125
+ homepage: https://github.com/moccos/fluent-plugin-websocket
126
+ licenses: []
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: 1.9.2
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 1.8.25
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: Fluentd websocket output plugin
149
+ test_files:
150
+ - test/plugin/test_out_websocket.rb