hutch 0.27.0 → 1.1.0

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: 07e4ec8d85eefed7b25ae9bb43fb3c0ff8ffe0a4f24526b986686906aaa0f5cc
4
- data.tar.gz: 94062cdf67c00e9224d3fee9be1fa294ba0e234f8400ec4efc640eaecc07a2df
3
+ metadata.gz: 74721c392b797963bf268ff65d638b888e11d43307446ed63bd3de14e36aa97e
4
+ data.tar.gz: 1ddb6053bd164c0332650169415ae9a20daa9724039be7765cc90aade1e0f304
5
5
  SHA512:
6
- metadata.gz: e5a9ef9a749741aee734246701cde0a99f1c36f02e730eb1e888d2a125dba6e4ed9f9cdf945656ebbf8dcd118775c4717110c4d542b6547df84119baeb29f0a4
7
- data.tar.gz: 8a929dafd7c168256da9c349e4bf60a052456f2d34db4e717e3c46a08e461dac60f95ea6903a76a54bb934fbbcabb62a1c2e24b662469d3e5afd9e459a165b2c
6
+ metadata.gz: e690481212eeca9499f491b34c39e9f8e4f883f617063a5123bf1471e87b7f7251c52e0c92b103fe73dfa8db1859ad5feca76b6f0694ff68554191e66621f209
7
+ data.tar.gz: 043c203877a230f2d50c023a005ce84c7a7fc764c2b6ce3d452ab8aa143fa4175e4ba4bd54a4e2e611839360b2ec292d28c03ec338c92bbaa3b84e34b8a644f0
data/.travis.yml CHANGED
@@ -1,3 +1,6 @@
1
+ dist: bionic
2
+ sudo: required
3
+
1
4
  language: ruby
2
5
  cache: bundler
3
6
  before_install:
@@ -5,18 +8,16 @@ before_install:
5
8
  before_script:
6
9
  - "./bin/ci/install_on_debian.sh"
7
10
  - until sudo lsof -i:5672; do echo "Waiting for RabbitMQ to start..."; sleep 1; done
11
+ - "./bin/ci/before_build.sh"
8
12
  matrix:
9
13
  include:
10
- - rvm: "2.6.4"
11
- - rvm: "2.5.6"
12
- - rvm: "2.4.7"
13
- - rvm: "2.3.8"
14
- - rvm: "jruby-9.2.8.0"
14
+ - rvm: "3.0.0"
15
+ - rvm: "2.7.1"
16
+ - rvm: "2.6.6"
17
+ - rvm: "2.5.8"
18
+ - rvm: "jruby-9.2.19.0"
19
+ name: "Latest JRuby"
15
20
  - rvm: "ruby-head"
16
21
  allow_failures:
17
- rvm:
18
- - "jruby-9.2.8.0"
19
- - ruby-head
20
-
21
- services:
22
- - rabbitmq
22
+ - name: "Latest JRuby"
23
+ - rvm: ruby-head
data/CHANGELOG.md CHANGED
@@ -1,7 +1,127 @@
1
- ## 0.28.0 (under development)
1
+ ## 1.1.0 (July 26th, 2021)
2
2
 
3
- No chages yet.
3
+ ### Bugsnag Error Handler
4
4
 
5
+ Contributed by @ivanhuang1.
6
+
7
+ GitHub issue: [#362](https://github.com/ruby-amqp/hutch/pull/362)
8
+
9
+ ### Updated Sentry Error Handler
10
+
11
+ Contributed by Karol @Azdaroth Galanciak.
12
+
13
+ GitHub issue: [#363](https://github.com/ruby-amqp/hutch/pull/363)
14
+
15
+
16
+ ### Type Casting for Values Set Using Hutch::Config.set
17
+
18
+ Values set with `Hutch::Config.set` now have expected setting type casting
19
+ applied to them.
20
+
21
+ Contributed by Karol @Azdaroth Galanciak.
22
+
23
+ GitHub issue: [#358](https://github.com/ruby-amqp/hutch/pull/358)
24
+
25
+
26
+ ## 1.0.0 (April 8th, 2020)
27
+
28
+ Hutch has been around for several years. It is time to ship a 1.0. With it we try to correct
29
+ a few of overly opinionated decisions from recent releases. This means this release
30
+ contains potentially breaking changes.
31
+
32
+ ### Breaking Changes
33
+
34
+ * Hutch will no longer configure any queue type (such as [quorum queues](https://www.rabbitmq.com/quorum-queues.html))
35
+ or queue mode (used by classic [lazy queues](https://www.rabbitmq.com/lazy-queues.html))
36
+ by default as that can be breaking change for existing Hutch and RabbitMQ installations due to the
37
+ [property equivalence requirement](https://www.rabbitmq.com/queues.html#property-equivalence) in AMQP 0-9-1.
38
+
39
+ This means **some defaults introduced in `0.28.0` ([gocardless/hutch#341](https://github.com/gocardless/hutch/pull/341)) were reverted**.
40
+ The user has to opt in to configure the queue type and mode and other [optional arguments](https://www.rabbitmq.com/queues.html#optional-arguments) they need to use.
41
+ Most optional arguments can be set via [policies](https://www.rabbitmq.com/parameters.html#policies) which is always the recommended approach.
42
+ Queue type, unfortunately, is not one of them as different queue types have completely different
43
+ implementation details, on disk data formats and so on.
44
+
45
+ To use a quorum queue, use the `quorum_queue` consumer DSL method:
46
+
47
+ ``` ruby
48
+ class ConsumerUsingQuorumQueue
49
+ include Hutch::Consumer
50
+ consume 'hutch.test1'
51
+ # when in doubt, prefer using a policy to this DSL
52
+ # https://www.rabbitmq.com/parameters.html#policies
53
+ arguments 'x-key': :value
54
+
55
+ quorum_queue
56
+ end
57
+ ```
58
+
59
+ To use a classic lazy queue, use the `lazy_queue` consumer DSL method:
60
+
61
+ ``` ruby
62
+ class ConsumerUsingLazyQueue
63
+ include Hutch::Consumer
64
+ consume 'hutch.test1'
65
+ # when in doubt, prefer using a policy to this DSL
66
+ # https://www.rabbitmq.com/parameters.html#policies
67
+ arguments 'x-key': :value
68
+
69
+ lazy_queue
70
+ classic_queue
71
+ end
72
+ ```
73
+
74
+ By default Hutch will not configure any `x-queue-type` or `x-queue-mode` optional arguments
75
+ which is identical to RabbitMQ defaults (a regular classic queue).
76
+
77
+ Note that as of RabbitMQ 3.8.2, an omitted `x-queue-type` is [considered to be identical](https://github.com/rabbitmq/rabbitmq-common/issues/341)
78
+ to `x-queue-type` set to `classic` by RabbitMQ server.
79
+
80
+
81
+ #### Enhancements
82
+
83
+ * Exchange type is now configurable via the `mq_exchange_type` config setting. Supported exchanges must be
84
+ compatible with topic exchanges (e.g. wrap it). Default value is `topic`.
85
+
86
+ This feature is limited to topic and delayed message exchange plugins and is mostly
87
+ useful for forward compatibility.
88
+
89
+ Contributed by Michael Bumann.
90
+
91
+ GitHub issue: [gocardless/hutch#349](https://github.com/gocardless/hutch/pull/349)
92
+
93
+
94
+ ## 0.28.0 (March 17, 2020)
95
+
96
+ ### Enhancements
97
+
98
+ * Add lazy and quorum options for queues.
99
+
100
+ GitHub issue: [gocardless/hutch#341](https://github.com/gocardless/hutch/pull/341)
101
+
102
+ Contributed by: Arthur Del Esposte
103
+
104
+ * Log level in the message publisher switched to DEBUG.
105
+
106
+ GitHub issue: [gocardless/hutch#343](https://github.com/gocardless/hutch/pull/343)
107
+
108
+ Contributed by: Codruț Constantin Gușoi
109
+
110
+ ### Documentation
111
+
112
+ * Add zeitwerk note to README.
113
+
114
+ GitHub issue: [gocardless/hutch#342](https://github.com/gocardless/hutch/pull/342)
115
+
116
+ Contributed by: Paolo Zaccagnini
117
+
118
+ ### CI
119
+
120
+ * Use jruby-9.2.9.0
121
+
122
+ GitHub issue: [gocardless/hutch#336](https://github.com/gocardless/hutch/pull/336)
123
+
124
+ Contributed by: Olle Jonsson
5
125
 
6
126
  ## 0.27.0 (September 9th, 2019)
7
127
 
data/Gemfile CHANGED
@@ -20,11 +20,14 @@ group :development, :test do
20
20
  gem "simplecov", "~> 0.12"
21
21
 
22
22
  gem "sentry-raven"
23
+ gem "sentry-ruby"
23
24
  gem "honeybadger"
24
25
  gem "coveralls", "~> 0.8.15", require: false
25
26
  gem "newrelic_rpm"
26
- gem "airbrake", "~> 9.0"
27
+ gem "ddtrace"
28
+ gem "airbrake", "~> 10.0"
27
29
  gem "rollbar"
30
+ gem "bugsnag"
28
31
  end
29
32
 
30
33
  group :development, :darwin do
data/LICENSE CHANGED
@@ -1,4 +1,5 @@
1
1
  Copyright (c) 2013-2016 GoCardless
2
+ Copyright (c) 2016-2020 Hutch contributors
2
3
 
3
4
  Permission is hereby granted, free of charge, to any person
4
5
  obtaining a copy of this software and associated documentation
data/README.md CHANGED
@@ -39,7 +39,7 @@ gem install hutch
39
39
 
40
40
  ## Requirements
41
41
 
42
- - Hutch requires Ruby 2.3+ or JRuby 9K.
42
+ - Hutch requires Ruby 2.4+ or JRuby 9K.
43
43
  - Hutch requires RabbitMQ 3.3 or later.
44
44
 
45
45
  ## Overview
@@ -59,8 +59,8 @@ Hutch uses [Bunny](http://rubybunny.info) or [March Hare](http://rubymarchhare.i
59
59
  ### Project Maturity
60
60
 
61
61
  Hutch is a mature project that was originally extracted from production systems
62
- at [GoCardless](https://gocardless.com) in 2013 and is now maintained by a large
63
- group of contributors.
62
+ at [GoCardless](https://gocardless.com) in 2013 and is now maintained by its contributors
63
+ and users.
64
64
 
65
65
  ## Consumers
66
66
 
@@ -109,6 +109,28 @@ class FailedPaymentConsumer
109
109
  end
110
110
  ```
111
111
 
112
+ It is possible to set some custom options to consumer's queue explicitly.
113
+ This example sets the consumer's queue as a
114
+ [quorum queue](https://www.rabbitmq.com/quorum-queues.html)
115
+ and to operate in the [lazy mode](https://www.rabbitmq.com/lazy-queues.html).
116
+ The `initial_group_size`
117
+ [argument](https://www.rabbitmq.com/quorum-queues.html#replication-factor) is
118
+ optional.
119
+
120
+ ```ruby
121
+ class FailedPaymentConsumer
122
+ include Hutch::Consumer
123
+ consume 'gc.ps.payment.failed'
124
+ queue_name 'failed_payments'
125
+ lazy_queue
126
+ quorum_queue initial_group_size: 3
127
+
128
+ def process(message)
129
+ mark_payment_as_failed(message[:id])
130
+ end
131
+ end
132
+ ```
133
+
112
134
  You can also set custom arguments per consumer. This example declares a consumer with
113
135
  a maximum length of 10 messages:
114
136
 
@@ -166,6 +188,12 @@ This will enable NewRelic custom instrumentation:
166
188
  Hutch::Config.set(:tracer, Hutch::Tracers::NewRelic)
167
189
  ```
168
190
 
191
+ And this will enable Datadog custom instrumentation:
192
+
193
+ ```ruby
194
+ Hutch::Config.set(:tracer, Hutch::Tracers::Datadog)
195
+ ```
196
+
169
197
  Batteries included!
170
198
 
171
199
  ## Running Hutch
@@ -219,13 +247,55 @@ directory of a Rails app, or pass the path to a Rails app in with the
219
247
  the `app/consumers/` directory, to allow them to be auto-loaded when Rails
220
248
  boots.
221
249
 
250
+ If you're using the new Zeitwerk autoloader (enabled by default in Rails 6)
251
+ and the consumers are not loaded in development environment you will need to
252
+ trigger the autoloading in an initializer with
253
+
254
+ ```ruby
255
+ ::Zeitwerk::Loader.eager_load_all
256
+ ```
257
+
258
+ or with something more specific like
259
+
260
+ ```ruby
261
+ autoloader = Rails.autoloaders.main
262
+
263
+ Dir.glob(File.join('app/consumers', '*_consumer.rb')).each do |consumer|
264
+ autoloader.preload(consumer)
265
+ end
266
+ ```
267
+
268
+ ### Consumer Groups
269
+
270
+ It is possible to load only a subset of consumers. This is done by defining a consumer
271
+ group under the `consumer_groups` configuration key:
272
+
273
+ ``` yaml
274
+ consumer_groups:
275
+ payments:
276
+ - DepositConsumer
277
+ - CashoutConsumer
278
+ notification:
279
+ - EmailNotificationConsumer
280
+ ```
281
+
282
+ To only load a group of consumers, use the `--only-group` option:
283
+
284
+ ``` shell
285
+ hutch --only-group=payments --config=/path/to/hutch.yaml
286
+ ```
287
+
288
+ ### Loading Consumers Manually (One-by-One)
289
+
222
290
  To require files that define consumers manually, simply pass each file as an
223
291
  option to `--require`. Hutch will automatically detect whether you've provided
224
292
  a Rails app or a standard file, and take the appropriate behaviour:
225
293
 
226
294
  ```bash
227
- $ hutch --require path/to/rails-app # loads a rails app
228
- $ hutch --require path/to/file.rb # loads a ruby file
295
+ # loads a rails app
296
+ hutch --require path/to/rails-app
297
+ # loads a ruby file
298
+ hutch --require path/to/file.rb
229
299
  ```
230
300
 
231
301
  ### Stopping Hutch
@@ -344,6 +414,7 @@ Known configuration parameters are:
344
414
  * `automatically_recover`: Bunny's enable/disable network recovery (default: `true`)
345
415
  * `network_recovery_interval`: Bunny's reconnect interval (default: `1`)
346
416
  * `tracer`: tracer to use to track message processing
417
+ * `namespace`: A namespace string to help group your queues (default: `nil`)
347
418
 
348
419
  ### Environment variables
349
420
 
@@ -402,6 +473,13 @@ Generate with
402
473
  <td><tt>HUTCH_MQ_EXCHANGE</tt></td>
403
474
  <td><p>RabbitMQ Exchange to use for publishing</p></td>
404
475
  </tr>
476
+ <tr>
477
+ <td><tt>mq_exchange_type</tt></td>
478
+ <td>topic</td>
479
+ <td>String</td>
480
+ <td><tt>HUTCH_MQ_EXCHANGE_TYPE</tt></td>
481
+ <td><p>RabbitMQ Exchange type to use for publishing</p></td>
482
+ </tr>
405
483
  <tr>
406
484
  <td><tt>mq_vhost</tt></td>
407
485
  <td>/</td>
@@ -584,5 +662,19 @@ Generate with
584
662
  <td><tt>HUTCH_CONSUMER_TAG_PREFIX</tt></td>
585
663
  <td><p>Prefix displayed on the consumers tags.</p></td>
586
664
  </tr>
665
+ <tr>
666
+ <td><tt>namespace</tt></td>
667
+ <td>nil</td>
668
+ <td>String</td>
669
+ <td><tt>HUTCH_NAMESPACE</tt></td>
670
+ <td><p>A namespace to help group your queues</p></td>
671
+ </tr>
672
+ <tr>
673
+ <td><tt>group</tt></td>
674
+ <td>''</td>
675
+ <td>String</td>
676
+ <td><tt>HUTCH_GROUP</tt></td>
677
+ <td></td>
678
+ </tr>
587
679
  </tbody>
588
680
  </table>
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env sh
2
+
3
+ CTL=${BUNNY_RABBITMQCTL:-"sudo rabbitmqctl"}
4
+ PLUGINS=${BUNNY_RABBITMQ_PLUGINS:-"sudo rabbitmq-plugins"}
5
+
6
+ echo "Will use rabbitmqctl at ${CTL}"
7
+ echo "Will use rabbitmq-plugins at ${PLUGINS}"
8
+
9
+ $PLUGINS enable rabbitmq_management
10
+
11
+ sleep 3
12
+
13
+ # guest:guest has full access to /
14
+ $CTL add_vhost /
15
+ $CTL add_user guest guest
16
+ $CTL set_permissions -p / guest ".*" ".*" ".*"
17
+
18
+ # Reduce retention policy for faster publishing of stats
19
+ $CTL eval 'supervisor2:terminate_child(rabbit_mgmt_sup_sup, rabbit_mgmt_sup), application:set_env(rabbitmq_management, sample_retention_policies, [{global, [{605, 1}]}, {basic, [{605, 1}]}, {detailed, [{10, 1}]}]), rabbit_mgmt_sup_sup:start_child().' || true
20
+ $CTL eval 'supervisor2:terminate_child(rabbit_mgmt_agent_sup_sup, rabbit_mgmt_agent_sup), application:set_env(rabbitmq_management_agent, sample_retention_policies, [{global, [{605, 1}]}, {basic, [{605, 1}]}, {detailed, [{10, 1}]}]), rabbit_mgmt_agent_sup_sup:start_child().' || true
@@ -1,17 +1,46 @@
1
1
  #!/bin/sh
2
2
 
3
- sudo apt-get install -y wget
4
- wget -O - "https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc" | sudo apt-key add -
3
+ sudo apt-get install curl gnupg debian-keyring debian-archive-keyring apt-transport-https -y
5
4
 
6
- sudo tee /etc/apt/sources.list.d/bintray.rabbitmq.list <<EOF
7
- deb https://dl.bintray.com/rabbitmq-erlang/debian xenial erlang
8
- deb https://dl.bintray.com/rabbitmq/debian xenial main
5
+ ## Team RabbitMQ's main signing key
6
+ sudo apt-key adv --keyserver "hkps://keys.openpgp.org" --recv-keys "0x0A9AF2115F4687BD29803A206B73A36E6026DFCA"
7
+ ## Launchpad PPA that provides modern Erlang releases
8
+ sudo apt-key adv --keyserver "keyserver.ubuntu.com" --recv-keys "F77F1EDA57EBB1CC"
9
+ ## PackageCloud RabbitMQ repository
10
+ sudo apt-key adv --keyserver "keyserver.ubuntu.com" --recv-keys "F6609E60DC62814E"
11
+
12
+ ## Add apt repositories maintained by Team RabbitMQ
13
+ sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
14
+ ## Provides modern Erlang/OTP releases
15
+ ##
16
+ ## "bionic" as distribution name should work for any reasonably recent Ubuntu or Debian release.
17
+ ## See the release to distribution mapping table in RabbitMQ doc guides to learn more.
18
+ deb http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
19
+ deb-src http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
20
+
21
+ ## Provides RabbitMQ
22
+ ##
23
+ ## "bionic" as distribution name should work for any reasonably recent Ubuntu or Debian release.
24
+ ## See the release to distribution mapping table in RabbitMQ doc guides to learn more.
25
+ deb https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
26
+ deb-src https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
9
27
  EOF
10
28
 
29
+ ## Update package indices
11
30
  sudo apt-get update -y
12
- sudo apt-get upgrade -y
13
- sudo apt-get install -y rabbitmq-server
31
+
32
+ ## Install Erlang packages
33
+ sudo apt-get install -y erlang-base \
34
+ erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
35
+ erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
36
+ erlang-runtime-tools erlang-snmp erlang-ssl \
37
+ erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl
38
+
39
+ ## Install rabbitmq-server and its dependencies
40
+ sudo apt-get install rabbitmq-server -y --fix-missing
14
41
 
15
42
  sudo service rabbitmq-server start
16
43
 
44
+ sudo rabbitmqctl await_startup --timeout 120
45
+
17
46
  until sudo lsof -i:5672; do echo "Waiting for RabbitMQ to start..."; sleep 1; done
data/hutch.gemspec CHANGED
@@ -6,10 +6,10 @@ Gem::Specification.new do |gem|
6
6
  gem.add_runtime_dependency 'march_hare', '>= 3.0.0'
7
7
  else
8
8
  gem.platform = Gem::Platform::RUBY
9
- gem.add_runtime_dependency 'bunny', '>= 2.13', '< 2.15'
9
+ gem.add_runtime_dependency 'bunny', '>= 2.16', '< 3.0'
10
10
  end
11
11
  gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
12
- gem.add_runtime_dependency 'multi_json', '~> 1.12'
12
+ gem.add_runtime_dependency 'multi_json', '~> 1.14'
13
13
  gem.add_runtime_dependency 'activesupport', '>= 4.2', '< 7'
14
14
 
15
15
  gem.name = 'hutch'
data/lib/hutch/broker.rb CHANGED
@@ -122,11 +122,12 @@ module Hutch
122
122
 
123
123
  def declare_exchange(ch = channel)
124
124
  exchange_name = @config[:mq_exchange]
125
+ exchange_type = @config[:mq_exchange_type]
125
126
  exchange_options = { durable: true }.merge(@config[:mq_exchange_options])
126
127
  logger.info "using topic exchange '#{exchange_name}'"
127
128
 
128
129
  with_bunny_precondition_handler('exchange') do
129
- ch.topic(exchange_name, exchange_options)
130
+ Bunny::Exchange.new(ch, exchange_type, exchange_name, exchange_options)
130
131
  end
131
132
  end
132
133
 
@@ -181,12 +182,15 @@ module Hutch
181
182
  # Return a mapping of queue names to the routing keys they're bound to.
182
183
  def bindings
183
184
  results = Hash.new { |hash, key| hash[key] = [] }
184
- api_client.bindings.each do |binding|
185
- next if binding['destination'] == binding['routing_key']
186
- next unless binding['source'] == @config[:mq_exchange]
187
- next unless binding['vhost'] == @config[:mq_vhost]
185
+
186
+ filtered = api_client.bindings.
187
+ reject { |b| b['destination'] == b['routing_key'] }.
188
+ select { |b| b['source'] == @config[:mq_exchange] && b['vhost'] == @config[:mq_vhost] }
189
+
190
+ filtered.each do |binding|
188
191
  results[binding['destination']] << binding['routing_key']
189
192
  end
193
+
190
194
  results
191
195
  end
192
196
 
@@ -194,8 +198,8 @@ module Hutch
194
198
  def unbind_redundant_bindings(queue, routing_keys)
195
199
  return unless http_api_use_enabled?
196
200
 
197
- bindings.each do |dest, keys|
198
- next unless dest == queue.name
201
+ filtered = bindings.select { |dest, keys| dest == queue.name }
202
+ filtered.each do |dest, keys|
199
203
  keys.reject { |key| routing_keys.include?(key) }.each do |key|
200
204
  logger.debug "removing redundant binding #{queue.name} <--> #{key}"
201
205
  queue.unbind(exchange, routing_key: key)
data/lib/hutch/cli.rb CHANGED
@@ -33,6 +33,23 @@ module Hutch
33
33
  def load_app
34
34
  # Try to load a Rails app in the current directory
35
35
  load_rails_app('.') if Hutch::Config.autoload_rails
36
+ set_up_code_paths!
37
+
38
+ # Because of the order things are required when we run the Hutch binary
39
+ # in hutch/bin, the Sentry Raven gem gets required **after** the error
40
+ # handlers are set up. Due to this, we never got any Sentry notifications
41
+ # when an error occurred in any of the consumers.
42
+ if defined?(Raven)
43
+ Hutch::Config[:error_handlers] << Hutch::ErrorHandlers::SentryRaven.new
44
+ end
45
+ if defined?(Sentry)
46
+ Hutch::Config[:error_handlers] << Hutch::ErrorHandlers::Sentry.new
47
+ end
48
+
49
+ true
50
+ end
51
+
52
+ def set_up_code_paths!
36
53
  Hutch::Config.require_paths.each do |path|
37
54
  # See if each path is a Rails app. If so, try to load it.
38
55
  next if load_rails_app(path)
@@ -51,16 +68,6 @@ module Hutch
51
68
  $LOAD_PATH.pop
52
69
  end
53
70
  end
54
-
55
- # Because of the order things are required when we run the Hutch binary
56
- # in hutch/bin, the Sentry Raven gem gets required **after** the error
57
- # handlers are set up. Due to this, we never got any Sentry notifications
58
- # when an error occurred in any of the consumers.
59
- if defined?(Raven)
60
- Hutch::Config[:error_handlers] << Hutch::ErrorHandlers::Sentry.new
61
- end
62
-
63
- true
64
71
  end
65
72
 
66
73
  def load_rails_app(path)
data/lib/hutch/config.rb CHANGED
@@ -49,6 +49,9 @@ module Hutch
49
49
  # RabbitMQ Exchange to use for publishing
50
50
  string_setting :mq_exchange, 'hutch'
51
51
 
52
+ # RabbitMQ Exchange type to use for publishing
53
+ string_setting :mq_exchange_type, 'topic'
54
+
52
55
  # RabbitMQ vhost to use
53
56
  string_setting :mq_vhost, '/'
54
57
 
@@ -142,6 +145,9 @@ module Hutch
142
145
  # Prefix displayed on the consumers tags.
143
146
  string_setting :consumer_tag_prefix, 'hutch'
144
147
 
148
+ # A namespace to help group your queues
149
+ string_setting :namespace, nil
150
+
145
151
  string_setting :group, ''
146
152
 
147
153
  # Set of all setting keys
@@ -190,14 +196,7 @@ module Hutch
190
196
  env_keys_configured.each_with_object({}) {|attr, result|
191
197
  value = ENV[key_for(attr)]
192
198
 
193
- case
194
- when is_bool(attr) || value == 'false'
195
- result[attr] = to_bool(value)
196
- when is_num(attr)
197
- result[attr] = value.to_i
198
- else
199
- result[attr] = value
200
- end
199
+ result[attr] = type_cast(attr, value)
201
200
  }
202
201
  end
203
202
 
@@ -232,7 +231,7 @@ module Hutch
232
231
 
233
232
  def self.set(attr, value)
234
233
  check_attr(attr.to_sym)
235
- user_config[attr.to_sym] = value
234
+ user_config[attr.to_sym] = type_cast(attr, value)
236
235
  end
237
236
 
238
237
  class << self
@@ -269,6 +268,18 @@ module Hutch
269
268
  end
270
269
  end
271
270
 
271
+ def self.type_cast(attr, value)
272
+ case
273
+ when is_bool(attr) || value == 'false'
274
+ to_bool(value)
275
+ when is_num(attr)
276
+ value.to_i
277
+ else
278
+ value
279
+ end
280
+ end
281
+ private_class_method :type_cast
282
+
272
283
  def self.define_methods
273
284
  @config.keys.each do |key|
274
285
  define_singleton_method(key) do
@@ -29,14 +29,38 @@ module Hutch
29
29
  # wants to subscribe to.
30
30
  def consume(*routing_keys)
31
31
  @routing_keys = self.routing_keys.union(routing_keys)
32
+ # these are opt-in
33
+ @queue_mode = nil
34
+ @queue_type = nil
32
35
  end
33
36
 
37
+ attr_reader :queue_mode, :queue_type, :initial_group_size
38
+
34
39
  # Explicitly set the queue name
35
40
  def queue_name(name)
36
41
  @queue_name = name
37
42
  end
38
43
 
39
- # Allow to specify custom arguments that will be passed when creating the queue.
44
+ # Explicitly set the queue mode to 'lazy'
45
+ def lazy_queue
46
+ @queue_mode = 'lazy'
47
+ end
48
+
49
+ # Explicitly set the queue type to 'classic'
50
+ def classic_queue
51
+ @queue_type = 'classic'
52
+ end
53
+
54
+ # Explicitly set the queue type to 'quorum'
55
+ # @param [Hash] options the options params related to quorum queue
56
+ # @option options [Integer] :initial_group_size Initial Replication Factor
57
+ def quorum_queue(options = {})
58
+ @queue_type = 'quorum'
59
+ @initial_group_size = options[:initial_group_size]
60
+ end
61
+
62
+ # Configures an optional argument that will be passed when declaring the queue.
63
+ # Prefer using a policy to this DSL: https://www.rabbitmq.com/parameters.html#policies
40
64
  def arguments(arguments = {})
41
65
  @arguments = arguments
42
66
  end
@@ -58,7 +82,13 @@ module Hutch
58
82
 
59
83
  # Returns consumer custom arguments.
60
84
  def get_arguments
61
- @arguments || {}
85
+ all_arguments = @arguments || {}
86
+
87
+ all_arguments['x-queue-mode'] = @queue_mode if @queue_mode
88
+ all_arguments['x-queue-type'] = @queue_type if @queue_type
89
+ all_arguments['x-quorum-initial-group-size'] = @initial_group_size if @initial_group_size
90
+
91
+ all_arguments
62
92
  end
63
93
 
64
94
  # Accessor for the consumer's routing key.
@@ -0,0 +1,30 @@
1
+ require "hutch/logging"
2
+ require "bugsnag"
3
+ require "hutch/error_handlers/base"
4
+
5
+ module Hutch
6
+ module ErrorHandlers
7
+ class Bugsnag < Base
8
+ def handle(properties, payload, consumer, ex)
9
+ message_id = properties.message_id
10
+ prefix = "message(#{message_id || "-"}):"
11
+ logger.error "#{prefix} Logging event to Bugsnag"
12
+ logger.error "#{prefix} #{ex.class} - #{ex.message}"
13
+
14
+ ::Bugsnag.notify(ex) do |report|
15
+ report.add_tab(:hutch, {
16
+ payload: payload,
17
+ consumer: consumer
18
+ })
19
+ end
20
+ end
21
+
22
+ def handle_setup_exception(ex)
23
+ logger.error "Logging setup exception to Bugsnag"
24
+ logger.error "#{ex.class} - #{ex.message}"
25
+
26
+ ::Bugsnag.notify(ex)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,31 +1,26 @@
1
1
  require 'hutch/logging'
2
- require 'raven'
2
+ require 'sentry-ruby'
3
3
  require 'hutch/error_handlers/base'
4
4
 
5
5
  module Hutch
6
6
  module ErrorHandlers
7
7
  class Sentry < Base
8
-
9
- def initialize
10
- unless Raven.respond_to?(:capture_exception)
11
- raise "The Hutch Sentry error handler requires Raven >= 0.4.0"
12
- end
13
- end
14
-
15
8
  def handle(properties, payload, consumer, ex)
16
9
  message_id = properties.message_id
17
10
  prefix = "message(#{message_id || '-'}):"
18
11
  logger.error "#{prefix} Logging event to Sentry"
19
12
  logger.error "#{prefix} #{ex.class} - #{ex.message}"
20
- Raven.capture_exception(ex, extra: { payload: payload })
13
+ ::Sentry.configure_scope do |scope|
14
+ scope.set_context("payload", payload)
15
+ end
16
+ ::Sentry.capture_exception(ex)
21
17
  end
22
18
 
23
19
  def handle_setup_exception(ex)
24
20
  logger.error "Logging setup exception to Sentry"
25
21
  logger.error "#{ex.class} - #{ex.message}"
26
- Raven.capture_exception(ex)
22
+ ::Sentry.capture_exception(ex)
27
23
  end
28
-
29
24
  end
30
25
  end
31
26
  end
@@ -0,0 +1,31 @@
1
+ require 'hutch/logging'
2
+ require 'raven'
3
+ require 'hutch/error_handlers/base'
4
+
5
+ module Hutch
6
+ module ErrorHandlers
7
+ class SentryRaven < Base
8
+
9
+ def initialize
10
+ unless Raven.respond_to?(:capture_exception)
11
+ raise "The Hutch Sentry error handler requires Raven >= 0.4.0"
12
+ end
13
+ end
14
+
15
+ def handle(properties, payload, consumer, ex)
16
+ message_id = properties.message_id
17
+ prefix = "message(#{message_id || '-'}):"
18
+ logger.error "#{prefix} Logging event to Sentry"
19
+ logger.error "#{prefix} #{ex.class} - #{ex.message}"
20
+ Raven.capture_exception(ex, extra: { payload: payload })
21
+ end
22
+
23
+ def handle_setup_exception(ex)
24
+ logger.error "Logging setup exception to Sentry"
25
+ logger.error "#{ex.class} - #{ex.message}"
26
+ Raven.capture_exception(ex)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -2,8 +2,10 @@ module Hutch
2
2
  module ErrorHandlers
3
3
  autoload :Logger, 'hutch/error_handlers/logger'
4
4
  autoload :Sentry, 'hutch/error_handlers/sentry'
5
+ autoload :SentryRaven, 'hutch/error_handlers/sentry_raven'
5
6
  autoload :Honeybadger, 'hutch/error_handlers/honeybadger'
6
7
  autoload :Airbrake, 'hutch/error_handlers/airbrake'
7
8
  autoload :Rollbar, 'hutch/error_handlers/rollbar'
9
+ autoload :Bugsnag, 'hutch/error_handlers/bugsnag'
8
10
  end
9
11
  end
@@ -42,7 +42,7 @@ module Hutch
42
42
  private
43
43
 
44
44
  def log_publication(serializer, payload, routing_key)
45
- logger.info {
45
+ logger.debug {
46
46
  spec =
47
47
  if serializer.binary?
48
48
  "#{payload.bytesize} bytes message"
@@ -6,7 +6,7 @@ module Hutch
6
6
  class JSON
7
7
 
8
8
  def self.encode(payload)
9
- ::JSON.dump(payload)
9
+ ::MultiJson.dump(payload)
10
10
  end
11
11
 
12
12
  def self.decode(payload)
@@ -0,0 +1,17 @@
1
+ require 'ddtrace'
2
+
3
+ module Hutch
4
+ module Tracers
5
+ class Datadog
6
+ def initialize(klass)
7
+ @klass = klass
8
+ end
9
+
10
+ def handle(message)
11
+ ::Datadog.tracer.trace(@klass.class.name, service: 'hutch', span_type: 'rabbitmq') do
12
+ @klass.process(message)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/hutch/tracers.rb CHANGED
@@ -2,5 +2,6 @@ module Hutch
2
2
  module Tracers
3
3
  autoload :NullTracer, 'hutch/tracers/null_tracer'
4
4
  autoload :NewRelic, 'hutch/tracers/newrelic'
5
+ autoload :Datadog, 'hutch/tracers/datadog'
5
6
  end
6
7
  end
data/lib/hutch/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Hutch
2
- VERSION = '0.27.0'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -49,6 +49,44 @@ describe Hutch::Config do
49
49
  context 'sets value in user config hash' do
50
50
  it { is_expected.to eq(new_value) }
51
51
  end
52
+
53
+ context 'type casting' do
54
+ context 'number attributes' do
55
+ before { Hutch::Config.set(:heartbeat, new_value) }
56
+ subject(:value) { Hutch::Config.user_config[:heartbeat] }
57
+
58
+ let(:new_value) { "0" }
59
+
60
+
61
+ specify 'casts values to integers' do
62
+ expect(value).to eq 0
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'boolean attributes' do
68
+ before { Hutch::Config.set(:autoload_rails, new_value) }
69
+ subject(:value) { Hutch::Config.user_config[:autoload_rails] }
70
+
71
+ let(:new_value) { "t" }
72
+
73
+
74
+ specify 'casts values to booleans' do
75
+ expect(value).to eq true
76
+ end
77
+ end
78
+
79
+ context 'string attributes' do
80
+ before { Hutch::Config.set(:mq_exchange_type, new_value) }
81
+ subject(:value) { Hutch::Config.user_config[:mq_exchange_type] }
82
+
83
+ let(:new_value) { 1 }
84
+
85
+
86
+ specify 'does not perform any typecasting' do
87
+ expect(value).to eq new_value
88
+ end
89
+ end
52
90
  end
53
91
 
54
92
  context 'for invalid attributes' do
@@ -28,6 +28,32 @@ describe Hutch::Consumer do
28
28
  ComplexConsumer
29
29
  end
30
30
 
31
+ let(:consumer_using_quorum_queue) do
32
+ unless defined? ConsumerUsingQuorumQueue
33
+ class ConsumerUsingQuorumQueue
34
+ include Hutch::Consumer
35
+ consume 'hutch.test1'
36
+ arguments foo: :bar
37
+
38
+ quorum_queue
39
+ end
40
+ end
41
+ ConsumerUsingQuorumQueue
42
+ end
43
+
44
+ let(:consumer_using_classic_queue) do
45
+ unless defined? ConsumerUsingLazyQueue
46
+ class ConsumerUsingLazyQueue
47
+ include Hutch::Consumer
48
+ consume 'hutch.test1'
49
+ arguments foo: :bar
50
+ lazy_queue
51
+ classic_queue
52
+ end
53
+ end
54
+ ConsumerUsingLazyQueue
55
+ end
56
+
31
57
  describe 'module inclusion' do
32
58
  it 'registers the class as a consumer' do
33
59
  expect(Hutch).to receive(:register_consumer) do |klass|
@@ -71,6 +97,43 @@ describe Hutch::Consumer do
71
97
  end
72
98
  end
73
99
 
100
+ describe 'default queue mode' do
101
+ it 'does not specify any mode by default' do
102
+ expect(simple_consumer.queue_mode).to eq(nil)
103
+ expect(simple_consumer.queue_type).to eq(nil)
104
+ end
105
+ end
106
+
107
+ describe '.lazy_queue' do
108
+ context 'when queue mode has been set explicitly to lazy' do
109
+ it 'sets queue mode to lazy' do
110
+ expect(consumer_using_classic_queue.queue_mode).to eq('lazy')
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '.classic_queue' do
116
+ context 'when queue type has been set explicitly to classic' do
117
+ it 'sets queue type to classic' do
118
+ expect(consumer_using_classic_queue.queue_type).to eq('classic')
119
+ end
120
+ end
121
+ end
122
+
123
+ describe '.quorum_queue' do
124
+ context 'when queue type has been set explicitly to quorum' do
125
+ it 'sets queue type to quorum' do
126
+ expect(consumer_using_quorum_queue.queue_type).to eq('quorum')
127
+ end
128
+
129
+ it 'accepts initial group size as an option' do
130
+ consumer = simple_consumer
131
+ expect { consumer.quorum_queue(initial_group_size: 3) }
132
+ .to change { consumer.initial_group_size }.to(3)
133
+ end
134
+ end
135
+ end
136
+
74
137
  describe '.arguments' do
75
138
  let(:args) { { foo: :bar} }
76
139
 
@@ -82,15 +145,30 @@ describe Hutch::Consumer do
82
145
  end
83
146
 
84
147
  describe '.get_arguments' do
85
-
86
148
  context 'when defined' do
87
- it { expect(complex_consumer.get_arguments).to eq(foo: :bar) }
149
+ it { expect(complex_consumer.get_arguments).to include(foo: :bar) }
88
150
  end
89
151
 
90
- context 'when not defined' do
91
- it { expect(simple_consumer.get_arguments).to eq({}) }
152
+ context 'when queue is lazy' do
153
+ it 'has the x-queue-mode argument set to lazy' do
154
+ expect(consumer_using_classic_queue.get_arguments['x-queue-mode'])
155
+ .to eq('lazy')
156
+ end
92
157
  end
93
158
 
159
+ context "when queue's type is quorum" do
160
+ let(:arguments) { consumer_using_quorum_queue.get_arguments }
161
+ it 'has the x-queue-type argument set to quorum' do
162
+ expect(arguments['x-queue-type']).to eq('quorum')
163
+ expect(arguments).to_not have_key('x-quorum-initial-group-size')
164
+ end
165
+
166
+ it 'has the x-quorum-initial-group-size argument set to quorum' do
167
+ consumer_using_quorum_queue.quorum_queue(initial_group_size: 5)
168
+ expect(arguments['x-queue-type']).to eq('quorum')
169
+ expect(arguments['x-quorum-initial-group-size']).to eq(5)
170
+ end
171
+ end
94
172
  end
95
173
 
96
174
  describe '.get_queue_name' do
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Hutch::ErrorHandlers::Bugsnag do
6
+ let(:error_handler) { described_class.new }
7
+
8
+ before do
9
+ Bugsnag.configure do |bugsnag|
10
+ bugsnag.api_key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
11
+ end
12
+ end
13
+
14
+ describe "#handle" do
15
+ let(:error) do
16
+ begin
17
+ raise "Stuff went wrong"
18
+ rescue RuntimeError => err
19
+ err
20
+ end
21
+ end
22
+
23
+ it "logs the error to Bugsnag" do
24
+ message_id = "1"
25
+ properties = OpenStruct.new(message_id: message_id)
26
+ payload = "{}"
27
+ consumer = double
28
+ ex = error
29
+ message = {
30
+ payload: payload,
31
+ consumer: consumer
32
+ }
33
+
34
+ expect(::Bugsnag).to receive(:notify).with(ex).and_call_original
35
+ expect_any_instance_of(::Bugsnag::Report).to receive(:add_tab).with(:hutch, message)
36
+ error_handler.handle(properties, payload, consumer, ex)
37
+ end
38
+ end
39
+
40
+ describe "#handle_setup_exception" do
41
+ let(:error) do
42
+ begin
43
+ raise "Stuff went wrong"
44
+ rescue RuntimeError => err
45
+ err
46
+ end
47
+ end
48
+
49
+ it "logs the error to Bugsnag" do
50
+ ex = error
51
+ expect(::Bugsnag).to receive(:notify).with(ex)
52
+ error_handler.handle_setup_exception(ex)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch::ErrorHandlers::SentryRaven do
4
+ let(:error_handler) { Hutch::ErrorHandlers::SentryRaven.new }
5
+
6
+ describe '#handle' do
7
+ let(:properties) { OpenStruct.new(message_id: "1") }
8
+ let(:payload) { "{}" }
9
+ let(:error) do
10
+ begin
11
+ raise "Stuff went wrong"
12
+ rescue RuntimeError => err
13
+ err
14
+ end
15
+ end
16
+
17
+ it "logs the error to Sentry" do
18
+ expect(Raven).to receive(:capture_exception).with(error, extra: { payload: payload })
19
+ error_handler.handle(properties, payload, double, error)
20
+ end
21
+ end
22
+
23
+ describe '#handle_setup_exception' do
24
+ let(:error) do
25
+ begin
26
+ raise "Stuff went wrong during setup"
27
+ rescue RuntimeError => err
28
+ err
29
+ end
30
+ end
31
+
32
+ it "logs the error to Sentry" do
33
+ expect(Raven).to receive(:capture_exception).with(error)
34
+ error_handler.handle_setup_exception(error)
35
+ end
36
+ end
37
+ end
@@ -15,7 +15,8 @@ describe Hutch::ErrorHandlers::Sentry do
15
15
  end
16
16
 
17
17
  it "logs the error to Sentry" do
18
- expect(Raven).to receive(:capture_exception).with(error, extra: { payload: payload })
18
+ expect(::Sentry).to receive(:capture_exception).with(error).and_call_original
19
+
19
20
  error_handler.handle(properties, payload, double, error)
20
21
  end
21
22
  end
@@ -30,7 +31,8 @@ describe Hutch::ErrorHandlers::Sentry do
30
31
  end
31
32
 
32
33
  it "logs the error to Sentry" do
33
- expect(Raven).to receive(:capture_exception).with(error)
34
+ expect(::Sentry).to receive(:capture_exception).with(error).and_call_original
35
+
34
36
  error_handler.handle_setup_exception(error)
35
37
  end
36
38
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Hutch::Tracers::Datadog do
4
+ describe "#handle" do
5
+ subject(:handle) { tracer.handle(message) }
6
+
7
+ let(:tracer) { described_class.new(klass) }
8
+ let(:klass) do
9
+ Class.new do
10
+ attr_reader :message
11
+
12
+ def initialize
13
+ @message = nil
14
+ end
15
+
16
+ def class
17
+ OpenStruct.new(name: 'ClassName')
18
+ end
19
+
20
+ def process(message)
21
+ @message = message
22
+ end
23
+ end.new
24
+ end
25
+ let(:message) { double(:message) }
26
+
27
+ before do
28
+ allow(Datadog.tracer).to receive(:trace).and_call_original
29
+ end
30
+
31
+ it 'uses Datadog tracer' do
32
+ handle
33
+
34
+ expect(Datadog.tracer).to have_received(:trace).with('ClassName',
35
+ hash_including(service: 'hutch', span_type: 'rabbitmq'))
36
+ end
37
+
38
+ it 'processes the message' do
39
+ expect {
40
+ handle
41
+ }.to change { klass.message }.from(nil).to(message)
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hutch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Marr
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-09 00:00:00.000000000 Z
11
+ date: 2021-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.13'
19
+ version: '2.16'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.15'
22
+ version: '3.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '2.13'
29
+ version: '2.16'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.15'
32
+ version: '3.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: carrot-top
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.12'
53
+ version: '1.14'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '1.12'
60
+ version: '1.14'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: activesupport
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -97,6 +97,7 @@ files:
97
97
  - LICENSE
98
98
  - README.md
99
99
  - Rakefile
100
+ - bin/ci/before_build.sh
100
101
  - bin/ci/install_on_debian.sh
101
102
  - bin/hutch
102
103
  - examples/consumer.rb
@@ -115,10 +116,12 @@ files:
115
116
  - lib/hutch/error_handlers.rb
116
117
  - lib/hutch/error_handlers/airbrake.rb
117
118
  - lib/hutch/error_handlers/base.rb
119
+ - lib/hutch/error_handlers/bugsnag.rb
118
120
  - lib/hutch/error_handlers/honeybadger.rb
119
121
  - lib/hutch/error_handlers/logger.rb
120
122
  - lib/hutch/error_handlers/rollbar.rb
121
123
  - lib/hutch/error_handlers/sentry.rb
124
+ - lib/hutch/error_handlers/sentry_raven.rb
122
125
  - lib/hutch/exceptions.rb
123
126
  - lib/hutch/logging.rb
124
127
  - lib/hutch/message.rb
@@ -126,6 +129,7 @@ files:
126
129
  - lib/hutch/serializers/identity.rb
127
130
  - lib/hutch/serializers/json.rb
128
131
  - lib/hutch/tracers.rb
132
+ - lib/hutch/tracers/datadog.rb
129
133
  - lib/hutch/tracers/newrelic.rb
130
134
  - lib/hutch/tracers/null_tracer.rb
131
135
  - lib/hutch/version.rb
@@ -138,13 +142,16 @@ files:
138
142
  - spec/hutch/config_spec.rb
139
143
  - spec/hutch/consumer_spec.rb
140
144
  - spec/hutch/error_handlers/airbrake_spec.rb
145
+ - spec/hutch/error_handlers/bugsnag_spec.rb
141
146
  - spec/hutch/error_handlers/honeybadger_spec.rb
142
147
  - spec/hutch/error_handlers/logger_spec.rb
143
148
  - spec/hutch/error_handlers/rollbar_spec.rb
149
+ - spec/hutch/error_handlers/sentry_raven_spec.rb
144
150
  - spec/hutch/error_handlers/sentry_spec.rb
145
151
  - spec/hutch/logger_spec.rb
146
152
  - spec/hutch/message_spec.rb
147
153
  - spec/hutch/serializers/json_spec.rb
154
+ - spec/hutch/tracers/datadog_spec.rb
148
155
  - spec/hutch/waiter_spec.rb
149
156
  - spec/hutch/worker_spec.rb
150
157
  - spec/hutch_spec.rb
@@ -162,7 +169,7 @@ homepage: https://github.com/gocardless/hutch
162
169
  licenses:
163
170
  - MIT
164
171
  metadata: {}
165
- post_install_message:
172
+ post_install_message:
166
173
  rdoc_options: []
167
174
  require_paths:
168
175
  - lib
@@ -177,8 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
184
  - !ruby/object:Gem::Version
178
185
  version: '0'
179
186
  requirements: []
180
- rubygems_version: 3.0.3
181
- signing_key:
187
+ rubygems_version: 3.1.4
188
+ signing_key:
182
189
  specification_version: 4
183
190
  summary: Easy inter-service communication using RabbitMQ.
184
191
  test_files:
@@ -187,13 +194,16 @@ test_files:
187
194
  - spec/hutch/config_spec.rb
188
195
  - spec/hutch/consumer_spec.rb
189
196
  - spec/hutch/error_handlers/airbrake_spec.rb
197
+ - spec/hutch/error_handlers/bugsnag_spec.rb
190
198
  - spec/hutch/error_handlers/honeybadger_spec.rb
191
199
  - spec/hutch/error_handlers/logger_spec.rb
192
200
  - spec/hutch/error_handlers/rollbar_spec.rb
201
+ - spec/hutch/error_handlers/sentry_raven_spec.rb
193
202
  - spec/hutch/error_handlers/sentry_spec.rb
194
203
  - spec/hutch/logger_spec.rb
195
204
  - spec/hutch/message_spec.rb
196
205
  - spec/hutch/serializers/json_spec.rb
206
+ - spec/hutch/tracers/datadog_spec.rb
197
207
  - spec/hutch/waiter_spec.rb
198
208
  - spec/hutch/worker_spec.rb
199
209
  - spec/hutch_spec.rb