logstash-filter-zeromq 0.1.2

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
+ SHA1:
3
+ metadata.gz: e3dcdef0b8b0bcd244c53f52988a55af838825ef
4
+ data.tar.gz: 0d5bf5f6fa3781c2a0a9d7a82dd312d882e4cf59
5
+ SHA512:
6
+ metadata.gz: 936eff3ec8d09106d1186e69a5efc0f689b221961eebb18dc2b4f2d8b03e595da41314ca4c9c7cc19d2384b97400426e702528c5ab6bf009e9f54f158f03c7d9
7
+ data.tar.gz: d53c4b023a10ac06d8726d0a6f9171a503de0fe74a538550f8543374eeddc3fec2397eb324752a58290a956e1ba617d3b317238287b163b4c82cc0953022cafa
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ .bundle
4
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+ gem "logstash", :github => "elasticsearch/logstash", :branch => "1.5"
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ @files=[]
2
+
3
+ task :default do
4
+ system("rake -T")
5
+ end
6
+
7
+ require "logstash/devutils/rake"
@@ -0,0 +1,214 @@
1
+ # encoding: utf-8
2
+ require "logstash/filters/base"
3
+ require "logstash/namespace"
4
+
5
+ # ZeroMQ filter. This is the best way to send an event externally for filtering
6
+ # It works much like an exec filter would by sending the event "offsite"
7
+ # for processing and waiting for a response
8
+ #
9
+ # The protocol here is:
10
+ # * REQ sent with JSON-serialized logstash event
11
+ # * REP read expected to be the full JSON 'filtered' event
12
+ # * - if reply read is an empty string, it will cancel the event.
13
+ #
14
+ # Note that this is a limited subset of the zeromq functionality in
15
+ # inputs and outputs. The only topology that makes sense here is:
16
+ # REQ/REP.
17
+ class LogStash::Filters::ZeroMQ < LogStash::Filters::Base
18
+
19
+ config_name "zeromq"
20
+ milestone 1
21
+
22
+ # 0mq socket address to connect or bind
23
+ # Please note that inproc:// will not work with logstash
24
+ # as we use a context per thread
25
+ # By default, filters connect
26
+ config :address, :validate => :string, :default => "tcp://127.0.0.1:2121"
27
+
28
+ # The field to send off-site for processing
29
+ # If this is unset, the whole event will be sent
30
+ # TODO (lusis)
31
+ # Allow filtering multiple fields
32
+ config :field, :validate => :string
33
+
34
+ # 0mq mode
35
+ # server mode binds/listens
36
+ # client mode connects
37
+ config :mode, :validate => ["server", "client"], :default => "client"
38
+
39
+ # timeout in milliseconds on which to wait for a reply.
40
+ config :timeout, :validate => :number, :default => 500
41
+
42
+ # number of retries, used for both sending and receiving messages.
43
+ # for sending, retries should return instantly.
44
+ # for receiving, the total blocking time is up to retries X timeout,
45
+ # which by default is 3 X 500 = 1500ms
46
+ config :retries, :validate => :number, :default => 3
47
+
48
+ # tag to add if zeromq timeout expires before getting back an answer.
49
+ # If set to "" then no tag will be added.
50
+ config :add_tag_on_timeout, :validate => :string, :default => "zeromqtimeout"
51
+
52
+ # 0mq socket options
53
+ # This exposes zmq_setsockopt
54
+ # for advanced tuning
55
+ # see http://api.zeromq.org/2-1:zmq-setsockopt for details
56
+ #
57
+ # This is where you would set values like:
58
+ # ZMQ::HWM - high water mark
59
+ # ZMQ::IDENTITY - named queues
60
+ # ZMQ::SWAP_SIZE - space for disk overflow
61
+ # ZMQ::SUBSCRIBE - topic filters for pubsub
62
+ #
63
+ # example: sockopt => ["ZMQ::HWM", 50, "ZMQ::IDENTITY", "my_named_queue"]
64
+ config :sockopt, :validate => :hash
65
+
66
+ public
67
+ def initialize(params)
68
+ super(params)
69
+
70
+ @threadsafe = false
71
+ end
72
+
73
+ public
74
+ def register
75
+ require "ffi-rzmq"
76
+ require "logstash/util/zeromq"
77
+ self.class.send(:include, LogStash::Util::ZeroMQ)
78
+ connect
79
+ end #def register
80
+
81
+ public
82
+ def teardown
83
+ close
84
+ super()
85
+ end #def teardown
86
+
87
+ private
88
+ def close
89
+ @logger.debug("0mq: closing socket.")
90
+ @poller.deregister(@zsocket, ZMQ::POLLIN)
91
+ @zsocket.close
92
+ end #def close
93
+
94
+ private
95
+ def connect
96
+ @logger.debug("0mq: connecting socket")
97
+ @zsocket = context.socket(ZMQ::REQ)
98
+ error_check(@zsocket.setsockopt(ZMQ::LINGER, 0),
99
+ "while setting ZMQ::LINGER == 0)")
100
+ @poller = ZMQ::Poller.new
101
+ @poller.register(@zsocket, ZMQ::POLLIN)
102
+
103
+ if @sockopt
104
+ #TODO: should make sure that ZMQ::LINGER and ZMQ::POLLIN are not changed
105
+ setopts(@zsocket, @sockopt)
106
+ end
107
+
108
+ setup(@zsocket, @address)
109
+ end #def connect
110
+
111
+ private
112
+ def reconnect
113
+ close
114
+ connect
115
+ end #def reconnect
116
+
117
+ #send and receive data. message is assumed to be json
118
+ #will return a boolean for success, and a string containing one of several things:
119
+ # - empty string: response from server
120
+ # - updated string: response from server
121
+ # - original message: could not send request or get response from server in time
122
+ private
123
+ def send_recv(message)
124
+ success = false
125
+ @retries.times do
126
+ @logger.debug("0mq: sending", :request => message)
127
+ rc = @zsocket.send_string(message)
128
+ if ZMQ::Util.resultcode_ok?(rc)
129
+ success = true
130
+ break
131
+ else
132
+ @logger.debug("0mq: error sending message (zmq_errno = #{ZMQ::Util.errno}, zmq_error_string = '#{ZMQ::Util.error_string}'")
133
+ reconnect
134
+ end #if resultcode
135
+ end #retries.times
136
+
137
+ #if we did not succeed log it and fail here.
138
+ if not success
139
+ @logger.warn("0mq: error sending message (zmq_errno = #{ZMQ::Util.errno}, zmq_error_string = '#{ZMQ::Util.error_string}'")
140
+ return success, message
141
+ end
142
+
143
+ #now get reply
144
+ reply = ''
145
+ success = false
146
+ @retries.times do
147
+ @logger.debug("0mq: polling for reply for #{@timeout}ms.")
148
+ #poll the socket. If > 0, something to read. If < 0, error. If zero, loop
149
+ num_readable = @poller.poll(@timeout)
150
+ if num_readable > 0
151
+ #something to read, do it.
152
+ rc = @zsocket.recv_string(reply)
153
+ @logger.debug("0mq: message received, checking error")
154
+ error_check(rc, "in recv_string")
155
+ success = true
156
+ break
157
+ elsif num_readable < 0
158
+ #error, reconnect
159
+ close
160
+ connect
161
+ end
162
+ end # @retries.times
163
+
164
+ #if we maxed out on number of retries, then set reply to message so that
165
+ #the event isn't cancelled. we want to carry on if the server is down.
166
+ if not success
167
+ @logger.warn("0mq: did not receive reply (zmq_errno = #{ZMQ::Util.errno}, zmq_error_string = '#{ZMQ::Util.error_string}'")
168
+ return success, message
169
+ end
170
+
171
+ return success, reply
172
+ end #def send_recv
173
+
174
+ public
175
+ def filter(event)
176
+ return unless filter?(event)
177
+
178
+ begin
179
+ if @field
180
+ success, reply = send_recv(event[@field])
181
+ else
182
+ success, reply = send_recv(event.to_json)
183
+ end
184
+ # If we receive an empty reply, this is an indication that the filter
185
+ # wishes to cancel this event.
186
+ if reply.empty?
187
+ @logger.debug("0mq: recieved empty reply, cancelling event.")
188
+ event.cancel
189
+ return
190
+ end
191
+ @logger.debug("0mq: receiving", :reply => reply)
192
+ if @field
193
+ event[@field] = event.sprintf(reply)
194
+ filter_matched(event)
195
+ else
196
+ reply = JSON.parse(reply)
197
+ event.overwrite(reply)
198
+ end
199
+ filter_matched(event)
200
+ #if message send/recv was not successful add the timeout
201
+ if not success
202
+ (event["tags"] ||= []) << @add_tag_on_timeout
203
+ end
204
+ rescue => e
205
+ @logger.warn("0mq filter exception", :address => @address, :exception => e, :backtrace => e.backtrace)
206
+ end
207
+ end # def filter
208
+
209
+ private
210
+ def server?
211
+ @mode == "server"
212
+ end # def server?
213
+
214
+ end # class LogStash::Filters::ZeroMQ
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = 'logstash-filter-zeromq'
4
+ s.version = '0.1.2'
5
+ s.licenses = ['Apache License (2.0)']
6
+ s.summary = "ZeroMQ filter. This is a way to send an event externally for filtering"
7
+ s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
8
+ s.authors = ["Elasticsearch"]
9
+ s.email = 'info@elasticsearch.com'
10
+ s.homepage = "http://www.elasticsearch.org/guide/en/logstash/current/index.html"
11
+ s.require_paths = ["lib"]
12
+
13
+ # Files
14
+ s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
15
+
16
+ # Tests
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+
19
+ # Special flag to let us know this is actually a logstash plugin
20
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
21
+
22
+ # Gem dependencies
23
+ s.add_runtime_dependency 'logstash', '>= 1.4.0', '< 2.0.0'
24
+
25
+ s.add_runtime_dependency 'ffi-rzmq', ['1.0.0']
26
+
27
+ s.add_development_dependency 'logstash-devutils'
28
+ end
29
+
@@ -0,0 +1,6 @@
1
+ require "logstash/devutils/rspec/spec_helper"
2
+ require 'logstash/filters/zeromq'
3
+
4
+ describe LogStash::Filters::ZeroMQ do
5
+
6
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-filter-zeromq
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Elasticsearch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.0
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.0
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 1.4.0
28
+ - - <
29
+ - !ruby/object:Gem::Version
30
+ version: 2.0.0
31
+ prerelease: false
32
+ type: :runtime
33
+ - !ruby/object:Gem::Dependency
34
+ name: ffi-rzmq
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 1.0.0
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - '='
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.0
45
+ prerelease: false
46
+ type: :runtime
47
+ - !ruby/object:Gem::Dependency
48
+ name: logstash-devutils
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ prerelease: false
60
+ type: :development
61
+ description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
62
+ email: info@elasticsearch.com
63
+ executables: []
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - .gitignore
68
+ - Gemfile
69
+ - Rakefile
70
+ - lib/logstash/filters/zeromq.rb
71
+ - logstash-filter-zeromq.gemspec
72
+ - spec/filters/zeromq_spec.rb
73
+ homepage: http://www.elasticsearch.org/guide/en/logstash/current/index.html
74
+ licenses:
75
+ - Apache License (2.0)
76
+ metadata:
77
+ logstash_plugin: 'true'
78
+ logstash_group: filter
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.4.4
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: ZeroMQ filter. This is a way to send an event externally for filtering
99
+ test_files:
100
+ - spec/filters/zeromq_spec.rb