logstash-integration-rabbitmq 7.2.0-java → 7.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7901c2c7a657f948fa4b0babcfba746e84d15effeacaf98e410b59e774bb015c
4
- data.tar.gz: 447c27c4a03355df0d307017f88a31c830281f10a80c0a8c6e6b68be80b2d334
3
+ metadata.gz: 207f3a12b1cbb1d32a97f5341574d44d025e789c18af79f5562555df9fa94d6a
4
+ data.tar.gz: '09287862ba07197a33028cf84cae6bf84804ca7d4158617cafe71a255958688c'
5
5
  SHA512:
6
- metadata.gz: 459a95ef169e4b25ebe32ab9e72d6925ba987c2dccfd7fc27b68b789668b342ba21bf9e66aa0942ef6e8418cb855b3561731ae4b7cfd9300c45b1f60a2e1b0e0
7
- data.tar.gz: 3254e80a9990bd0b50bbdda4e4959eb04619006b29b61a1ffcb4fb0bbd037e876aecae4bf208999a4294fb8482c302b9875249cb06525fb35c14e45a98d44909
6
+ metadata.gz: 162c55651e563452c7a3930ab665a68edacbdbfc4c0f1aaa1bd9ba7e1f8388ce86be8e07cfcc48372333b035c72dfef8cc98122ee1abd332c2fa955928744de5
7
+ data.tar.gz: 699b2aaecda77591b1fa3f731ce094f104ed1b9f74fe81cb1c80876c15baa133d46162a9e8ce9020615aa9b40bb2259e0a98f4f1317f992f4398734552098191
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 7.3.0
2
+ - Refactor: logging improvements [#47](https://github.com/logstash-plugins/logstash-integration-rabbitmq/pull/47)
3
+ * integrated MarchHare logging to be part of Logstash's log instead of using std-err
4
+ * normalized logging format on (Ruby) errors
5
+
1
6
  ## 7.2.0
2
7
  - Remove ruby pipeline dependency. Starting from Logstash 8, Ruby execution engine is not available. All pipelines should use Java pipeline [#39](https://github.com/logstash-plugins/logstash-integration-rabbitmq/pull/39)
3
8
 
@@ -180,12 +180,9 @@ module LogStash
180
180
  @output_queue = output_queue
181
181
  consume!
182
182
  rescue => e
183
- raise unless stop?
183
+ raise(e) unless stop?
184
184
 
185
- logger.warn("Ignoring exception thrown during plugin shutdown",
186
- :message => e.message,
187
- :class => e.class.name,
188
- :location => e.backtrace.first)
185
+ @logger.warn("Ignoring exception thrown during plugin shutdown", error_details(e))
189
186
  end
190
187
 
191
188
  def setup!
@@ -200,10 +197,7 @@ module LogStash
200
197
 
201
198
  reset!
202
199
 
203
- @logger.warn("Error while setting up connection for rabbitmq input! Will retry.",
204
- :message => e.message,
205
- :class => e.class.name,
206
- :location => e.backtrace.first)
200
+ @logger.warn("Error while setting up connection, will retry", error_details(e))
207
201
  sleep_for_retry
208
202
  retry
209
203
  end
@@ -215,7 +209,7 @@ module LogStash
215
209
  def reset!
216
210
  @hare_info.connection && @hare_info.connection.close
217
211
  rescue => e
218
- @logger.debug("Exception while resetting connection", :exception => e.message, :backtrace => e.backtrace)
212
+ @logger.debug("Exception while resetting connection", error_details(e))
219
213
  ensure
220
214
  @hare_info = nil
221
215
  end
@@ -250,8 +244,8 @@ module LogStash
250
244
 
251
245
  begin
252
246
  @hare_info.queue.subscribe_with(@consumer, :manual_ack => @ack)
253
- rescue MarchHare::Exception => e
254
- @logger.warn("Could not subscribe to queue! Will retry in #{@subscription_retry_interval_seconds} seconds", :queue => @queue)
247
+ rescue => e
248
+ @logger.warn("Could not subscribe to queue, will retry in #{@subscription_retry_interval_seconds} seconds", error_details(e, :queue => @queue))
255
249
 
256
250
  sleep @subscription_retry_interval_seconds
257
251
  retry
@@ -316,15 +310,17 @@ module LogStash
316
310
  def shutdown_consumer
317
311
  return unless @consumer
318
312
  @hare_info.channel.basic_cancel(@consumer.consumer_tag)
313
+ connection = @hare_info.connection
319
314
  until @consumer.terminated?
320
- @logger.info("Waiting for rabbitmq consumer to terminate before stopping!", :params => self.params)
315
+ @logger.info("Waiting for RabbitMQ consumer to terminate before stopping", url: connection_url(connection))
321
316
  sleep 1
322
317
  end
323
318
  end
324
319
 
325
320
  def on_cancellation
326
321
  if !stop? # If this isn't already part of a regular stop
327
- @logger.info("Received basic.cancel from #{rabbitmq_settings[:host]}, shutting down.")
322
+ connection = @hare_info.connection
323
+ @logger.info("Received cancellation, shutting down", url: connection_url(connection))
328
324
  stop
329
325
  end
330
326
  end
@@ -77,10 +77,7 @@ module LogStash
77
77
  local_exchange.publish(message, :routing_key => routing_key, :properties => message_properties)
78
78
  end
79
79
  rescue MarchHare::Exception, IOError, AlreadyClosedException, TimeoutException => e
80
- @logger.error("Error while publishing. Will retry.",
81
- :message => e.message,
82
- :exception => e.class,
83
- :backtrace => e.backtrace)
80
+ @logger.error("Error while publishing, will retry", error_details(e, backtrace: true))
84
81
 
85
82
  sleep_for_retry
86
83
  retry
@@ -109,13 +109,13 @@ module LogStash
109
109
  s = {
110
110
  :vhost => @vhost,
111
111
  :addresses => addresses_from_hosts_and_port(@host, @port),
112
- :user => @user,
112
+ :username => @user,
113
113
  :automatic_recovery => @automatic_recovery,
114
- :pass => @password ? @password.value : "guest",
114
+ :password => @password ? @password.value : "guest",
115
115
  }
116
116
 
117
- s[:timeout] = @connection_timeout || 0
118
- s[:heartbeat] = @heartbeat || 0
117
+ s[:connection_timeout] = @connection_timeout || 0
118
+ s[:requested_heartbeat] = @heartbeat || 0
119
119
 
120
120
  if @ssl
121
121
  s[:tls] = @ssl_version
@@ -142,7 +142,7 @@ module LogStash
142
142
  def connect!
143
143
  @hare_info = connect() unless @hare_info # Don't duplicate the conn!
144
144
  rescue MarchHare::Exception, java.io.IOException => e
145
- error_message = if e.message.empty? && e.is_a?(java.io.IOException)
145
+ message = if e.message.empty? && e.is_a?(java.io.IOException)
146
146
  # IOException with an empty message is probably an instance of
147
147
  # these problems:
148
148
  # https://github.com/logstash-plugins/logstash-output-rabbitmq/issues/52
@@ -151,21 +151,12 @@ module LogStash
151
151
  # Best guess is to help the user understand that there is probably
152
152
  # some kind of configuration problem causing the error, but we
153
153
  # can't really offer any more detailed hints :\
154
- "An unknown error occurred. RabbitMQ gave no hints as to the cause. Maybe this is a configuration error (invalid vhost, for example). I recommend checking the RabbitMQ server logs for clues about this failure."
154
+ "An unknown RabbitMQ error occurred, maybe this is a configuration error (invalid vhost, for example) - please check the RabbitMQ server logs for clues about this failure"
155
155
  else
156
- e.message
156
+ "RabbitMQ connection error, will retry"
157
157
  end
158
158
 
159
- if @logger.debug?
160
- @logger.error("RabbitMQ connection error, will retry.",
161
- :error_message => error_message,
162
- :exception => e.class.name,
163
- :backtrace => e.backtrace)
164
- else
165
- @logger.error("RabbitMQ connection error, will retry.",
166
- :error_message => error_message,
167
- :exception => e.class.name)
168
- end
159
+ @logger.error(message, error_details(e))
169
160
 
170
161
  sleep_for_retry
171
162
  retry
@@ -179,48 +170,43 @@ module LogStash
179
170
  @hare_info && @hare_info.connection && @hare_info.connection.open?
180
171
  end
181
172
 
182
- def connected?
183
- return nil unless @hare_info && @hare_info.connection
184
- @hare_info.connection.connected?
185
- end
186
-
187
173
  private
188
174
 
189
175
  def declare_exchange!(channel, exchange, exchange_type, durable)
190
- @logger.debug? && @logger.debug("Declaring an exchange", :name => exchange,
191
- :type => exchange_type, :durable => durable)
192
- exchange = channel.exchange(exchange, :type => exchange_type.to_sym, :durable => durable)
193
- @logger.debug? && @logger.debug("Exchange declared")
194
- exchange
195
- rescue StandardError => e
196
- @logger.error("Could not declare exchange!",
197
- :exchange => exchange, :type => exchange_type,
198
- :durable => durable, :error_class => e.class.name,
199
- :error_message => e.message, :backtrace => e.backtrace)
176
+ @logger.debug? && @logger.debug("Declaring an exchange", :name => exchange, :type => exchange_type, :durable => durable)
177
+ channel.exchange(exchange, :type => exchange_type.to_sym, :durable => durable)
178
+ rescue => e
179
+ @logger.error("Could not declare exchange", error_details(e, :exchange => exchange, :type => exchange_type, :durable => durable))
180
+
200
181
  raise e
201
182
  end
202
183
 
203
184
  def connect
204
- @logger.debug? && @logger.debug("Connecting to RabbitMQ. Settings: #{rabbitmq_settings.inspect}")
205
-
206
- connection = MarchHare.connect(rabbitmq_settings)
185
+ @logger.debug? && @logger.debug("Connecting to RabbitMQ", rabbitmq_settings)
186
+
187
+ # disable MarchHare's attempt to provide a "better" exception logging experience:
188
+ settings = rabbitmq_settings.merge :exception_handler => com.rabbitmq.client.impl.ForgivingExceptionHandler.new
189
+ connection = MarchHare.connect(settings) # MarchHare::Session.connect
190
+ # we could pass down the :logger => logger but that adds an extra:
191
+ # `logger.info("Using TLS/SSL version #{tls}")` which isn't useful
192
+ # the rest of MH::Session logging is mostly debug level details
193
+ #
194
+ # NOTE: effectively redirects MarchHare's default std-out logging to LS
195
+ # (MARCH_HARE_LOG_LEVEL=debug no longer has an effect)
196
+ connection.instance_variable_set(:@logger, LoggerAdapter.new(logger))
207
197
 
208
198
  connection.on_shutdown do |conn, cause|
209
- @logger.warn("RabbitMQ connection was closed!",
210
- :url => connection_url(conn),
211
- :automatic_recovery => @automatic_recovery,
212
- :cause => cause)
199
+ @logger.warn("RabbitMQ connection was closed", url: connection_url(conn), automatic_recovery: @automatic_recovery, cause: cause)
213
200
  end
214
201
  connection.on_blocked do
215
- @logger.warn("RabbitMQ connection blocked! Check your RabbitMQ instance!",
216
- :url => connection_url(connection))
202
+ @logger.warn("RabbitMQ connection blocked - please check the RabbitMQ server logs", url: connection_url(connection))
217
203
  end
218
204
  connection.on_unblocked do
219
- @logger.warn("RabbitMQ connection unblocked!", :url => connection_url(connection))
205
+ @logger.warn("RabbitMQ connection unblocked", url: connection_url(connection))
220
206
  end
221
207
 
222
208
  channel = connection.create_channel
223
- @logger.info("Connected to RabbitMQ at #{rabbitmq_settings[:host]}")
209
+ @logger.info("Connected to RabbitMQ", url: connection_url(connection))
224
210
 
225
211
  HareInfo.new(connection, channel)
226
212
  end
@@ -235,6 +221,44 @@ module LogStash
235
221
  def sleep_for_retry
236
222
  Stud.stoppable_sleep(@connect_retry_interval) { @rabbitmq_connection_stopping }
237
223
  end
224
+
225
+ def error_details(e, info = {})
226
+ details = info.merge(:exception => e.class, :message => e.message)
227
+ if e.is_a?(MarchHare::Exception) && e.cause
228
+ details[:cause] = e.cause # likely a Java exception
229
+ end
230
+ details[:backtrace] = e.backtrace if @logger.debug? || info[:backtrace] == true
231
+ details
232
+ end
233
+
234
+ # @private adapting MarchHare's Ruby Logger assumptions
235
+ class LoggerAdapter < SimpleDelegator
236
+
237
+ java_import java.lang.Throwable
238
+
239
+ [:trace, :debug, :info, :warn, :error, :fatal].each do |level|
240
+ # sample logging used by MarchHare that we're after:
241
+ #
242
+ # rescue Exception => e
243
+ # logger.error("Caught exception when recovering queue #{q.name}")
244
+ # logger.error(e)
245
+ # end
246
+ class_eval <<-RUBY, __FILE__, __LINE__
247
+ def #{level}(arg)
248
+ if arg.is_a?(Exception) || arg.is_a?(Throwable)
249
+ details = { :exception => arg.class }
250
+ details[:cause] = arg.cause if arg.cause
251
+ details[:backtrace] = arg.backtrace
252
+ __getobj__.#{level}(arg.message.to_s, details)
253
+ else
254
+ __getobj__.#{level}(arg) # String
255
+ end
256
+ end
257
+ RUBY
258
+ end
259
+
260
+ end
261
+
238
262
  end
239
263
  end
240
264
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-integration-rabbitmq'
3
- s.version = '7.2.0'
3
+ s.version = '7.3.0'
4
4
  s.licenses = ['Apache License (2.0)']
5
5
  s.summary = "Integration with RabbitMQ - input and output plugins"
6
6
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline "+
@@ -45,6 +45,10 @@ describe LogStash::Inputs::RabbitMQ do
45
45
  allow(connection).to receive(:on_blocked)
46
46
  allow(connection).to receive(:on_unblocked)
47
47
  allow(connection).to receive(:close)
48
+ allow(connection).to receive(:host).and_return host
49
+ allow(connection).to receive(:port).and_return port
50
+ allow(connection).to receive(:vhost).and_return nil
51
+ allow(connection).to receive(:user).and_return 'guest'
48
52
  allow(channel).to receive(:exchange).and_return(exchange)
49
53
  allow(channel).to receive(:queue).and_return(queue)
50
54
  allow(channel).to receive(:prefetch=)
@@ -80,7 +84,7 @@ describe LogStash::Inputs::RabbitMQ do
80
84
  context "with an exchange declared" do
81
85
  let(:exchange) { "exchange" }
82
86
  let(:key) { "routing key" }
83
- let(:rabbitmq_settings) { super.merge("exchange" => exchange, "key" => key, "exchange_type" => "fanout") }
87
+ let(:rabbitmq_settings) { super().merge("exchange" => exchange, "key" => key, "exchange_type" => "fanout") }
84
88
 
85
89
  before do
86
90
  allow(instance).to receive(:declare_exchange!)
@@ -335,7 +339,7 @@ describe "LogStash::Inputs::RabbitMQ with a live server", :integration => true d
335
339
  }
336
340
 
337
341
  20.times do
338
- instance.connected? ? break : sleep(0.1)
342
+ instance.send(:connection_open?) ? break : sleep(0.1)
339
343
  end
340
344
 
341
345
  # Extra time to make sure the consumer can attach
@@ -364,16 +368,16 @@ describe "LogStash::Inputs::RabbitMQ with a live server", :integration => true d
364
368
 
365
369
  context "using defaults" do
366
370
  it "should start, connect, and stop cleanly" do
367
- expect(instance.connected?).to be_truthy
371
+ expect(instance.send(:connection_open?)).to be_truthy
368
372
  end
369
373
  end
370
374
 
371
375
  it "should have the correct prefetch value" do
372
- expect(instance.instance_variable_get(:@hare_info).channel.prefetch).to eql(256)
376
+ expect(hare_info.channel.prefetch).to eql(256)
373
377
  end
374
378
 
375
379
  describe "receiving a message with a queue + exchange specified" do
376
- let(:config) { super.merge("queue" => queue_name, "exchange" => exchange_name, "exchange_type" => "fanout", "metadata_enabled" => "true") }
380
+ let(:config) { super().merge("queue" => queue_name, "exchange" => exchange_name, "exchange_type" => "fanout", "metadata_enabled" => "true") }
377
381
  let(:event) { output_queue.pop }
378
382
  let(:exchange) { test_channel.exchange(exchange_name, :type => "fanout") }
379
383
  let(:exchange_name) { "logstash-input-rabbitmq-#{rand(0xFFFFFFFF)}" }
@@ -461,6 +465,32 @@ describe "LogStash::Inputs::RabbitMQ with a live server", :integration => true d
461
465
  end
462
466
  end
463
467
 
468
+ context "(MarchHare) error logging" do
469
+
470
+ let(:error) do
471
+ MarchHare::Exception.new('TEST ERROR').tap do |error|
472
+ allow( error ).to receive(:cause).and_return(error_cause)
473
+ end
474
+ end
475
+ let(:error_cause) { java.io.IOException.new('TEST CAUSE') }
476
+ let(:logger) { instance.logger }
477
+
478
+ before do
479
+ queues = hare_info.channel.instance_variable_get(:@queues)
480
+ expect( queue = queues.values.first ).to_not be nil
481
+ # emulate an issue during recovery (to trigger logger.error calls)
482
+ allow( queue ).to receive(:recover_from_network_failure).and_raise(error)
483
+ allow( logger ).to receive(:error)
484
+ end
485
+
486
+ it "gets redirected to plugin logger" do
487
+ hare_info.channel.recover_queues
488
+ expect( logger ).to have_received(:error).with(/Caught exception when recovering queue/i)
489
+ expect( logger ).to have_received(:error).with('TEST ERROR', hash_including(exception: MarchHare::Exception, cause: error_cause))
490
+ end
491
+
492
+ end
493
+
464
494
  describe LogStash::Inputs::RabbitMQ do
465
495
  require "logstash/devutils/rspec/shared_examples"
466
496
  it_behaves_like "an interruptible input plugin"
@@ -60,6 +60,10 @@ describe LogStash::Outputs::RabbitMQ do
60
60
  allow(connection).to receive(:on_shutdown)
61
61
  allow(connection).to receive(:on_recovery_start)
62
62
  allow(connection).to receive(:on_recovery)
63
+ allow(connection).to receive(:host).and_return host
64
+ allow(connection).to receive(:port).and_return port
65
+ allow(connection).to receive(:vhost).and_return nil
66
+ allow(connection).to receive(:user).and_return 'guest'
63
67
  allow(channel).to receive(:exchange).and_return(exchange)
64
68
 
65
69
  instance.register
@@ -206,7 +210,7 @@ describe "LogStash::Outputs::RabbitMQ with a live server", :integration => true
206
210
  instance.register
207
211
 
208
212
  20.times do
209
- instance.connected? ? break : sleep(0.1)
213
+ instance.send(:connection_open?) ? break : sleep(0.1)
210
214
  end
211
215
 
212
216
  # Extra time to make sure the output can attach
@@ -238,12 +242,12 @@ describe "LogStash::Outputs::RabbitMQ with a live server", :integration => true
238
242
 
239
243
  context "using defaults" do
240
244
  it "should start, connect, and stop cleanly" do
241
- expect(instance.connected?).to be_truthy
245
+ expect(instance.send(:connection_open?)).to be_truthy
242
246
  end
243
247
 
244
248
  it "should close cleanly" do
245
249
  instance.close
246
- expect(instance.connected?).to be_falsey
250
+ expect(instance.send(:connection_open?)).to be_falsey
247
251
  end
248
252
 
249
253
  it 'applies per message settings' do
@@ -48,7 +48,7 @@ describe LogStash::PluginMixins::RabbitMQConnection do
48
48
  let(:path) { file.path }
49
49
  after { File.unlink(path)}
50
50
 
51
- let(:rabbitmq_settings) { super.merge({"connection_timeout" => 123,
51
+ let(:rabbitmq_settings) { super().merge({"connection_timeout" => 123,
52
52
  "heartbeat" => 456,
53
53
  "ssl" => true,
54
54
  "ssl_version" => "TLSv1.1",
@@ -56,11 +56,11 @@ describe LogStash::PluginMixins::RabbitMQConnection do
56
56
  "ssl_certificate_password" => "123"}) }
57
57
 
58
58
  it "should set the timeout to the expected value" do
59
- expect(instance.rabbitmq_settings[:timeout]).to eql(rabbitmq_settings["connection_timeout"])
59
+ expect(instance.rabbitmq_settings[:connection_timeout]).to eql(rabbitmq_settings["connection_timeout"])
60
60
  end
61
61
 
62
62
  it "should set heartbeat to the expected value" do
63
- expect(instance.rabbitmq_settings[:heartbeat]).to eql(rabbitmq_settings["heartbeat"])
63
+ expect(instance.rabbitmq_settings[:requested_heartbeat]).to eql(rabbitmq_settings["heartbeat"])
64
64
  end
65
65
 
66
66
  it "should set tls to the expected value" do
@@ -79,14 +79,14 @@ describe LogStash::PluginMixins::RabbitMQConnection do
79
79
 
80
80
  context 'with a custom port' do
81
81
  let(:port) { 123 }
82
- let(:rabbitmq_settings) { super.merge({"port" => port})}
82
+ let(:rabbitmq_settings) { super().merge({"port" => port})}
83
83
 
84
84
  it_behaves_like 'it sets the addresses correctly'
85
85
  end
86
86
  end
87
87
 
88
88
  describe "ssl enabled, but no verification" do
89
- let(:rabbitmq_settings) { super.merge({"connection_timeout" => 123,
89
+ let(:rabbitmq_settings) { super().merge({"connection_timeout" => 123,
90
90
  "heartbeat" => 456,
91
91
  "ssl" => true}) }
92
92
 
@@ -102,7 +102,7 @@ describe LogStash::PluginMixins::RabbitMQConnection do
102
102
 
103
103
  context 'with a custom port' do
104
104
  let(:port) { 999 }
105
- let(:rabbitmq_settings) { super.merge({"port" => port})}
105
+ let(:rabbitmq_settings) { super().merge({"port" => port})}
106
106
 
107
107
  it_behaves_like 'it sets the addresses correctly'
108
108
  end
@@ -129,6 +129,10 @@ describe LogStash::PluginMixins::RabbitMQConnection do
129
129
  allow(connection).to receive(:on_blocked)
130
130
  allow(connection).to receive(:on_unblocked)
131
131
  allow(connection).to receive(:on_shutdown)
132
+ allow(connection).to receive(:host).and_return host
133
+ allow(connection).to receive(:port).and_return port
134
+ allow(connection).to receive(:vhost).and_return nil
135
+ allow(connection).to receive(:user).and_return 'guest'
132
136
 
133
137
  instance.register
134
138
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-integration-rabbitmq
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.0
4
+ version: 7.3.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-11 00:00:00.000000000 Z
11
+ date: 2021-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement