hermes-rb 0.2.0 → 0.6.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: 104554076c3b4ad46491c12d842e3580fdf8c96ba36eefbfc2f4c66a5ba5f208
4
- data.tar.gz: a5f1754803e51907feda1164ff25c048731037f4cd75f2a6eaf4db68668b6647
3
+ metadata.gz: 7cc73b9dbd7c2d1569311975037c0d5f45aac33c3eca2ba581b095dc2670662f
4
+ data.tar.gz: dbb3cd464fd5ac24ba0e8f9c8dcbaf904a31d49ad43088f1e01c06323862ee36
5
5
  SHA512:
6
- metadata.gz: aea75486bab7ba279b788dc48ea465f3ecb96c7281d9b6cc9bc29443c738ba779fe0951f6d0a8028211cce4f64520556f085cab73aee7ba98bac01af9dc5a973
7
- data.tar.gz: 10b79dce9ad5c116d6ccb31a6102b1e3732a2b0a73e328b5ef37b421e5407cc8a5cc240e6b68c11b7fd26bd2c06acb579a610ba3708d83515d5c17dc48207f50
6
+ metadata.gz: 04ebe50de83e5c3fbce03dc0c543563cdc7dd3e64f93cb65a7783c4437f56dadd31f5fcb60c8ec3332e480f8485224282728856ae9c0a1d732c7de9918b2a1b7
7
+ data.tar.gz: 2873fba2537bb1d8eb9b46e829fc1b312d079fd3eed7dc65bed09caa536349741c365ca2ee108617833b360e8e91d0c6814c01c23c13874b68ca725f84b11ae0
data/Changelog.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## Master
4
+
5
+ ## 0.6.0
6
+ - Add Health check
7
+
8
+ ## 0.5.0
9
+ - Add Datadog tracer
10
+ - Allow to provide a custom tracer
11
+
12
+ ## 0.4.0
13
+ - Make it possible to provide Hutch consumer config
14
+
15
+ ## 0.3.1
16
+ - Fix filtering params for logs for nil values in sensitive attributes
17
+
18
+ ## 0.3.0
19
+ - Reorganize Hutch config - instead of setting config values when connecting to Hutch when using publisher, do it right after the initialization.
20
+ - Make params filter customizable for the logger
21
+ - Remove sensitive info when creating distributed trace records.
22
+
3
23
  ## 0.2.0
4
24
  - Implement "Safe Producer" extension allowing to retry delivery later in an automated way when publishing of the message fails.
5
25
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hermes-rb (0.2.0)
4
+ hermes-rb (0.6.0)
5
5
  activerecord (>= 5)
6
6
  activesupport (>= 5)
7
7
  dry-container (~> 0)
@@ -12,12 +12,12 @@ PATH
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activemodel (6.1.1)
16
- activesupport (= 6.1.1)
17
- activerecord (6.1.1)
18
- activemodel (= 6.1.1)
19
- activesupport (= 6.1.1)
20
- activesupport (6.1.1)
15
+ activemodel (6.1.3)
16
+ activesupport (= 6.1.3)
17
+ activerecord (6.1.3)
18
+ activemodel (= 6.1.3)
19
+ activesupport (= 6.1.3)
20
+ activesupport (6.1.3)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (>= 1.6, < 2)
23
23
  minitest (>= 5.1)
@@ -28,9 +28,11 @@ GEM
28
28
  amq-protocol (~> 2.3, >= 2.3.1)
29
29
  carrot-top (0.0.7)
30
30
  json
31
- concurrent-ruby (1.1.7)
31
+ concurrent-ruby (1.1.8)
32
+ ddtrace (0.45.0)
33
+ msgpack
32
34
  diff-lcs (1.4.4)
33
- dry-configurable (0.12.0)
35
+ dry-configurable (0.12.1)
34
36
  concurrent-ruby (~> 1.0)
35
37
  dry-core (~> 0.5, >= 0.5.0)
36
38
  dry-container (0.7.2)
@@ -38,21 +40,18 @@ GEM
38
40
  dry-configurable (~> 0.1, >= 0.1.3)
