hutch 0.27.0 → 1.1.0

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 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