logstash-integration-rabbitmq 7.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/CONTRIBUTORS +27 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE +13 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +98 -0
  8. data/docs/index.asciidoc +29 -0
  9. data/docs/input-rabbitmq.asciidoc +398 -0
  10. data/docs/output-rabbitmq.asciidoc +272 -0
  11. data/lib/logstash/inputs/rabbitmq.rb +317 -0
  12. data/lib/logstash/outputs/rabbitmq.rb +131 -0
  13. data/lib/logstash/plugin_mixins/rabbitmq_connection.rb +234 -0
  14. data/lib/logstash_registry.rb +7 -0
  15. data/logstash-integration-rabbitmq.gemspec +53 -0
  16. data/spec/fixtures/README.md +150 -0
  17. data/spec/fixtures/client/cert.pem +69 -0
  18. data/spec/fixtures/client/key.pem +27 -0
  19. data/spec/fixtures/client/keycert.p12 +0 -0
  20. data/spec/fixtures/client/req.pem +15 -0
  21. data/spec/fixtures/client_untrusted/cert.pem +19 -0
  22. data/spec/fixtures/client_untrusted/key.pem +28 -0
  23. data/spec/fixtures/client_untrusted/keycert.p12 +0 -0
  24. data/spec/fixtures/server/cert.pem +69 -0
  25. data/spec/fixtures/server/key.pem +27 -0
  26. data/spec/fixtures/server/key_password +1 -0
  27. data/spec/fixtures/server/keycert.p12 +0 -0
  28. data/spec/fixtures/server/rabbitmq.config +10 -0
  29. data/spec/fixtures/server/req.pem +15 -0
  30. data/spec/fixtures/testca/cacert.cer +0 -0
  31. data/spec/fixtures/testca/cacert.pem +17 -0
  32. data/spec/fixtures/testca/certs/01.pem +18 -0
  33. data/spec/fixtures/testca/certs/02.pem +18 -0
  34. data/spec/fixtures/testca/certs/05.pem +69 -0
  35. data/spec/fixtures/testca/certs/06.pem +69 -0
  36. data/spec/fixtures/testca/index.txt +4 -0
  37. data/spec/fixtures/testca/index.txt.attr +1 -0
  38. data/spec/fixtures/testca/index.txt.attr.old +1 -0
  39. data/spec/fixtures/testca/index.txt.old +3 -0
  40. data/spec/fixtures/testca/openssl.cnf +53 -0
  41. data/spec/fixtures/testca/private/cakey.pem +27 -0
  42. data/spec/fixtures/testca/serial +1 -0
  43. data/spec/fixtures/testca/serial.old +1 -0
  44. data/spec/inputs/rabbitmq_spec.rb +279 -0
  45. data/spec/outputs/rabbitmq_spec.rb +232 -0
  46. data/spec/plugin_mixins/rabbitmq_connection_spec.rb +175 -0
  47. metadata +256 -0