39
41
  dry-core (0.5.0)
40
42
  concurrent-ruby (~> 1.0)
41
- dry-equalizer (0.3.0)
42
43
  dry-inflector (0.2.0)
43
44
  dry-logic (1.1.0)
44
45
  concurrent-ruby (~> 1.0)
45
46
  dry-core (~> 0.5, >= 0.5)
46
- dry-struct (1.3.0)
47
- dry-core (~> 0.4, >= 0.4.4)
48
- dry-equalizer (~> 0.3)
49
- dry-types (~> 1.3)
47
+ dry-struct (1.4.0)
48
+ dry-core (~> 0.5, >= 0.5)
49
+ dry-types (~> 1.5)
50
50
  ice_nine (~> 0.11)
51
- dry-types (1.4.0)
51
+ dry-types (1.5.1)
52
52
  concurrent-ruby (~> 1.0)
53
53
  dry-container (~> 0.3)
54
- dry-core (~> 0.4, >= 0.4.4)
55
- dry-equalizer (~> 0.3)
54
+ dry-core (~> 0.5, >= 0.5)
56
55
  dry-inflector (~> 0.1, >= 0.1.2)
57
56
  dry-logic (~> 1.0, >= 1.0.2)
58
57
  hutch (1.0.0)
@@ -60,12 +59,14 @@ GEM
60
59
  bunny (>= 2.15, < 2.16)
61
60
  carrot-top (~> 0.0.7)
62
61
  multi_json (~> 1.14)
63
- i18n (1.8.7)
62
+ i18n (1.8.9)
64
63
  concurrent-ruby (~> 1.0)
65
64
  ice_nine (0.11.2)
66
65
  json (2.5.1)
67
- minitest (5.14.3)
66
+ minitest (5.14.4)
67
+ msgpack (1.4.2)
68
68
  multi_json (1.15.0)
69
+ newrelic_rpm (6.15.0)
69
70
  pg (1.2.3)
70
71
  rack (2.2.3)
71
72
  rake (13.0.1)
@@ -95,7 +96,9 @@ PLATFORMS
95
96
 
96
97
  DEPENDENCIES
97
98
  bundler
99
+ ddtrace
98
100
  hermes-rb!
101
+ newrelic_rpm
99
102
  pg
100
103
  rake
101
104
  rspec
data/README.md CHANGED
@@ -36,6 +36,9 @@ Rails.application.config.to_prepare do
36
36
  config.instrumenter = Instrumenter
37
37
  config.configure_hutch do |hutch|
38
38
  hutch.uri = ENV.fetch("HUTCH_URI")
39
+ hutch.force_publisher_confirms = true
40
+ hutch.enable_http_api_use = false
41
+ hutch.tracer = MyOwnCustomTracerIfIWantToDoSomethingCrazy
39
42
  end
40
43
  config.distributed_tracing_database_uri = ENV.fetch("DISTRIBUTED_TRACING_DATABASE_URI", nil)
41
44
  config.error_notification_service = Raven
@@ -43,8 +46,15 @@ Rails.application.config.to_prepare do
43
46
 
44
47
  event_handler.handle_events do
45
48
  handle Events::Example::Happened, with: Example::HappenedHandler
46
-
47
49
  handle Events::Example::SyncCallHappened, with: Example::SyncCallHappenedHandler, async: false
50
+
51
+ extra_consumer_config = -> do
52
+ classic_queue
53
+ quorum_queue initial_group_size: 3
54
+ arguments "x-max-length" => 10
55
+ end
56
+ handle Events::Example::SomethingHappenedWithExtraConsumerConfig, with: Example::SomethingHappenedWithExtraConsumerConfigHandler,
57
+ consumer_config: extra_consumer_config
48
58
  end
49
59
 
50
60
  # if you care about distributed tracing
@@ -77,9 +87,13 @@ end
77
87
 
78
88
  If you know what you are doing, you don't necessarily have to process things in the background. As long as the class implements the expected interface, you can do anything you want.
79
89
 
