hermes-rb 0.2.0 → 0.3.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: cc074c27cdac75e904004b2bd84d3d633f669251f5476065a9691979df5334da
4
+ data.tar.gz: 0255b07f12767b699b9bffb006ef00f8fc782f72c394bc5ab0622089441cf43b
5
5
  SHA512:
6
- metadata.gz: aea75486bab7ba279b788dc48ea465f3ecb96c7281d9b6cc9bc29443c738ba779fe0951f6d0a8028211cce4f64520556f085cab73aee7ba98bac01af9dc5a973
7
- data.tar.gz: 10b79dce9ad5c116d6ccb31a6102b1e3732a2b0a73e328b5ef37b421e5407cc8a5cc240e6b68c11b7fd26bd2c06acb579a610ba3708d83515d5c17dc48207f50
6
+ metadata.gz: 07d4527111544947adfb5222634df4b8a6f02169e612174a1de52723eeafc51a30daf3515b341f532244bf87e106cb204b6f7b5142f043e8aa24917a8e6374bc
7
+ data.tar.gz: 9d2f1c37b34b417c1fc9340590546f38608d67af7d1efb77d8a8853ea9827e0b6a19b43cfaad465867be52032bffe1446a2ef9280253d12896d124fbde6e0502
data/Changelog.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## Master
4
+
5
+ ## 0.3.0
6
+ - Reorganize Hutch config - instead of setting config values when connecting to Hutch when using publisher, do it right after the initialization.
7
+ - Make params filter customizable for the logger
8
+ - Remove sensitive info when creating distributed trace records.
9
+
3
10
  ## 0.2.0
4
11
  - Implement "Safe Producer" extension allowing to retry delivery later in an automated way when publishing of the message fails.
5
12
 
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.3.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.2.1)
16
+ activesupport (= 6.1.2.1)
17
+ activerecord (6.1.2.1)
18
+ activemodel (= 6.1.2.1)
19
+ activesupport (= 6.1.2.1)
20
+ activesupport (6.1.2.1)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (>= 1.6, < 2)
23
23
  minitest (>= 5.1)
@@ -28,7 +28,7 @@ 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
32
  diff-lcs (1.4.4)
33
33
  dry-configurable (0.12.0)
34
34
  concurrent-ruby (~> 1.0)
@@ -38,21 +38,18 @@ GEM
38
38
  dry-configurable (~> 0.1, >= 0.1.3)
39
39
  dry-core (0.5.0)
40
40
  concurrent-ruby (~> 1.0)
41
- dry-equalizer (0.3.0)
42
41
  dry-inflector (0.2.0)
43
42
  dry-logic (1.1.0)
44
43
  concurrent-ruby (~> 1.0)
45
44
  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)
45
+ dry-struct (1.4.0)
46
+ dry-core (~> 0.5, >= 0.5)
47
+ dry-types (~> 1.5)
50
48
  ice_nine (~> 0.11)
51
- dry-types (1.4.0)
49
+ dry-types (1.5.0)
52
50
  concurrent-ruby (~> 1.0)
53
51
  dry-container (~> 0.3)
54
- dry-core (~> 0.4, >= 0.4.4)
55
- dry-equalizer (~> 0.3)
52
+ dry-core (~> 0.5, >= 0.5)
56
53
  dry-inflector (~> 0.1, >= 0.1.2)
57
54
  dry-logic (~> 1.0, >= 1.0.2)
58
55
  hutch (1.0.0)
@@ -60,12 +57,13 @@ GEM
60
57
  bunny (>= 2.15, < 2.16)
61
58
  carrot-top (~> 0.0.7)
62
59
  multi_json (~> 1.14)
63
- i18n (1.8.7)
60
+ i18n (1.8.9)
64
61
  concurrent-ruby (~> 1.0)
65
62
  ice_nine (0.11.2)
66
63
  json (2.5.1)
67
64
  minitest (5.14.3)
68
65
  multi_json (1.15.0)
66
+ newrelic_rpm (6.15.0)
69
67
  pg (1.2.3)
70
68
  rack (2.2.3)
71
69
  rake (13.0.1)
@@ -96,6 +94,7 @@ PLATFORMS
96
94
  DEPENDENCIES
97
95
  bundler
98
96
  hermes-rb!
97
+ newrelic_rpm
99
98
  pg
100
99
  rake
101
100
  rspec
data/README.md CHANGED
@@ -36,6 +36,8 @@ 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
39
41
  end
40
42
  config.distributed_tracing_database_uri = ENV.fetch("DISTRIBUTED_TRACING_DATABASE_URI", nil)
41
43
  config.error_notification_service = Raven
@@ -79,7 +81,10 @@ If you know what you are doing, you don't necessarily have to process things in
79
81
 
80
82
  5. `event_handler` - an instance of event handler/storage, just use what is shown in the example.
81
83
  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.
84
+ 7. `configure_hutch` - a way to configure Hutch:
85
+ - `uri` - the URI for RabbitMQ, required.
86
+ - `force_publisher_confirms` - defaults to `true`
87
+ - `enable_http_api_use` - defaults to `false`
83
88
  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
89
 
85
90
  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 +139,7 @@ If you don't care about it, you can leave it empty.
134
139
 
135
140
  12. `distributed_tracing_database_table` - Table name for storing traces, by default it's `hermes_distributed_traces`. Optional.
136
141
 
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.
142
+ 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
143
 
139
144
  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
145
 
@@ -144,6 +149,9 @@ If you don't care about it, you can leave it empty.
144
149
 
145
150
  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
151
 
152
+ 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:
153
+ - provide custom array of sensitive attributes and still use a default filter: `Hermes::Logger::ParamsFilter.new(sensitive_keywords: Rails.application.config.filter_parameters)`.
154
+ - 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
155
  ## RPC
148
156
 
149
157
  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 +180,10 @@ parsed_response_hash = Hermes::RpcClient.new(rpc_call_timeout: 10).call(event)
172
180
 
173
181
  If the request timeouts, `Hermes::RpcClient::RpcTimeoutError` will be raised.
174
182
 
183
+ ## NewRelic integration
184
+
185
+ The integration is enabled automatically if you use `newrelic_rpm` gem via `Hutch::Tracers::NewRelic`.
186
+
175
187
  ## Distributed Tracing (experimental feature, the interface might change in the future)
176
188
 
177
189
  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 +252,7 @@ To take advantage of this feature, apply the following logic in the initializer
240
252
 
241
253
  ``` rb
242
254
  Hermes.configure do |config|
243
- config.clock = clock
244
- config.error_notification_service = Raven
255
+ config.error_notification_service = Raven # required for this use case
245
256
  config.enable_safe_producer(HermesRecoveryJob)
246
257
  end
247
258
  ```
data/hermes-rb.gemspec CHANGED
@@ -40,4 +40,5 @@ 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"
43
44
  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"
@@ -50,3 +51,4 @@ module Hermes
50
51
  end
51
52
 
52
53
  require "hermes/distributed_trace"
54
+ require "hermes/distributed_trace/mapper"
@@ -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
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,37 @@ 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
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, Hutch::Tracers::NewRelic) if Object.const_defined?("NewRelic")
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
78
108
  end
79
109
  private_constant :HutchConfig
80
110
  end
@@ -73,6 +73,14 @@ 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
@@ -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
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)
@@ -23,13 +20,9 @@ module Hermes
23
20
  private
24
21
 
25
22
  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
23
+ body.deep_dup.tap do |body_copy|
24
+ body_copy.each { |key, value| logger_params_filter.call(key, value) }
25
+ end
33
26
  end
34
27
  end
35
28
  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) }
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.3.0"
4
4
  end
5
5
  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.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Galanciak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-13 00:00:00.000000000 Z
11
+ date: 2021-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct
@@ -178,6 +178,20 @@ 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'
181
195
  description: A messenger of gods, delivering them via RabbitMQ with a little help
182
196
  from Hutch
183
197
  email:
@@ -207,11 +221,13 @@ files:
207
221
  - lib/hermes/database_error_handler.rb
208
222
  - lib/hermes/dependencies_container.rb
209
223
  - lib/hermes/distributed_trace.rb
224
+ - lib/hermes/distributed_trace/mapper.rb
210
225
  - lib/hermes/distributed_trace_repository.rb
211
226
  - lib/hermes/event_handler.rb
212
227
  - lib/hermes/event_processor.rb
213
228
  - lib/hermes/event_producer.rb
214
229
  - lib/hermes/logger.rb
230
+ - lib/hermes/logger/params_filter.rb
215
231
  - lib/hermes/null_error_notification_service.rb
216
232
  - lib/hermes/null_instrumenter.rb
217
233
  - lib/hermes/producer_error_handler.rb