logstash-input-bunny 0.1.11 → 0.1.12
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 +4 -4
- data/lib/logstash/inputs/bunny.rb +139 -148
- data/logstash-input-bunny.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5c4dbbe89ddbb17aeacca3faecf3647eecced04
|
4
|
+
data.tar.gz: 645754ffc7b545fd97188364d5e556e1fd0474c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f64cf8c7e46897dee3c0245452045deb1589f1bd7d08e9e1f21ab8c78848177ccb6876d67a32cf99c342f787f04b66fa7e8bc71f275392285d27fd6a7e454bc4
|
7
|
+
data.tar.gz: b2371829cd2ea89ea4d5e8c9e51f40414bf1cac3dca0ed7bcaf96b658a29715e35b51ced95b581fd2a74b2b9d72854c53cac3804378408309441b5eca8437740
|
@@ -13,222 +13,213 @@ require "logstash/inputs/rabbitmq/bunny"
|
|
13
13
|
#
|
14
14
|
# * Bunny - <https://github.com/ruby-amqp/bunny>
|
15
15
|
class LogStash::Inputs::Bunny < LogStash::Inputs::Threadable
|
16
|
-
|
17
16
|
config_name "bunny"
|
18
17
|
|
19
18
|
#
|
20
19
|
# Connection
|
21
20
|
#
|
22
21
|
|
23
|
-
|
24
|
-
config :
|
25
|
-
|
26
|
-
|
27
|
-
config :
|
28
|
-
|
29
|
-
# RabbitMQ username
|
30
|
-
config :user, :validate => :string, :default => "guest"
|
31
|
-
|
32
|
-
# RabbitMQ password
|
33
|
-
config :password, :validate => :password, :default => "guest"
|
22
|
+
config :host, validate: :string, required: true
|
23
|
+
config :port, validate: :number, default: 5672
|
24
|
+
config :user, validate: :string, default: "guest"
|
25
|
+
config :password, validate: :password, default: "guest"
|
26
|
+
config :vhost, validate: :string, default: "/"
|
34
27
|
|
35
|
-
|
36
|
-
config :
|
28
|
+
config :ssl, validate: :boolean, :default => false
|
29
|
+
config :ssl_cert, validate: :string
|
30
|
+
config :ssl_key, validate: :string
|
31
|
+
config :ssl_ca_cert, validate: :string
|
32
|
+
config :verify_peer, validate: :boolean, default: false
|
37
33
|
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
config :ssl_key, :validate => :string
|
42
|
-
config :ssl_ca_cert, :validate => :string
|
43
|
-
|
44
|
-
# Validate SSL certificate
|
45
|
-
config :verify_ssl, :validate => :boolean, :default => false
|
46
|
-
config :verify_peer, :validate => :boolean, :default => false
|
34
|
+
#
|
35
|
+
# Queue & Consumer
|
36
|
+
#
|
47
37
|
|
48
|
-
#
|
49
|
-
|
38
|
+
#
|
39
|
+
# The Bunny plugin's approach differs from Logstash's RabbitMQ plugin in that
|
40
|
+
# we require an exchange so that we can create & bind multiple queues based
|
41
|
+
# on routing keys.
|
42
|
+
#
|
43
|
+
# In addition, rather than accepting a single string for the queue, we now
|
44
|
+
# accept a hash of queue > routing_key pairs.
|
45
|
+
#
|
50
46
|
|
47
|
+
config :exchange, validate: :string, required: true
|
48
|
+
config :queues, validate: :hash, required: true
|
51
49
|
|
50
|
+
config :prefetch, validate: :number, default: 20
|
51
|
+
config :ack, validate: :boolean, default: true
|
52
52
|
|
53
53
|
#
|
54
|
-
# Queue
|
54
|
+
# Queue Durability / Persistence
|
55
55
|
#
|
56
56
|
|
57
|
-
#
|
58
|
-
config :
|
57
|
+
# Create durable queues so that they survive broker restarts
|
58
|
+
config :durable, validate: :boolean, default: false
|
59
59
|
|
60
|
-
#
|
61
|
-
config :
|
62
|
-
|
63
|
-
# Should the queue be deleted on the broker when the last consumer
|
64
|
-
# disconnects? Set this option to `false` if you want the queue to remain
|
65
|
-
# on the broker, queueing up messages until a consumer comes along to
|
66
|
-
# consume them.
|
67
|
-
config :auto_delete, :validate => :boolean, :default => false
|
60
|
+
# Delete queues once the last consumer disconnects.
|
61
|
+
config :auto_delete, validate: :boolean, default: false
|
68
62
|
|
69
63
|
# Is the queue exclusive? Exclusive queues can only be used by the connection
|
70
64
|
# that declared them and will be deleted when it is closed (e.g. due to a Logstash
|
71
65
|
# restart).
|
72
|
-
config :exclusive,
|
73
|
-
|
74
|
-
# Extra queue arguments as an array.
|
75
|
-
# To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
|
76
|
-
config :arguments, :validate => :array, :default => {}
|
66
|
+
config :exclusive, validate: :boolean, default: false
|
77
67
|
|
78
|
-
#
|
79
|
-
config :
|
68
|
+
# Passive queue creation? Useful for checking queue existance without modifying server state
|
69
|
+
config :passive, validate: :boolean, default: false
|
80
70
|
|
81
|
-
#
|
82
|
-
|
71
|
+
#
|
72
|
+
# Initialization
|
73
|
+
#
|
83
74
|
|
84
|
-
|
85
|
-
|
75
|
+
def initialize(params)
|
76
|
+
params["codec"] = "json" if !params["codec"]
|
77
|
+
super
|
78
|
+
end
|
86
79
|
|
80
|
+
def input_tag
|
81
|
+
"#{@vhost}/#{@exchange}"
|
82
|
+
end
|
87
83
|
|
84
|
+
def message(severity, message, data={})
|
85
|
+
message = "Bunny[#{input_tag}] #{message}"
|
86
|
+
@logger.send(severity, message, data)
|
87
|
+
end
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
#
|
89
|
+
def register
|
90
|
+
require "bunny"
|
92
91
|
|
93
|
-
|
94
|
-
#
|
95
|
-
# The name of the exchange to bind the queue to.
|
96
|
-
config :exchange, :validate => :string
|
92
|
+
message(:info, "registering input", host: @host)
|
97
93
|
|
98
|
-
|
99
|
-
|
100
|
-
# The routing key to use when binding a queue to the exchange.
|
101
|
-
# This is only relevant for direct or topic exchanges.
|
102
|
-
#
|
103
|
-
# * Routing keys are ignored on fanout exchanges.
|
104
|
-
# * Wildcards are not valid on direct exchanges.
|
105
|
-
config :key, :validate => :string, :default => "logstash"
|
94
|
+
@vhost ||= Bunny::DEFAULT_HOST
|
95
|
+
@port ||= AMQ::Protocol::DEFAULT_PORT
|
106
96
|
|
97
|
+
@settings = {
|
98
|
+
vhost: @vhost,
|
99
|
+
host: @host,
|
100
|
+
port: @port,
|
101
|
+
user: @user,
|
102
|
+
pass: @password.value,
|
103
|
+
tls: @ssl,
|
104
|
+
automatically_recover: false
|
105
|
+
}
|
107
106
|
|
108
|
-
|
109
|
-
|
107
|
+
if @ssl
|
108
|
+
@settings[:verify_peer] = @verify_peer
|
109
|
+
end
|
110
110
|
|
111
|
-
|
111
|
+
if @ssl and @ssl_cert
|
112
|
+
@settings[:tls_cert] = @ssl_cert
|
113
|
+
@settings[:tls_key] = @ssl_key
|
114
|
+
@settings[:tls_ca_certificates] = [@ssl_ca_cert] if @ssl_ca_cert
|
115
|
+
end
|
112
116
|
end
|
113
117
|
|
114
|
-
include ::LogStash::Inputs::RabbitMQ::BunnyImpl
|
115
|
-
|
116
118
|
def run(output_queue)
|
117
119
|
@output_queue = output_queue
|
120
|
+
delay = Bunny::Session::DEFAULT_NETWORK_RECOVERY_INTERVAL * 2
|
118
121
|
|
119
122
|
begin
|
120
123
|
setup
|
121
124
|
consume
|
122
|
-
rescue Bunny::NetworkFailure, Bunny::ConnectionClosedError,
|
123
|
-
Bunny::ConnectionLevelException, Bunny::TCPConnectionFailed
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
@logger.error("RabbitMQ[#{input_name}] connection error: #{e.message}. Will attempt to reconnect in #{n} seconds...")
|
132
|
-
|
133
|
-
sleep n
|
134
|
-
retry
|
135
|
-
|
136
|
-
rescue OpenSSL::SSL::SSLError => e
|
137
|
-
n = Bunny::Session::DEFAULT_NETWORK_RECOVERY_INTERVAL * 2
|
125
|
+
rescue Bunny::NetworkFailure, Bunny::ConnectionClosedError,
|
126
|
+
Bunny::ConnectionLevelException, Bunny::TCPConnectionFailed,
|
127
|
+
OpenSSL::SSL::SSLError => e
|
128
|
+
|
129
|
+
@consumers.each do |name, consumer|
|
130
|
+
error = "connection error: #{e.message}. Retrying in #{delay} seconds."
|
131
|
+
message(:error, error)
|
132
|
+
consumer.channel.maybe_kill_consumer_work_pool!
|
133
|
+
end
|
138
134
|
|
139
|
-
|
140
|
-
sleep n
|
135
|
+
sleep delay
|
141
136
|
retry
|
142
137
|
|
143
138
|
rescue LogStash::ShutdownSignal
|
144
|
-
|
145
|
-
|
146
|
-
rescue Exception => e
|
147
|
-
@logger.error("RabbitMQ[#{input_name}] unhandled exception: #{e.inspect}")
|
148
|
-
@logger.error(e.backtrace)
|
149
|
-
end
|
150
|
-
end
|
139
|
+
release
|
151
140
|
|
152
|
-
|
153
|
-
|
141
|
+
rescue Exception => e
|
142
|
+
message(:error, "unhandled exception: #{e.inspect}", backtrace: e.backtrace)
|
154
143
|
|
155
|
-
if @ssl and @ssl_cert
|
156
|
-
@settings[:tls_cert] = @ssl_cert
|
157
|
-
@settings[:tls_key] = @ssl_key
|
158
|
-
@settings[:tls_ca_certificates] = [@ssl_ca_cert] if @ssl_ca_cert
|
159
|
-
@settings[:verify_peer] = @verify_peer
|
160
144
|
end
|
161
145
|
end
|
162
146
|
|
163
147
|
def teardown
|
164
|
-
|
165
|
-
@ch.close if @ch && @ch.open?
|
166
|
-
@conn.close if @conn && @conn.open?
|
148
|
+
release
|
167
149
|
finished
|
168
150
|
end
|
169
151
|
|
170
|
-
protected
|
171
|
-
|
172
|
-
def consumer_id
|
173
|
-
@consumer_id ||= "#{`hostname -s`.strip}-#{Thread.current.object_id}"
|
174
|
-
end
|
175
|
-
|
176
|
-
def input_name
|
177
|
-
@exchange.nil? or @key.nil? ? queue : "#{@exchange}:#{@key}"
|
178
|
-
end
|
179
|
-
|
180
152
|
def setup
|
181
153
|
return if terminating?
|
182
154
|
|
155
|
+
#
|
156
|
+
# With multiple threads, Logstash/Jruby/Bunny combo seems to fail ssl
|
157
|
+
# handshake on the first 1-2 connection attempts when restarting Logstash.
|
158
|
+
#
|
159
|
+
# optionally, look at : settings[:connect_timeout]
|
160
|
+
#
|
183
161
|
begin
|
184
|
-
|
185
|
-
|
186
|
-
@
|
187
|
-
@
|
188
|
-
@conn.start
|
162
|
+
connection_attempt ||= 1
|
163
|
+
message(:debug, "connecting")
|
164
|
+
@connection = Bunny.new(@settings)
|
165
|
+
@connection.start
|
189
166
|
rescue OpenSSL::SSL::SSLError
|
190
|
-
|
191
|
-
|
192
|
-
|
167
|
+
message(:warn, "ssl handshake failed, retrying",
|
168
|
+
attempt: connection_attempt)
|
169
|
+
connection_attempt += 1
|
170
|
+
retry unless connection_attempt > 3
|
193
171
|
end
|
194
172
|
|
195
|
-
@
|
196
|
-
@
|
197
|
-
|
198
|
-
|
173
|
+
@consumers = {}
|
174
|
+
@queues.each do |queue_name, routing_key|
|
175
|
+
consumer = "#{queue_name}#{routing_key}"
|
176
|
+
message(:debug, "creating consumer #{consumer}")
|
177
|
+
|
178
|
+
channel = @connection.create_channel.tap do |channel|
|
179
|
+
channel.prefetch(@prefetch)
|
180
|
+
end
|
181
|
+
|
182
|
+
queue = channel.queue(@queue,
|
183
|
+
durable: @durable,
|
184
|
+
auto_delete: @auto_delete,
|
185
|
+
exclusive: @exclusive,
|
186
|
+
passive: @passive)
|
187
|
+
|
188
|
+
queue.bind(@exchange, routing_key: routing_key)
|
199
189
|
|
200
|
-
|
201
|
-
|
202
|
-
:durable => @durable,
|
203
|
-
:auto_delete => @auto_delete,
|
204
|
-
:exclusive => @exclusive,
|
205
|
-
:passive => @passive,
|
206
|
-
:arguments => @arguments)
|
207
|
-
|
208
|
-
# exchange binding is optional for the input
|
209
|
-
if @exchange
|
210
|
-
@q.bind(@exchange, :routing_key => @key)
|
190
|
+
@consumers[consumer] = Bunny::Consumer.
|
191
|
+
new(channel, queue, nil, !@ack, @exclusive)
|
211
192
|
end
|
212
193
|
end
|
213
194
|
|
214
|
-
def
|
215
|
-
@
|
195
|
+
def release
|
196
|
+
@consumers.each do |name, consumer|
|
197
|
+
consumer.cancel
|
198
|
+
consumer.channel.close if consumer.channel and consumer.channel.open?
|
199
|
+
end
|
200
|
+
@consumers = []
|
216
201
|
|
217
|
-
|
218
|
-
|
202
|
+
@connection.close if @connection and @connection.open?
|
203
|
+
end
|
219
204
|
|
220
|
-
|
221
|
-
@
|
222
|
-
|
223
|
-
|
224
|
-
|
205
|
+
def consume
|
206
|
+
@consumers.each do |name, consumer|
|
207
|
+
message(:info, "consuming events from #{name}")
|
208
|
+
|
209
|
+
consumer.on_delivery do |delivery_info, properties, data|
|
210
|
+
@codec.decode(data) do |event|
|
211
|
+
decorate(event)
|
212
|
+
event["bunny"] ||= {}
|
213
|
+
event["bunny"]["key"] = delivery_info.routing_key
|
214
|
+
event["bunny"]["queue"] = consumer.queue_name
|
215
|
+
@output_queue << event
|
216
|
+
end
|
217
|
+
|
218
|
+
consumer.channel.acknowledge(delivery_info.delivery_tag) if @ack
|
225
219
|
end
|
226
220
|
|
227
|
-
|
221
|
+
consumer.queue.subscribe_with(consumer, block: true)
|
228
222
|
end
|
229
|
-
|
230
|
-
@q.subscribe_with(@consumer, block: true)
|
231
223
|
end
|
232
|
-
|
233
224
|
end # class LogStash::Inputs::RabbitMQ
|
234
225
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-input-bunny'
|
4
|
-
s.version = '0.1.
|
4
|
+
s.version = '0.1.12'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "Pull events from a RabbitMQ exchange."
|
7
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"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-bunny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Serafini
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logstash-core
|