80
- 5. `event_handler` - an instance of event handler/storage, just use what is shown in the example.
90
+ 5. `event_handler` - an instance of event handler/storage, just use what is shown in the example. Notice that you can also pass extra consumer config lambda that will be evaluated within the context of Hutch consumer.
81
91
  6. `clock` - a clock object that is time-zone aware, implementing `now` method.
82
- 7. `configure_hutch` - a way to specify `hutch uri`, basically the URI for RabbitMQ.
92
+ 7. `configure_hutch` - a way to configure Hutch:
93
+ - `uri` - the URI for RabbitMQ, required.
94
+ - `force_publisher_confirms` - defaults to `true`
95
+ - `enable_http_api_use` - defaults to `false`
96
+ - `tracer` - defaults to `Hermes::Tracers::Datadog` if you use Datadog, `Hutch::Tracers::NewRelic` for NewRelic and `Hutch::Tracers::NullTracer` if you use neither Datadog, nor NewRelic. Check APM section for more details if you want to provide a custom tracer.
83
97
  8. `event_handler.handle_events` - that's how you declare events and their handlers. The event handler is an object that responds to `call` method and takes `event` as an argument. All events should ideally be subclasses of `Hermes::BaseEvent`
84
98
 
85
99
  This class inherits from `Dry::Struct`, so getting familiar with [dry-struct gem](https://dry-rb.org/gems/dry-struct/) would be beneficial. Here is an example event:
@@ -134,7 +148,7 @@ If you don't care about it, you can leave it empty.
134
148
 
135
149
  12. `distributed_tracing_database_table` - Table name for storing traces, by default it's `hermes_distributed_traces`. Optional.
136
150
 
137
- 13. `distributes_tracing_mapper` - an object responding to `call` method taking one argument (a hash of attributes) that has to return a hash as well. This hash will be used for assigning attributes when creating `Hermes::DistributedTrace`. The default mapper just returns the original hash. You can use it if you want to remove, for example, some sensitive info from the event's body. Optional.
151
+ 13. `distributes_tracing_mapper` - an object responding to `call` method taking one argument (a hash of attributes) which must return a hash as well. This hash will be used for assigning attributes when creating `Hermes::DistributedTrace`. It defaults to `Hermes::DistributedTrace::Mapper`, which uses `logger_params_filter` to remove sensitive info (this config option is covered below). You can either provide a custom mapper or pass a custom params filter, for example: `Hermes::DistributedTrace::Mapper.new(params_filter: custom_params_filter)`
138
152
 
139
153
  14. `error_notification_service` - an object responding to `capture_exception` method taking one argument (error). Its interface is based on `Raven` from [Sentry Raven](https://github.com/getsentry/sentry-ruby/tree/master/sentry-raven). By default `Hermes::NullErrorNotificationService` is used, which does nothing. Optional.
140
154
 
@@ -144,6 +158,9 @@ If you don't care about it, you can leave it empty.
144
158
 
145
159
  17. `producer_retryable` - used when `safe_producer` was enabled via (`enable_safe_producer`). By default, it is a method retrying delivery 3 times rescuing from `StandardError` each time. The object responsible for this behavior by default is: `Hermes::Retryable.new(times: 3, errors: [StandardError])`.
146
160
 
161
+ 18. `logger_params_filter` - a service used as params filter for logger, to make sure no sensitive data will be logged. It defaults to `Hermes::Logger::ParamsFilter` which already performs some filtering but it might not be enough in your case. If you are not satisfied with the defaults, you have 2 options, which are especially simple in Rails apps:
162
+ - provide custom array of sensitive attributes and still use a default filter: `Hermes::Logger::ParamsFilter.new(sensitive_keywords: Rails.application.config.filter_parameters)`.
163
+ - provide custom filter object, which responds to `call` method and takes 2 arguments: attribute name and its value and performs mutation by using `gsub!` (don't worry, the entire body is cloned before passing it to the filter, so nothing unexpected will happen). This is compatible with the interface of `Rails.application.config.filter_parameters` when you use a custom filter there. In such case, you can do something like this: `Rails.application.config.filter_parameters = [Proc.new { |k, v| do_something_custom_here(k, v) }]` and then just assign `Rails.application.config.filter_parameters.first` in the Hermes config.
147
164
  ## RPC
148
165
 
149
166
  If you want to handle RPC call, you need to add `rpc: true` flag. Keep in mind that RPC requires a synchronous processing and response, so you also need to set `async: false`. The routing key and correlation ID will be resolved based on the message that is published by the client. The payload that is sent back will be what event handler reutrns, so it might be a good idea to just return a hash so that you can operate on JSON easily.
@@ -172,6 +189,12 @@ parsed_response_hash = Hermes::RpcClient.new(rpc_call_timeout: 10).call(event)
172
189
 
173
190
  If the request timeouts, `Hermes::RpcClient::RpcTimeoutError` will be raised.
174
191
 
192
+ ## APM and tracing
193
+
194
+ The integration is enabled automatically if you use `newrelic_rpm` gem via `Hutch::Tracers::NewRelic` or via `Hermes::Tracers::Datadog` when using `ddtrace` gem.
195
+
196
+ You can also provide your own tracer, as long as it implements an interface expected by [Hutch][https://github.com/ruby-amqp/hutch].
197
+
175
198
  ## Distributed Tracing (experimental feature, the interface might change in the future)
176
199
 
177
200
  If you want to take advantage of distributed tracing, you need to specify `distributed_tracing_database_uri` in the config and in many cases that will be enough, although there are some cases where some extra code will be required to properly use it.
@@ -240,8 +263,7 @@ To take advantage of this feature, apply the following logic in the initializer
240
263
 
241
264
  ``` rb
242
265
  Hermes.configure do |config|
243
- config.clock = clock
244
- config.error_notification_service = Raven
266
+ config.error_notification_service = Raven # required for this use case
245
267
  config.enable_safe_producer(HermesRecoveryJob)
246
268
  end
247
269
  ```
@@ -437,6 +459,33 @@ end
437
459
 
438
460
  Hermes is just an extra layer on top of [hutch](https://github.com/gocardless/hutch), refer to Hutch's docs for more info about dealing with the workers and deployment.
439
461
 
462
+ ## Health Checks
463
+
464
+ If you want to perform a health check, use `Hermes::Checks::HealthCheck.check`, which checks if it's possible to connect RabbitMQ via Hutch.
465
+
466
+ The interface is compliant with `health_check`[https://github.com/ianheggie/health_check] gem. If you want to add the custom health check, just add this to the config:
467
+
468
+ ``` rb
469
+ config.add_custom_check("hermes") do
470
+ Hermes::Checks::HealthCheck.check
471
+ end
472
+ ```
473
+
474
+ You can also use `bin/health_check` file to perform healthcheck - on success, the script exits with `0` status and on failure, it logs the error and exits with `1` status.
475
+
476
+ To perform the actual check:
477
+
478
+ 1. Via `health_check` gem:
479
+ ```
480
+ curl -v localhost:3000/health_check/hermes.json
481
+ ```
482
+
483
+ 2. Via binary:
484
+
485
+ ```
486
+ bin/hermes_health_check
487
+ ```
488
+
440
489
  ## CircleCI config for installing RabbitMQ
441
490
 
442
491
  Use `- image: brandembassy/rabbitmq:latest`
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require_relative "../lib/hermes-rb"
5
+
6
+ result = Hermes::Checks::HealthCheck.check
7
+ if result.empty?
8
+ exit 0
9
+ else
10
+ Hermes::DependenciesContainer["logger"].log_health_check_failure(result)
11
+ exit 1
12
+ end
data/hermes-rb.gemspec CHANGED
@@ -23,8 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
25
  end
26
- spec.bindir = "exe"
27
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.bindir = "bin"
27
+ spec.executables = ["hermes_health_check"]
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  spec.add_dependency "dry-struct", "~> 1"
@@ -40,4 +40,6 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "timecop"
41
41
  spec.add_development_dependency "vcr"
42
42
  spec.add_development_dependency "pg"
43
+ spec.add_development_dependency "newrelic_rpm"
44
+ spec.add_development_dependency "ddtrace"
43
45
  end
data/lib/hermes.rb CHANGED
@@ -11,6 +11,7 @@ require "hermes/serializer"
11
11
  require "hermes/rpc_client"
12
12
  require "hermes/null_instrumenter"
13
13
  require "hermes/logger"
14
+ require "hermes/logger/params_filter"
14
15
  require "hermes/rb"
15
16
  require "hermes/b_3_propagation_model_headers"
16
17
  require "hermes/trace_context"
@@ -23,6 +24,8 @@ require "hermes/retryable_event_producer"
23
24
  require "hermes/producer_error_handler"
24
25
  require "hermes/producer_error_handler/null_handler"
25
26
  require "hermes/producer_error_handler/safe_handler"
27
+ require "hermes/tracers"
28
+ require "hermes/checks"
26
29
  require "active_support"
27
30
  require "active_support/core_ext/string"
28
31
  require "active_record"
@@ -50,3 +53,4 @@ module Hermes
50
53
  end
51
54
 
52
55
  require "hermes/distributed_trace"
56
+ require "hermes/distributed_trace/mapper"
@@ -0,0 +1,5 @@
1
+ module Hermes
2
+ module Checks
3
+ autoload :HealthCheck, "hermes/checks/health_check"
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ module Hermes
2
+ module Checks
3
+ class HealthCheck
4
+ def self.check
5
+ broker = Hutch::Broker.new
6
+ broker.connect
7
+ broker.disconnect
8
+ ""
9
+ rescue StandardError => e
10
+ "[Hermes - #{e.message}] "
11
+ end
12
+ end
13
+ end
14
+ end
@@ -4,10 +4,11 @@ module Hermes
4
4
  :background_processor, :enqueue_method, :event_handler, :rpc_call_timeout,
5
5
  :instrumenter, :distributed_tracing_database_uri, :distributed_tracing_database_table,
6
6
  :distributes_tracing_mapper, :database_error_handler, :error_notification_service, :producer_error_handler,
7
- :producer_error_handler_job_class, :producer_retryable
7
+ :producer_error_handler_job_class, :producer_retryable, :logger_params_filter, :tracer
8
8
 
9
9
  def configure_hutch
10
10
  yield hutch
11
+ hutch.commit_config
11
12
  end
12
13
 
13
14
  def self.configure
@@ -44,7 +45,7 @@ module Hermes
44
45
  end
45
46
 
46
47
  def distributes_tracing_mapper
47
- @distributes_tracing_mapper || ->(attributes) { attributes }
48
+ @distributes_tracing_mapper || Hermes::DistributedTrace::Mapper.new
48
49
  end
49
50
 
50
51
  def error_notification_service
@@ -73,8 +74,44 @@ module Hermes
73
74
  )
74
75
  end
75
76
 
77
+ def logger_params_filter
78
+ @logger_params_filter || Hermes::Logger::ParamsFilter.new
79
+ end
80
+
76
81
  class HutchConfig
77
- attr_accessor :uri
82
+ attr_reader :original_hutch_config
83
+ private :original_hutch_config
84
+
85
+ attr_accessor :uri, :force_publisher_confirms, :enable_http_api_use, :tracer
86
+
87
+ def initialize(original_hutch_config: Hutch::Config)
88
+ @original_hutch_config = original_hutch_config
89
+ end
90
+
91
+ def commit_config
92
+ original_hutch_config.set(:tracer, tracer) if tracer
93
+ original_hutch_config.set(:force_publisher_confirms, force_publisher_confirms)
94
+ original_hutch_config.set(:uri, uri)
95
+ end
96
+
97
+ def force_publisher_confirms
98
+ return @force_publisher_confirms if defined?(@force_publisher_confirms)
99
+
100
+ @force_publisher_confirms ||= true
101
+ end
102
+
103
+ def enable_http_api_use
104
+ return @enable_http_api_use if defined?(@enable_http_api_use)
105
+
106
+ @enable_http_api_use ||= false
107
+ end
108
+
109
+ def tracer
110
+ return @tracer if @tracer
111
+ return Hermes::Tracers::Datadog if Object.const_defined?("Datadog")
112
+ return Hutch::Tracers::NewRelic if Object.const_defined?("NewRelic")
113
+ Hutch::Tracers::NullTracer
114
+ end
78
115
  end
79
116
  private_constant :HutchConfig
80
117
  end
@@ -2,7 +2,7 @@ require "hutch"
2
2
 
3
3
  module Hermes
4
4
  class ConsumerBuilder
5
- def build(event_class)
5
+ def build(event_class, consumer_config: -> {})
6
6
  queue = queue_name_from_event(event_class)
7
7
  routing_key = event_class.routing_key
8
8
  consumer_name = consumer_name_from_event(event_class)
@@ -12,6 +12,7 @@ module Hermes
12
12
 
13
13
  consume routing_key
14
14
  queue_name queue
15
+ instance_exec(&consumer_config)
15
16
 
16
17
  define_method :process do |message|
17
18
  instrumenter.instrument("Hermes.Consumer.process") do
@@ -73,8 +73,20 @@ module Hermes
73
73
  config.producer_retryable
74
74
  end
75
75
 
76
+ def self.hutch_logger
77
+ Hutch.logger
78
+ end
79
+
80
+ def self.logger_params_filter
81
+ config.logger_params_filter
82
+ end
83
+
76
84
  def self.objects_resolver
77
85
  Object
78
86
  end
87
+
88
+ def self.consumer_builder
89
+ Hermes::ConsumerBuilder.new
90
+ end
79
91
  end
80
92
  end
@@ -0,0 +1,18 @@
1
+ module Hermes
2
+ class DistributedTrace
3
+ class Mapper
4
+ attr_reader :params_filter
5
+ private :params_filter
6
+
7
+ def initialize(params_filter: Hermes::DependenciesContainer["logger_params_filter"])
8
+ @params_filter = params_filter
9
+ end
10
+
11
+ def call(attributes)
12
+ attributes.deep_dup.tap do |attributes_copy|
13
+ attributes_copy.each { |key, value| params_filter.call(key, value) }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -5,25 +5,27 @@ module Hermes
5
5
  attr_reader :container, :consumer_builder
6
6
  private :container, :consumer_builder
7
7
 
8
- def initialize
9
- @container = Dry::Container.new
10
- @consumer_builder = Hermes::ConsumerBuilder.new
8
+ def initialize(container: Dry::Container.new, consumer_builder: Hermes::DependenciesContainer["consumer_builder"])
9
+ @container = container
10
+ @consumer_builder = consumer_builder
11
11
  end
12
12
 
13
13
  def handle_events(&block)
14
14
  instance_exec(&block)
15
15
  end
16
16
 
17
- def handle(event_class, with:, async: true, rpc: false)
17
+ def handle(event_class, with:, async: true, rpc: false, consumer_config: -> {})
18
18
  handler = with
19
19
  options = {
20
20
  async: async,
21
- rpc: rpc
21
+ rpc: rpc,
22
+ consumer_config: consumer_config
22
23
  }
23
- consumer = build_consumer_for_event(event_class)
24
+ consumer = build_consumer_for_event(event_class, consumer_config)
24
25
 
25
- registration = Registration.new(handler, consumer, options)
26
- container.register(event_class, registration)
26
+ Registration.new(handler, consumer, options).tap do |registration|
27
+ container.register(event_class, registration)
28
+ end
27
29
  end
28
30
 
29
31
  def registration_for(event_class)
@@ -32,8 +34,8 @@ module Hermes
32
34
 
33
35
  private
34
36
 
35
- def build_consumer_for_event(event_class)
36
- consumer_builder.build(event_class)
37
+ def build_consumer_for_event(event_class, consumer_config)
38
+ consumer_builder.build(event_class, consumer_config: consumer_config)
37
39
  end
38
40
 
39
41
  class Registration
@@ -52,6 +54,10 @@ module Hermes
52
54
  def rpc?
53
55
  options.fetch(:rpc) == true
54
56
  end
57
+
58
+ def consumer_config
59
+ optons.fetch(:consumer_config)
60
+ end
55
61
  end
56
62
  end
57
63
  end
data/lib/hermes/logger.rb CHANGED
@@ -1,15 +1,12 @@
1
1
  module Hermes
2
2
  class Logger
3
- SENSITIVE_ATTRIBUTES_KEYWORDS = %w(token password credit_card).freeze
4
- STRIPPED_VALUE = "[STRIPPED]".freeze
3
+ attr_reader :backend, :logger_params_filter
4
+ private :backend, :logger_params_filter
5
5
 
6
- private_constant :SENSITIVE_ATTRIBUTES_KEYWORDS, :STRIPPED_VALUE
7
-
8
- attr_reader :backend
9
- private :backend
10
-
11
- def initialize(backend: Hutch.logger)
6
+ def initialize(backend: Hermes::DependenciesContainer["hutch_logger"],
7
+ logger_params_filter: Hermes::DependenciesContainer["logger_params_filter"])
12
8
  @backend = backend
9
+ @logger_params_filter = logger_params_filter
13
10
  end
14
11
 
15
12
  def log_enqueued(event_class, body, headers, timestamp)
@@ -20,16 +17,16 @@ module Hermes
20
17
  backend.info "[Hutch] published event to: #{routing_key}, properties: #{properties}, body: #{strip_sensitive_info(body)} at #{timestamp}"
21
18
  end
22
19
 
20
+ def log_health_check_failure(error)
21
+ backend.info "[Hermes] health check failed: #{error}"
22
+ end
23
+
23
24
  private
24
25
 
25
26
  def strip_sensitive_info(body)
26
- body.stringify_keys.map do |attribute, value|
27
- if SENSITIVE_ATTRIBUTES_KEYWORDS.any? { |sensitive_attribute| attribute.match(sensitive_attribute) }
28
- [attribute, STRIPPED_VALUE]
29
- else
30
- [attribute, value]
31
- end
32
- end.to_h
27
+ body.deep_dup.tap do |body_copy|
28
+ body_copy.each { |key, value| logger_params_filter.call(key, value) }
29
+ end
33
30
  end
34
31
  end
35
32
  end
@@ -0,0 +1,25 @@
1
+ module Hermes
2
+ class Logger
3
+ class ParamsFilter
4
+ SENSITIVE_ATTRIBUTES_KEYWORDS = %w(token password credit_card card_number security_code verification_value
5
+ private_key signature api_key secret_key publishable_key).freeze
6
+ STRIPPED_VALUE = "[STRIPPED]".freeze
7
+
8
+ private_constant :SENSITIVE_ATTRIBUTES_KEYWORDS, :STRIPPED_VALUE
9
+
10
+ attr_reader :sensitive_keywords, :stripped_value
11
+ private :sensitive_keywords, :stripped_value
12
+
13
+ def initialize(sensitive_keywords: SENSITIVE_ATTRIBUTES_KEYWORDS, stripped_value: STRIPPED_VALUE)
14
+ @sensitive_keywords = sensitive_keywords.map(&:to_s)
15
+ @stripped_value = stripped_value
16
+ end
17
+
18
+ def call(attribute, value)
19
+ if sensitive_keywords.any? { |sensitive_attribute| attribute.to_s.match(sensitive_attribute) } && value.respond_to?(:to_str)
20
+ value.gsub!(value, stripped_value)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,19 +1,19 @@
1
1
  require "forwardable"
2
2
  require "singleton"
3
3
 
4
-
5
4
  module Hermes
6
5
  class Publisher
7
6
  include Singleton
8
7
  extend Forwardable
9
8
 
10
- attr_reader :mutex
11
- private :mutex
9
+ attr_reader :configuration, :mutex
10
+ private :configuration, :mutex
12
11
 
13
12
  def_delegators :current_adapter, :publish
14
13
 
15
- def initialize
16
- super
14
+ def initialize(configuration: Hermes::DependenciesContainer["config"])
15
+ super()
16
+ @configuration = configuration
17
17
  @mutex = Mutex.new
18
18
  end
19
19
 
@@ -34,15 +34,5 @@ module Hermes
34
34
  end
35
35
  end
36
36
  end
37
-
38
- def connect
39
- current_adapter.class.connect
40
- end
41
-
42
- private
43
-
44
- def configuration
45
- Hermes.configuration
46
- end
47
37
  end
48
38
  end
@@ -3,10 +3,7 @@ require "hutch"
3
3
  module Hermes
4
4
  class Publisher::HutchAdapter
5
5
  def self.connect(configuration: Hermes::DependenciesContainer["hutch_config"])
6
- Hutch::Config.set(:uri, configuration.uri)
7
- Hutch::Config.set(:force_publisher_confirms, true)
8
- Hutch::Config.set(:tracer, Hutch::Tracers::NewRelic) if Object.const_defined?("NewRelic")
9
- Hutch.connect(enable_http_api_use: false)
6
+ Hutch.connect(enable_http_api_use: configuration.enable_http_api_use)
10
7
  end
11
8
 
12
9
  def initialize(configuration: Hermes::DependenciesContainer["hutch_config"])
@@ -1,5 +1,5 @@
1
1
  module Hermes
2
2
  module Rb
3
- VERSION = "0.2.0"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
@@ -0,0 +1,5 @@
1
+ module Hermes
2
+ module Tracers
3
+ autoload :Datadog, "hermes/tracers/datadog"
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ require "ddtrace"
2
+
3
+ module Hermes
4
+ module Tracers
5
+ class Datadog
6
+ attr_reader :klass
7
+ private :klass
8
+
9
+ def initialize(klass)
10
+ @klass = klass
11
+ end
12
+
13
+ def handle(message)
14
+ ::Datadog.tracer.trace(klass.class.name, service: "hermes", span_type: "rabbitmq") do
15
+ klass.process(message)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hermes-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Galanciak
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-13 00:00:00.000000000 Z
11
+ date: 2021-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct
@@ -178,11 +178,40 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: newrelic_rpm
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: ddtrace
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
181
209
  description: A messenger of gods, delivering them via RabbitMQ with a little help
182
210
  from Hutch
183
211
  email:
184
212
  - dev@bookingsync.com
185
- executables: []
213
+ executables:
214
+ - hermes_health_check
186
215
  extensions: []
187
216
  extra_rdoc_files: []
188
217
  files:
@@ -196,22 +225,27 @@ files:
196
225
  - README.md
197
226
  - Rakefile
198
227
  - bin/console
228
+ - bin/hermes_health_check
199
229
  - bin/setup
200
230
  - hermes-rb.gemspec
201
231
  - lib/hermes-rb.rb
202
232
  - lib/hermes.rb
203
233
  - lib/hermes/b_3_propagation_model_headers.rb
204
234
  - lib/hermes/base_event.rb
235
+ - lib/hermes/checks.rb
236
+ - lib/hermes/checks/health_check.rb
205
237
  - lib/hermes/configuration.rb
206
238
  - lib/hermes/consumer_builder.rb
207
239
  - lib/hermes/database_error_handler.rb
208
240
  - lib/hermes/dependencies_container.rb
209
241
  - lib/hermes/distributed_trace.rb
242
+ - lib/hermes/distributed_trace/mapper.rb
210
243
  - lib/hermes/distributed_trace_repository.rb
211
244
  - lib/hermes/event_handler.rb
212
245
  - lib/hermes/event_processor.rb
213
246
  - lib/hermes/event_producer.rb
214
247
  - lib/hermes/logger.rb
248
+ - lib/hermes/logger/params_filter.rb
215
249
  - lib/hermes/null_error_notification_service.rb
216
250
  - lib/hermes/null_instrumenter.rb
217
251
  - lib/hermes/producer_error_handler.rb
@@ -229,6 +263,8 @@ files:
229
263
  - lib/hermes/serializer.rb
230
264
  - lib/hermes/support/matchers/publish_async_message.rb
231
265
  - lib/hermes/trace_context.rb
266
+ - lib/hermes/tracers.rb
267
+ - lib/hermes/tracers/datadog.rb
232
268
  - untitled
233
269
  homepage: https://github.com/BookingSync/hermes-rb
234
270
  licenses: