airbrake-ruby 4.0.1 → 4.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
  SHA1:
3
- metadata.gz: 681ed72fb1b600b723e7dbb48c607d37a58a1c71
4
- data.tar.gz: 3afa4336efbf5c0aa621eeebc6d1e890a0af7254
3
+ metadata.gz: 25d739899ae0250aa01c5e81ab01d76bbcfac28d
4
+ data.tar.gz: fca6e05b839805cb5d4b4171145c1dfeb4b4890b
5
5
  SHA512:
6
- metadata.gz: daadebdf259818ec34b172c694ea942416b498451461cdb09e728e28245fa0456dc8fe07fc000f01966650c6b567f7ec10cd46126c2d443e4d783c5670b29247
7
- data.tar.gz: 8f2df8d80dbc8be84cf48a88678ee98ce4a538d02e995d63dfa1392dbb5acd0edd787f605b85f161b5131d20260e94345ae994fe77a3359a3c281b453bfc9804
6
+ metadata.gz: 13fd52e48ce2f8405640785323f2cc330d9364496b58ce0b8fb416b28baff5584a95b97ded5441ee47aca872af43cf7251ebb7cfd6d3b1660c523ee774e6a870
7
+ data.tar.gz: d96f9bb73da48029a993bda925ec727a945177300721eb521f5966bac962f6d9ae2941cd191b4bc2d5497c07da7764c5d7c740bf5bb7fc0a30b61c50b263c08f
data/lib/airbrake-ruby.rb CHANGED
@@ -77,71 +77,9 @@ module Airbrake
77
77
  # @!macro see_public_api_method
78
78
  # @see Airbrake.$0
79
79
 
80
- # NilNoticeNotifier is a no-op notice notifier, which mimics
81
- # +Airbrake::NoticeNotifier+ and serves only the purpose of making the library
82
- # API easier to use.
83
- #
84
- # @since v2.1.0
85
- class NilNoticeNotifier
86
- # @macro see_public_api_method
87
- def notify(_exception, _params = {}, &block); end
88
-
89
- # @macro see_public_api_method
90
- def notify_sync(_exception, _params = {}, &block); end
91
-
92
- # @macro see_public_api_method
93
- def add_filter(_filter = nil, &_block); end
94
-
95
- # @macro see_public_api_method
96
- def delete_filter(_filter_class); end
97
-
98
- # @macro see_public_api_method
99
- def build_notice(_exception, _params = {}); end
100
-
101
- # @macro see_public_api_method
102
- def close; end
103
-
104
- # @macro see_public_api_method
105
- def configured?
106
- false
107
- end
108
-
109
- # @macro see_public_api_method
110
- def merge_context(_context); end
111
- end
112
-
113
- # NilPerformanceNotifier is a no-op notifier, which mimics
114
- # {Airbrake::PerformanceNotifier} and serves only the purpose of making the
115
- # library API easier to use.
116
- #
117
- # @since v3.2.0
118
- class NilPerformanceNotifier
119
- # @see Airbrake.notify_request
120
- # @see Airbrake.notify_query
121
- def notify(_performance_info); end
122
-
123
- # @see Airbrake.notify_request
124
- # @see Airbrake.notify_query
125
- def add_filter(_filter = nil, &_block); end
126
-
127
- # @see Airbrake.notify_request
128
- # @see Airbrake.notify_query
129
- def delete_filter(_filter_class); end
130
- end
131
-
132
- # NilDeployNotifier is a no-op notifier, which mimics
133
- # {Airbrake::DeployNotifier} and serves only the purpose of making the library
134
- # API easier to use.
135
- #
136
- # @since v3.2.0
137
- class NilDeployNotifier
138
- # @see Airbrake.notify_deploy
139
- def notify(_deploy_info); end
140
- end
141
-
142
- @notice_notifier = NilNoticeNotifier.new
143
- @performance_notifier = NilPerformanceNotifier.new
144
- @deploy_notifier = NilDeployNotifier.new
80
+ @performance_notifier = PerformanceNotifier.new
81
+ @notice_notifier = NoticeNotifier.new
82
+ @deploy_notifier = DeployNotifier.new
145
83
 
146
84
  class << self
147
85
  # Configures the Airbrake notifier.
@@ -163,13 +101,11 @@ module Airbrake
163
101
  def configure
164
102
  yield config = Airbrake::Config.instance
165
103
 
166
- raise Airbrake::Error, config.validation_error_message unless config.valid?
104
+ if (result = config.validate).rejected?
105
+ raise Airbrake::Error, result.value['error']
106
+ end
167
107
 
168
108
  Airbrake::Loggable.instance = config.logger
169
-
170
- @performance_notifier = PerformanceNotifier.new
171
- @notice_notifier = NoticeNotifier.new
172
- @deploy_notifier = DeployNotifier.new
173
109
  end
174
110
 
175
111
  # @return [Boolean] true if the notifier was configured, false otherwise
@@ -217,7 +153,7 @@ module Airbrake
217
153
  # @yield [notice] The notice to filter
218
154
  # @yieldparam [Airbrake::Notice]
219
155
  # @yieldreturn [void]
220
- # @return [Hash{String=>String}] the reponse from the server
156
+ # @return [Airbrake::Promise] the reponse from the server
221
157
  # @see .notify
222
158
  def notify_sync(exception, params = {}, &block)
223
159
  @notice_notifier.notify_sync(exception, params, &block)
@@ -108,8 +108,6 @@ module Airbrake
108
108
  # @param [Hash{Symbol=>Object}] user_config the hash to be used to build the
109
109
  # config
110
110
  def initialize(user_config = {})
111
- @validator = Config::Validator.new(self)
112
-
113
111
  self.proxy = {}
114
112
  self.queue_size = 100
115
113
  self.workers = 1
@@ -169,35 +167,34 @@ module Airbrake
169
167
  # @return [Boolean] true if the config meets the requirements, false
170
168
  # otherwise
171
169
  def valid?
172
- return true if ignored_environment?
173
-
174
- return false unless @validator.valid_project_id?
175
- return false unless @validator.valid_project_key?
176
- return false unless @validator.valid_environment?
170
+ validate.resolved?
171
+ end
177
172
 
178
- true
173
+ # @return [Promise]
174
+ # @see Validator.validate
175
+ def validate
176
+ Validator.validate(self)
179
177
  end
180
178
 
181
- def validation_error_message
182
- @validator.error_message
179
+ # @return [Promise]
180
+ # @see Validator.check_notify_ability
181
+ def check_notify_ability
182
+ Validator.check_notify_ability(self)
183
183
  end
184
184
 
185
185
  # @return [Boolean] true if the config ignores current environment, false
186
186
  # otherwise
187
187
  def ignored_environment?
188
- if ignore_environments.any? && environment.nil?
189
- logger.warn("#{LOG_LABEL} the 'environment' option is not set, " \
190
- "'ignore_environments' has no effect")
191
- end
188
+ check_notify_ability.rejected?
189
+ end
192
190
 
193
- env = environment.to_s
194
- ignore_environments.any? do |pattern|
195
- if pattern.is_a?(Regexp)
196
- env.match(pattern)
197
- else
198
- env == pattern.to_s
199
- end
200
- end
191
+ # @return [Promise] resolved promise if config is valid & can notify,
192
+ # rejected otherwise
193
+ def check_configuration
194
+ promise = validate
195
+ return promise if promise.rejected?
196
+
197
+ check_notify_ability
201
198
  end
202
199
 
203
200
  private
@@ -1,62 +1,90 @@
1
1
  module Airbrake
2
2
  class Config
3
- # Validates values of {Airbrake::Config} options.
3
+ # Validator validates values of {Airbrake::Config} options. A valid config
4
+ # is a config that guarantees that data can be sent to Airbrake given its
5
+ # configuration.
4
6
  #
5
7
  # @api private
6
8
  # @since v1.5.0
7
9
  class Validator
8
- # @return [String]
9
- REQUIRED_KEY_MSG = ':project_key is required'.freeze
10
-
11
- # @return [String]
12
- REQUIRED_ID_MSG = ':project_id is required'.freeze
13
-
14
- # @return [String]
15
- WRONG_ENV_TYPE_MSG = "the 'environment' option must be configured " \
16
- "with a Symbol (or String), but '%s' was provided: " \
17
- '%s'.freeze
18
-
19
10
  # @return [Array<Class>] the list of allowed types to configure the
20
11
  # environment option
21
12
  VALID_ENV_TYPES = [NilClass, String, Symbol].freeze
22
13
 
23
- # @return [String] error message, if validator was able to find any errors
24
- # in the config
25
- attr_reader :error_message
26
-
27
- # Validates given config and stores error message, if any errors were
28
- # found.
29
- #
30
- # @param config [Airbrake::Config] the config to validate
31
- def initialize(config)
32
- @config = config
33
- @error_message = nil
34
- end
14
+ class << self
15
+ # @param [Airbrake::Config] config
16
+ # @since v4.1.0
17
+ def validate(config)
18
+ promise = Airbrake::Promise.new
35
19
 
36
- # @return [Boolean]
37
- def valid_project_id?
38
- valid = @config.project_id.to_i > 0
39
- @error_message = REQUIRED_ID_MSG unless valid
40
- valid
41
- end
20
+ unless valid_project_id?(config)
21
+ return promise.reject(':project_id is required')
22
+ end
42
23
 
43
- # @return [Boolean]
44
- def valid_project_key?
45
- valid = @config.project_key.is_a?(String) && !@config.project_key.empty?
46
- @error_message = REQUIRED_KEY_MSG unless valid
47
- valid
48
- end
24
+ unless valid_project_key?(config)
25
+ return promise.reject(':project_key is required')
26
+ end
27
+
28
+ unless valid_environment?(config)
29
+ return promise.reject(
30
+ "the 'environment' option must be configured " \
31
+ "with a Symbol (or String), but '#{config.environment.class}' was " \
32
+ "provided: #{config.environment}"
33
+ )
34
+ end
35
+
36
+ promise.resolve(:ok)
37
+ end
38
+
39
+ # Whether the given +config+ allows sending data to Airbrake. It doesn't
40
+ # matter if it's valid or invalid.
41
+ #
42
+ # @param [Airbrake::Config] config
43
+ # @since v4.1.0
44
+ def check_notify_ability(config)
45
+ promise = Airbrake::Promise.new
49
46
 
50
- # @return [Boolean]
51
- def valid_environment?
52
- environment = @config.environment
53
- valid = VALID_ENV_TYPES.any? { |type| environment.is_a?(type) }
47
+ if ignored_environment?(config)
48
+ return promise.reject(
49
+ "current environment '#{config.environment}' is ignored"
50
+ )
51
+ end
54
52
 
55
- unless valid
56
- @error_message = format(WRONG_ENV_TYPE_MSG, environment.class, environment)
53
+ promise.resolve(:ok)
57
54
  end
58
55
 
59
- valid
56
+ private
57
+
58
+ def valid_project_id?(config)
59
+ return true if config.project_id.to_i > 0
60
+ false
61
+ end
62
+
63
+ def valid_project_key?(config)
64
+ return false unless config.project_key.is_a?(String)
65
+ return false if config.project_key.empty?
66
+ true
67
+ end
68
+
69
+ def valid_environment?(config)
70
+ VALID_ENV_TYPES.any? { |type| config.environment.is_a?(type) }
71
+ end
72
+
73
+ def ignored_environment?(config)
74
+ if config.ignore_environments.any? && config.environment.nil?
75
+ config.logger.warn(
76
+ "#{LOG_LABEL} the 'environment' option is not set, " \
77
+ "'ignore_environments' has no effect"
78
+ )
79
+ end
80
+
81
+ return false if config.ignore_environments.none? || !config.environment
82
+
83
+ env = config.environment.to_s
84
+ config.ignore_environments.any? do |pattern|
85
+ pattern.is_a?(Regexp) ? env.match(pattern) : env == pattern.to_s
86
+ end
87
+ end
60
88
  end
61
89
  end
62
90
  end
@@ -18,11 +18,11 @@ module Airbrake
18
18
  end
19
19
 
20
20
  # @see Airbrake.notify_deploy
21
- def notify(deploy_info, promise = Airbrake::Promise.new)
22
- if @config.ignored_environment?
23
- return promise.reject("The '#{@config.environment}' environment is ignored")
24
- end
21
+ def notify(deploy_info)
22
+ promise = @config.check_configuration
23
+ return promise if promise.rejected?
25
24
 
25
+ promise = Airbrake::Promise.new
26
26
  deploy_info[:environment] ||= @config.environment