@@ -0,0 +1,272 @@
1
+ :plugin: rabbitmq
2
+ :type: output
3
+ :default_codec: json
4
+
5
+ ///////////////////////////////////////////
6
+ START - GENERATED VARIABLES, DO NOT EDIT!
7
+ ///////////////////////////////////////////
8
+ :version: %VERSION%
9
+ :release_date: %RELEASE_DATE%
10
+ :changelog_url: %CHANGELOG_URL%
11
+ :include_path: ../../../../logstash/docs/include
12
+ ///////////////////////////////////////////
13
+ END - GENERATED VARIABLES, DO NOT EDIT!
14
+ ///////////////////////////////////////////
15
+
16
+ [id="plugins-{type}s-{plugin}"]
17
+
18
+ === Rabbitmq output plugin
19
+
20
+ include::{include_path}/plugin_header.asciidoc[]
21
+
22
+ ==== Description
23
+
24
+ Push events to a RabbitMQ exchange. Requires RabbitMQ 2.x
25
+ or later version (3.x is recommended).
26
+
27
+ Relevant links:
28
+
29
+ * http://www.rabbitmq.com/[RabbitMQ]
30
+ * http://rubymarchhare.info[March Hare]
31
+
32
+ [id="plugins-{type}s-{plugin}-options"]
33
+ ==== Rabbitmq Output Configuration Options
34
+
35
+ This plugin supports the following configuration options plus the <<plugins-{type}s-{plugin}-common-options>> described later.
36
+
37
+ [cols="<,<,<",options="header",]
38
+ |=======================================================================
39
+ |Setting |Input type|Required
40
+ | <<plugins-{type}s-{plugin}-arguments>> |<<array,array>>|No
41
+ | <<plugins-{type}s-{plugin}-automatic_recovery>> |<<boolean,boolean>>|No
42
+ | <<plugins-{type}s-{plugin}-connect_retry_interval>> |<<number,number>>|No
43
+ | <<plugins-{type}s-{plugin}-connection_timeout>> |<<number,number>>|No
44
+ | <<plugins-{type}s-{plugin}-durable>> |<<boolean,boolean>>|No
45
+ | <<plugins-{type}s-{plugin}-exchange>> |<<string,string>>|Yes
46
+ | <<plugins-{type}s-{plugin}-exchange_type>> |<<string,string>>, one of `["fanout", "direct", "topic", "x-consistent-hash", "x-modulus-hash"]`|Yes
47
+ | <<plugins-{type}s-{plugin}-heartbeat>> |<<number,number>>|No
48
+ | <<plugins-{type}s-{plugin}-host>> |<<string,string>>|Yes
49
+ | <<plugins-{type}s-{plugin}-key>> |<<string,string>>|No
50
+ | <<plugins-{type}s-{plugin}-message_properties>> |<<hash,hash>>|No
51
+ | <<plugins-{type}s-{plugin}-passive>> |<<boolean,boolean>>|No
52
+ | <<plugins-{type}s-{plugin}-password>> |<<password,password>>|No
53
+ | <<plugins-{type}s-{plugin}-persistent>> |<<boolean,boolean>>|No
54
+ | <<plugins-{type}s-{plugin}-port>> |<<number,number>>|No
55
+ | <<plugins-{type}s-{plugin}-ssl>> |<<boolean,boolean>>|No
56
+ | <<plugins-{type}s-{plugin}-ssl_certificate_password>> |<<string,string>>|No
57
+ | <<plugins-{type}s-{plugin}-ssl_certificate_path>> |a valid filesystem path|No
58
+ | <<plugins-{type}s-{plugin}-ssl_version>> |<<string,string>>|No
59
+ | <<plugins-{type}s-{plugin}-user>> |<<string,string>>|No
60
+ | <<plugins-{type}s-{plugin}-vhost>> |<<string,string>>|No
61
+ |=======================================================================
62
+
63
+ Also see <<plugins-{type}s-{plugin}-common-options>> for a list of options supported by all
64
+ output plugins.
65
+
66
+ &nbsp;
67
+
68
+ [id="plugins-{type}s-{plugin}-arguments"]
69
+ ===== `arguments`
70
+
71
+ * Value type is <<array,array>>
72
+ * Default value is `{}`
73
+
74
+ Extra queue arguments as an array.
75
+ To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
76
+
77
+ [id="plugins-{type}s-{plugin}-automatic_recovery"]
78
+ ===== `automatic_recovery`
79
+
80
+ * Value type is <<boolean,boolean>>
81
+ * Default value is `true`
82
+
83
+ Set this to automatically recover from a broken connection. You almost certainly don't want to override this!!!
84
+
85
+ [id="plugins-{type}s-{plugin}-connect_retry_interval"]
86
+ ===== `connect_retry_interval`
87
+
88
+ * Value type is <<number,number>>
89
+ * Default value is `1`
90
+
91
+ Time in seconds to wait before retrying a connection
92
+
93
+ [id="plugins-{type}s-{plugin}-connection_timeout"]
94
+ ===== `connection_timeout`
95
+
96
+ * Value type is <<number,number>>
97
+ * There is no default value for this setting.
98
+
99
+ The default connection timeout in milliseconds. If not specified the timeout is infinite.
100
+
101
+ [id="plugins-{type}s-{plugin}-durable"]
102
+ ===== `durable`
103
+
104
+ * Value type is <<boolean,boolean>>
105
+ * Default value is `true`
106
+
107
+ Is this exchange durable? (aka; Should it survive a broker restart?)
108
+
109
+ [id="plugins-{type}s-{plugin}-exchange"]
110
+ ===== `exchange`
111
+
112
+ * This is a required setting.
113
+ * Value type is <<string,string>>
114
+ * There is no default value for this setting.
115
+
116
+ The name of the exchange
117
+
118
+ [id="plugins-{type}s-{plugin}-exchange_type"]
119
+ ===== `exchange_type`
120
+
121
+ * This is a required setting.
122
+ * Value can be any of: `fanout`, `direct`, `topic`, `x-consistent-hash`, `x-modulus-hash`
123
+ * There is no default value for this setting.
124
+
125
+ The exchange type (fanout, topic, direct)
126
+
127
+ [id="plugins-{type}s-{plugin}-heartbeat"]
128
+ ===== `heartbeat`
129
+
130
+ * Value type is <<number,number>>
131
+ * There is no default value for this setting.
132
+
133
+ Heartbeat delay in seconds. If unspecified no heartbeats will be sent
134
+
135
+ [id="plugins-{type}s-{plugin}-host"]
136
+ ===== `host`
137
+
138
+ * This is a required setting.
139
+ * Value type is <<string,string>>
140
+ * There is no default value for this setting.
141
+
142
+ Common functionality for the rabbitmq input/output
143
+ RabbitMQ server address(es)
144
+ host can either be a single host, or a list of hosts
145
+ i.e.
146
+ host => "localhost"
147
+ or
148
+ host => ["host01", "host02]
149
+
150
+ if multiple hosts are provided on the initial connection and any subsequent
151
+ recovery attempts of the hosts is chosen at random and connected to.
152
+ Note that only one host connection is active at a time.
153
+
154
+ [id="plugins-{type}s-{plugin}-key"]
155
+ ===== `key`
156
+
157
+ * Value type is <<string,string>>
158
+ * Default value is `"logstash"`
159
+
160
+ The default codec for this plugin is JSON. You can override this to suit your particular needs however.
161
+ Key to route to by default. Defaults to 'logstash'
162
+
163
+ * Routing keys are ignored on fanout exchanges.
164
+
165
+ [id="plugins-{type}s-{plugin}-message_properties"]
166
+ ===== `message_properties`
167
+
168
+ * Value type is <<hash,hash>>
169
+ * Default value is `{}`
170
+
171
+ Add properties to be set per-message here, such as 'content_type', 'priority'
172
+
173
+ Example:
174
+ [source,ruby]
175
+ message_properties => {
176
+ "content_type" => "application/json"
177
+ "priority" => 1
178
+ }
179
+
180
+
181
+ [id="plugins-{type}s-{plugin}-passive"]
182
+ ===== `passive`
183
+
184
+ * Value type is <<boolean,boolean>>
185
+ * Default value is `false`
186
+
187
+ Passive queue creation? Useful for checking queue existance without modifying server state
188
+
189
+ [id="plugins-{type}s-{plugin}-password"]
190
+ ===== `password`
191
+
192
+ * Value type is <<password,password>>
193
+ * Default value is `"guest"`
194
+
195
+ RabbitMQ password
196
+
197
+ [id="plugins-{type}s-{plugin}-persistent"]
198
+ ===== `persistent`
199
+
200
+ * Value type is <<boolean,boolean>>
201
+ * Default value is `true`
202
+
203
+ Should RabbitMQ persist messages to disk?
204
+
205
+ [id="plugins-{type}s-{plugin}-port"]
206
+ ===== `port`
207
+
208
+ * Value type is <<number,number>>
209
+ * Default value is `5672`
210
+
211
+ RabbitMQ port to connect on
212
+
213
+ [id="plugins-{type}s-{plugin}-ssl"]
214
+ ===== `ssl`
215
+
216
+ * Value type is <<boolean,boolean>>
217
+ * There is no default value for this setting.
218
+
219
+ Enable or disable SSL.
220
+ Note that by default remote certificate verification is off.
221
+ Specify ssl_certificate_path and ssl_certificate_password if you need
222
+ certificate verification
223
+
224
+ [id="plugins-{type}s-{plugin}-ssl_certificate_password"]
225
+ ===== `ssl_certificate_password`
226
+
227
+ * Value type is <<string,string>>
228
+ * There is no default value for this setting.
229
+
230
+ Password for the encrypted PKCS12 (.p12) certificate file specified in ssl_certificate_path
231
+
232
+ [id="plugins-{type}s-{plugin}-ssl_certificate_path"]
233
+ ===== `ssl_certificate_path`
234
+
235
+ * Value type is <<path,path>>
236
+ * There is no default value for this setting.
237
+
238
+ Path to an SSL certificate in PKCS12 (.p12) format used for verifying the remote host
239
+
240
+ [id="plugins-{type}s-{plugin}-ssl_version"]
241
+ ===== `ssl_version`
242
+
243
+ * Value type is <<string,string>>
244
+ * Default value is `"TLSv1.2"`
245
+
246
+ Version of the SSL protocol to use.
247
+
248
+ [id="plugins-{type}s-{plugin}-user"]
249
+ ===== `user`
250
+
251
+ * Value type is <<string,string>>
252
+ * Default value is `"guest"`
253
+
254
+ RabbitMQ username
255
+
256
+ [id="plugins-{type}s-{plugin}-vhost"]
257
+ ===== `vhost`
258
+
259
+ * Value type is <<string,string>>
260
+ * Default value is `"/"`
261
+
262
+ The vhost (virtual host) to use. If you don't know what this
263
+ is, leave the default. With the exception of the default
264
+ vhost ("/"), names of vhosts should not begin with a forward
265
+ slash.
266
+
267
+
268
+
269
+ [id="plugins-{type}s-{plugin}-common-options"]
270
+ include::{include_path}/{type}.asciidoc[]
271
+
272
+ :default_codec!:
@@ -0,0 +1,317 @@
1
+ # encoding: utf-8
2
+ require_relative '../plugin_mixins/rabbitmq_connection'
3
+ require 'logstash/inputs/threadable'
4
+ require 'logstash/event'
5
+ java_import java.util.concurrent.ArrayBlockingQueue
6
+ java_import java.util.concurrent.TimeUnit
7
+
8
+ module LogStash
9
+ module Inputs
10
+ # Pull events from a http://www.rabbitmq.com/[RabbitMQ] queue.
11
+ #
12
+ # The default settings will create an entirely transient queue and listen for all messages by default.
13
+ # If you need durability or any other advanced settings, please set the appropriate options
14
+ #
15
+ # This plugin uses the http://rubymarchhare.info/[March Hare] library
16
+ # for interacting with the RabbitMQ server. Most configuration options
17
+ # map directly to standard RabbitMQ and AMQP concepts. The
18
+ # https://www.rabbitmq.com/amqp-0-9-1-reference.html[AMQP 0-9-1 reference guide]
19
+ # and other parts of the RabbitMQ documentation are useful for deeper
20
+ # understanding.
21
+ #
22
+ # The properties of messages received will be stored in the
23
+ # `[@metadata][rabbitmq_properties]` field if the `@metadata_enabled` setting is checked.
24
+ # Note that storing metadata may degrade performance.
25
+ # The following properties may be available (in most cases dependent on whether
26
+ # they were set by the sender):
27
+ #
28
+ # * app-id
29
+ # * cluster-id
30
+ # * consumer-tag
31
+ # * content-encoding
32
+ # * content-type
33
+ # * correlation-id
34
+ # * delivery-mode
35
+ # * exchange
36
+ # * expiration
37
+ # * message-id
38
+ # * priority
39
+ # * redeliver
40
+ # * reply-to
41
+ # * routing-key
42
+ # * timestamp
43
+ # * type
44
+ # * user-id
45
+ #
46
+ # For example, to get the RabbitMQ message's timestamp property
47
+ # into the Logstash event's `@timestamp` field, use the date
48
+ # filter to parse the `[@metadata][rabbitmq_properties][timestamp]`
49
+ # field:
50
+ # [source,ruby]
51
+ # filter {
52
+ # if [@metadata][rabbitmq_properties][timestamp] {
53
+ # date {
54
+ # match => ["[@metadata][rabbitmq_properties][timestamp]", "UNIX"]
55
+ # }
56
+ # }
57
+ # }
58
+ #
59
+ # Additionally, any message headers will be saved in the
60
+ # `[@metadata][rabbitmq_headers]` field.
61
+ class RabbitMQ < LogStash::Inputs::Threadable
62
+ include ::LogStash::PluginMixins::RabbitMQConnection
63
+
64
+ # The properties to extract from each message and store in a
65
+ # @metadata field.
66
+ #
67
+ # Technically the exchange, redeliver, and routing-key
68
+ # properties belong to the envelope and not the message but we
69
+ # ignore that distinction here. However, we extract the
70
+ # headers separately via get_headers even though the header
71
+ # table technically is a message property.
72
+ #
73
+ # Freezing all strings so that code modifying the event's
74
+ # @metadata field can't touch them.
75
+ #
76
+ # If updating this list, remember to update the documentation
77
+ # above too.
78
+ MESSAGE_PROPERTIES = [
79
+ "app-id",
80
+ "cluster-id",
81
+ "consumer-tag",
82
+ "content-encoding",
83
+ "content-type",
84
+ "correlation-id",
85
+ "delivery-mode",
86
+ "exchange",
87
+ "expiration",
88
+ "message-id",
89
+ "priority",
90
+ "redeliver",
91
+ "reply-to",
92
+ "routing-key",
93
+ "timestamp",
94
+ "type",
95
+ "user-id",
96
+ ].map { |s| s.freeze }.freeze
97
+
98
+ INTERNAL_QUEUE_POISON=[]
99
+
100
+ config_name "rabbitmq"
101
+
102
+ # The default codec for this plugin is JSON. You can override this to suit your particular needs however.
103
+ default :codec, "json"
104
+
105
+ # The name of the queue Logstash will consume events from. If
106
+ # left empty, a transient queue with an randomly chosen name
107
+ # will be created.
108
+ config :queue, :validate => :string, :default => ""
109
+
110
+ # Is this queue durable? (aka; Should it survive a broker restart?)
111
+ config :durable, :validate => :boolean, :default => false
112
+
113
+ # Should the queue be deleted on the broker when the last consumer
114
+ # disconnects? Set this option to `false` if you want the queue to remain
115
+ # on the broker, queueing up messages until a consumer comes along to
116
+ # consume them.
117
+ config :auto_delete, :validate => :boolean, :default => false
118
+
119
+ # Is the queue exclusive? Exclusive queues can only be used by the connection
120
+ # that declared them and will be deleted when it is closed (e.g. due to a Logstash
121
+ # restart).
122
+ config :exclusive, :validate => :boolean, :default => false
123
+
124
+ # Extra queue arguments as an array.
125
+ # To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
126
+ config :arguments, :validate => :array, :default => {}
127
+
128
+ # Prefetch count. If acknowledgements are enabled with the `ack`
129
+ # option, specifies the number of outstanding unacknowledged
130
+ # messages allowed.
131
+ config :prefetch_count, :validate => :number, :default => 256
132
+
133
+ # Enable message acknowledgements. With acknowledgements
134
+ # messages fetched by Logstash but not yet sent into the
135
+ # Logstash pipeline will be requeued by the server if Logstash
136
+ # shuts down. Acknowledgements will however hurt the message
137
+ # throughput.
138
+ #
139
+ # This will only send an ack back every `prefetch_count` messages.
140
+ # Working in batches provides a performance boost here.
141
+ config :ack, :validate => :boolean, :default => true
142
+
143
+ # If true the queue will be passively declared, meaning it must
144
+ # already exist on the server. To have Logstash create the queue
145
+ # if necessary leave this option as false. If actively declaring
146
+ # a queue that already exists, the queue options for this plugin
147
+ # (durable etc) must match those of the existing queue.
148
+ config :passive, :validate => :boolean, :default => false
149
+
150
+ # The name of the exchange to bind the queue to. Specify `exchange_type`
151
+ # as well to declare the exchange if it does not exist
152
+ config :exchange, :validate => :string
153
+
154
+ # The type of the exchange to bind to. Specifying this will cause this plugin
155
+ # to declare the exchange if it does not exist.
156
+ config :exchange_type, :validate => :string
157
+
158
+ # The routing key to use when binding a queue to the exchange.
159
+ # This is only relevant for direct or topic exchanges.
160
+ #
161
+ # * Routing keys are ignored on fanout exchanges.
162
+ # * Wildcards are not valid on direct exchanges.
163
+ config :key, :validate => :string, :default => "logstash"
164
+
165
+ # Amount of time in seconds to wait after a failed subscription request
166
+ # before retrying. Subscribes can fail if the server goes away and then comes back.
167
+ config :subscription_retry_interval_seconds, :validate => :number, :required => true, :default => 5
168
+
169
+ # Enable the storage of message headers and properties in `@metadata`. This may impact performance
170
+ config :metadata_enabled, :validate => :boolean, :default => false
171
+
172
+ def register
173
+ @internal_queue = java.util.concurrent.ArrayBlockingQueue.new(@prefetch_count*2)
174
+ end
175
+
176
+ def run(output_queue)
177
+ setup!
178
+ @output_queue = output_queue
179
+ consume!
180
+ end
181
+
182
+ def setup!
183
+ connect!
184
+ declare_queue!
185
+ bind_exchange!
186
+ @hare_info.channel.prefetch = @prefetch_count
187
+ rescue => e
188
+ @logger.warn("Error while setting up connection for rabbitmq input! Will retry.",
189
+ :message => e.message,
190
+ :class => e.class.name,
191
+ :location => e.backtrace.first)
192
+ sleep_for_retry
193
+ retry
194
+ end
195
+
196
+ def bind_exchange!
197
+ if @exchange
198
+ if @exchange_type # Only declare the exchange if @exchange_type is set!
199
+ @logger.info? && @logger.info("Declaring exchange '#{@exchange}' with type #{@exchange_type}")
200
+ @hare_info.exchange = declare_exchange!(@hare_info.channel, @exchange, @exchange_type, @durable)
201
+ end
202
+ @hare_info.queue.bind(@exchange, :routing_key => @key)
203
+ end
204
+ end
205
+
206
+ def declare_queue!
207
+ @hare_info.queue = declare_queue()
208
+ end
209
+
210
+ def declare_queue
211
+ @hare_info.channel.queue(@queue,
212
+ :durable => @durable,
213
+ :auto_delete => @auto_delete,
214
+ :exclusive => @exclusive,
215
+ :passive => @passive,
216
+ :arguments => @arguments)
217
+ end
218
+
219
+ def consume!
220
+ @consumer = @hare_info.queue.build_consumer(:on_cancellation => Proc.new { on_cancellation }) do |metadata, data|
221
+ @internal_queue.put [metadata, data]
222
+ end
223
+
224
+ begin
225
+ @hare_info.queue.subscribe_with(@consumer, :manual_ack => @ack)
226
+ rescue MarchHare::Exception => e
227
+ @logger.warn("Could not subscribe to queue! Will retry in #{@subscription_retry_interval_seconds} seconds", :queue => @queue)
228
+
229
+ sleep @subscription_retry_interval_seconds
230
+ retry
231
+ end
232
+
233
+ internal_queue_consume!
234
+ end
235
+
236
+ def internal_queue_consume!
237
+ i=0
238
+ last_delivery_tag=nil
239
+ while true
240
+ payload = @internal_queue.poll(10, TimeUnit::MILLISECONDS)
241
+ if !payload # Nothing in the queue
242
+ if last_delivery_tag # And we have unacked stuff
243
+ @hare_info.channel.ack(last_delivery_tag, true) if @ack
244
+ i=0
245
+ last_delivery_tag = nil
246
+ end
247
+ next
248
+ end
249
+
250
+ break if payload == INTERNAL_QUEUE_POISON
251
+
252
+ metadata, data = payload
253
+ @codec.decode(data) do |event|
254
+ decorate(event)
255
+ if @metadata_enabled
256
+ event.set("[@metadata][rabbitmq_headers]", get_headers(metadata))
257
+ event.set("[@metadata][rabbitmq_properties]", get_properties(metadata))
258
+ end
259
+ @output_queue << event if event
260
+ end
261
+
262
+ i += 1
263
+
264
+ if i >= @prefetch_count
265
+ @hare_info.channel.ack(metadata.delivery_tag, true) if @ack
266
+ i = 0
267
+ last_delivery_tag = nil
268
+ else
269
+ last_delivery_tag = metadata.delivery_tag
270
+ end
271
+ end
272
+ end
273
+
274
+ def stop
275
+ @internal_queue.put(INTERNAL_QUEUE_POISON)
276
+ shutdown_consumer
277
+ close_connection
278
+ end
279
+
280
+ def shutdown_consumer
281
+ return unless @consumer
282
+ @hare_info.channel.basic_cancel(@consumer.consumer_tag)
283
+ until @consumer.terminated?
284
+ @logger.info("Waiting for rabbitmq consumer to terminate before stopping!", :params => self.params)
285
+ sleep 1
286
+ end
287
+ end
288
+
289
+ def on_cancellation
290
+ if !stop? # If this isn't already part of a regular stop
291
+ @logger.info("Received basic.cancel from #{rabbitmq_settings[:host]}, shutting down.")
292
+ stop
293
+ end
294
+ end
295
+
296
+ private
297
+ def get_headers(metadata)
298
+ metadata.headers || {}
299
+ end
300
+
301
+ private
302
+ def get_properties(metadata)
303
+ MESSAGE_PROPERTIES.reduce({}) do |acc, name|
304
+ # The method names obviously can't contain hyphens.
305
+ value = metadata.send(name.gsub("-", "_"))
306
+ if value
307
+ # The AMQP 0.9.1 timestamp field only has second resolution
308
+ # so storing milliseconds serves no purpose and might give
309
+ # the incorrect impression of a higher resolution.
310
+ acc[name] = name != "timestamp" ? value : value.getTime / 1000
311
+ end
312
+ acc
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end