27
27
  @sender.send(
28
28
  deploy_info,
@@ -95,15 +95,14 @@ module Airbrake
95
95
  end
96
96
 
97
97
  def send_notice(exception, params, sender)
98
- promise = Airbrake::Promise.new
99
- if @config.ignored_environment?
100
- return promise.reject("The '#{@config.environment}' environment is ignored")
101
- end
98
+ promise = @config.check_configuration
99
+ return promise if promise.rejected?
102
100
 
103
101
  notice = build_notice(exception, params)
104
102
  yield notice if block_given?
105
103
  @filter_chain.refine(notice)
106
104
 
105
+ promise = Airbrake::Promise.new
107
106
  return promise.reject("#{notice} was marked as ignored") if notice.ignored?
108
107
 
109
108
  sender.send(notice, promise)
@@ -19,14 +19,13 @@ module Airbrake
19
19
  end
20
20
 
21
21
  # @param [Hash] resource
22
- # @param [Airbrake::Promise] promise
23
22
  # @see Airbrake.notify_query
24
23
  # @see Airbrake.notify_request
25
- def notify(resource, promise = Airbrake::Promise.new)
26
- if @config.ignored_environment?
27
- return promise.reject("The '#{@config.environment}' environment is ignored")
28
- end
24
+ def notify(resource)
25
+ promise = @config.check_configuration
26
+ return promise if promise.rejected?
29
27
 
28
+ promise = Airbrake::Promise.new
30
29
  unless @config.performance_stats
31
30
  return promise.reject("The Performance Stats feature is disabled")
32
31
  end
@@ -7,12 +7,6 @@ module Airbrake
7
7
  # @see https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/promise.rb
8
8
  # @since v1.7.0
9
9
  class Promise
10
- # @api private
11
- # @return [Hash<String,String>] either successful response containing the
12
- # +id+ key or unsuccessful response containing the +error+ key
13
- # @note This is a non-blocking call!
14
- attr_reader :value
15
-
16
10
  def initialize
17
11
  @on_resolved = []
18
12
  @on_rejected = []
@@ -32,8 +26,8 @@ module Airbrake
32
26
  # @return [self]
33
27
  def then(&block)
34
28
  @mutex.synchronize do
35
- if @value.key?('id')
36
- yield(@value)
29
+ if @value.key?('ok')
30
+ yield(@value['ok'])
37
31
  return self
38
32
  end
39
33
 
@@ -64,36 +58,52 @@ module Airbrake
64
58
  self
65
59
  end
66
60
 
67
- # Resolves the promise.
68
- #
69
61
  # @example
70
62
  # Airbrake::Promise.new.resolve('id' => '123')
71
63
  #
72
- # @param response [Hash<String,String>]
64
+ # @param reason [Object]
73
65
  # @return [self]
74
- def resolve(response)
66
+ def resolve(reason = 'resolved')
75
67
  @mutex.synchronize do
76
- @value = response
77
- @on_resolved.each { |callback| callback.call(response) }
68
+ @value['ok'] = reason
69
+ @on_resolved.each { |callback| callback.call(reason) }
78
70
  end
79
71
 
80
72
  self
81
73
  end
82
74
 
83
- # Rejects the promise.
84
- #
85
75
  # @example
86
76
  # Airbrake::Promise.new.reject('Something went wrong')
87
77
  #
88
- # @param error [String]
78
+ # @param reason [String]
89
79
  # @return [self]
90
- def reject(error)
80
+ def reject(reason = 'rejected')
91
81
  @mutex.synchronize do
92
- @value['error'] = error
93
- @on_rejected.each { |callback| callback.call(error) }
82
+ @value['error'] = reason
83
+ @on_rejected.each { |callback| callback.call(reason) }
94
84
  end
95
85
 
96
86
  self
97
87
  end
88
+
89
+ # @return [Boolean]
90
+ def rejected?
91
+ @value.key?('error')
92
+ end
93
+
94
+ # @return [Boolean]
95
+ def resolved?
96
+ @value.key?('ok')
97
+ end
98
+
99
+ # @return [Hash<String,String>] either successful response containing the
100
+ # +id+ key or unsuccessful response containing the +error+ key
101
+ # @note This is a non-blocking call!
102
+ # @todo Get rid of this method and use an accessor. The resolved guard is
103
+ # needed for compatibility but it shouldn't exist in the future
104
+ def value
105
+ return @value['ok'] if resolved?
106
+ @value
107
+ end
98
108
  end
99
109
  end