airbrake-ruby 4.15.0-java → 5.0.0.rc.1-java
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 +4 -4
- data/lib/airbrake-ruby.rb +21 -33
- data/lib/airbrake-ruby/async_sender.rb +1 -1
- data/lib/airbrake-ruby/config.rb +34 -6
- data/lib/airbrake-ruby/config/processor.rb +80 -0
- data/lib/airbrake-ruby/config/validator.rb +4 -0
- data/lib/airbrake-ruby/performance_notifier.rb +1 -1
- data/lib/airbrake-ruby/remote_settings.rb +128 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/sync_sender.rb +1 -1
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +45 -22
- data/spec/config/processor_spec.rb +223 -0
- data/spec/config/validator_spec.rb +18 -1
- data/spec/config_spec.rb +8 -4
- data/spec/remote_settings/settings_data_spec.rb +327 -0
- data/spec/remote_settings_spec.rb +212 -0
- data/spec/sync_sender_spec.rb +3 -1
- metadata +13 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a60c7ee3f35357ecbe72d0bdedb89a61b248101ac58d866166e5daa1e2f79eb
|
4
|
+
data.tar.gz: 53a68e1f1bab4158d773593ad201dce948a0df60c0fd1b80a27451a96dc5596c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d14d8843ea3d8c8923b654d5c1110fbefb83b40b63a15c930b5243de81f5ecd594d8e08be64a8242884793a6203f535d16088ebbbef3328d519f8cfd440d19e
|
7
|
+
data.tar.gz: '08fdf62186815e85696acd66641f60bfeca556c2a3e30c0b7d7c49c3f02bdd208d795aceee9af65a4683773580682f8efa96a61434a716118a8a85346432d41f'
|
data/lib/airbrake-ruby.rb
CHANGED
@@ -12,6 +12,9 @@ require 'airbrake-ruby/mergeable'
|
|
12
12
|
require 'airbrake-ruby/grouppable'
|
13
13
|
require 'airbrake-ruby/config'
|
14
14
|
require 'airbrake-ruby/config/validator'
|
15
|
+
require 'airbrake-ruby/config/processor'
|
16
|
+
require 'airbrake-ruby/remote_settings/settings_data'
|
17
|
+
require 'airbrake-ruby/remote_settings'
|
15
18
|
require 'airbrake-ruby/promise'
|
16
19
|
require 'airbrake-ruby/thread_pool'
|
17
20
|
require 'airbrake-ruby/sync_sender'
|
@@ -117,7 +120,15 @@ module Airbrake
|
|
117
120
|
def configure
|
118
121
|
yield config = Airbrake::Config.instance
|
119
122
|
Airbrake::Loggable.instance = config.logger
|
120
|
-
|
123
|
+
|
124
|
+
config_processor = Airbrake::Config::Processor.new(config)
|
125
|
+
|
126
|
+
config_processor.process_blocklist(notice_notifier)
|
127
|
+
config_processor.process_allowlist(notice_notifier)
|
128
|
+
|
129
|
+
@remote_settings ||= config_processor.process_remote_configuration
|
130
|
+
|
131
|
+
config_processor.add_filters(notice_notifier)
|
121
132
|
end
|
122
133
|
|
123
134
|
# @since v4.2.3
|
@@ -260,8 +271,8 @@ module Airbrake
|
|
260
271
|
# Airbrake.close
|
261
272
|
# Airbrake.notify('App crashed!') #=> raises Airbrake::Error
|
262
273
|
#
|
263
|
-
# @return [
|
264
|
-
# rubocop:disable Style/
|
274
|
+
# @return [nil]
|
275
|
+
# rubocop:disable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
|
265
276
|
def close
|
266
277
|
if defined?(@notice_notifier) && @notice_notifier
|
267
278
|
@notice_notifier.close
|
@@ -270,8 +281,14 @@ module Airbrake
|
|
270
281
|
if defined?(@performance_notifier) && @performance_notifier
|
271
282
|
@performance_notifier.close
|
272
283
|
end
|
284
|
+
|
285
|
+
if defined?(@remote_settings) && @remote_settings
|
286
|
+
@remote_settings.stop_polling
|
287
|
+
end
|
288
|
+
|
289
|
+
nil
|
273
290
|
end
|
274
|
-
# rubocop:enable Style/
|
291
|
+
# rubocop:enable Style/IfUnlessModifier, Metrics/CyclomaticComplexity
|
275
292
|
|
276
293
|
# Pings the Airbrake Deploy API endpoint about the occurred deploy.
|
277
294
|
#
|
@@ -567,35 +584,6 @@ module Airbrake
|
|
567
584
|
self.notice_notifier = NoticeNotifier.new
|
568
585
|
self.deploy_notifier = DeployNotifier.new
|
569
586
|
end
|
570
|
-
|
571
|
-
private
|
572
|
-
|
573
|
-
# rubocop:disable Metrics/AbcSize
|
574
|
-
def process_config_options(config)
|
575
|
-
if config.blocklist_keys.any?
|
576
|
-
blocklist = Airbrake::Filters::KeysBlocklist.new(config.blocklist_keys)
|
577
|
-
notice_notifier.add_filter(blocklist)
|
578
|
-
end
|
579
|
-
|
580
|
-
if config.allowlist_keys.any?
|
581
|
-
allowlist = Airbrake::Filters::KeysAllowlist.new(config.allowlist_keys)
|
582
|
-
notice_notifier.add_filter(allowlist)
|
583
|
-
end
|
584
|
-
|
585
|
-
return unless config.root_directory
|
586
|
-
|
587
|
-
[
|
588
|
-
Airbrake::Filters::RootDirectoryFilter,
|
589
|
-
Airbrake::Filters::GitRevisionFilter,
|
590
|
-
Airbrake::Filters::GitRepositoryFilter,
|
591
|
-
Airbrake::Filters::GitLastCheckoutFilter,
|
592
|
-
].each do |filter|
|
593
|
-
next if notice_notifier.has_filter?(filter)
|
594
|
-
|
595
|
-
notice_notifier.add_filter(filter.new(config.root_directory))
|
596
|
-
end
|
597
|
-
end
|
598
|
-
# rubocop:enable Metrics/AbcSize
|
599
587
|
end
|
600
588
|
end
|
601
589
|
# rubocop:enable Metrics/ModuleLength
|
@@ -16,7 +16,7 @@ module Airbrake
|
|
16
16
|
#
|
17
17
|
# @param [Hash] payload Whatever needs to be sent
|
18
18
|
# @return [Airbrake::Promise]
|
19
|
-
def send(payload, promise, endpoint = @config.
|
19
|
+
def send(payload, promise, endpoint = @config.error_endpoint)
|
20
20
|
unless thread_pool << [payload, promise, endpoint]
|
21
21
|
return promise.reject(
|
22
22
|
"AsyncSender has reached its capacity of #{@config.queue_size}",
|
data/lib/airbrake-ruby/config.rb
CHANGED
@@ -4,6 +4,7 @@ module Airbrake
|
|
4
4
|
#
|
5
5
|
# @api public
|
6
6
|
# @since v1.0.0
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
7
8
|
class Config
|
8
9
|
# @return [Integer] the project identificator. This value *must* be set.
|
9
10
|
# @api public
|
@@ -46,6 +47,17 @@ module Airbrake
|
|
46
47
|
# @api public
|
47
48
|
attr_accessor :host
|
48
49
|
|
50
|
+
# @since v?.?.?
|
51
|
+
alias error_host host
|
52
|
+
# @since v?.?.?
|
53
|
+
alias error_host= host=
|
54
|
+
|
55
|
+
# @return [String] the host, which provides the API endpoint to which
|
56
|
+
# APM data should be sent
|
57
|
+
# @api public
|
58
|
+
# @since v?.?.?
|
59
|
+
attr_accessor :apm_host
|
60
|
+
|
49
61
|
# @return [String, Pathname] the working directory of your project
|
50
62
|
# @api public
|
51
63
|
attr_accessor :root_directory
|
@@ -113,6 +125,18 @@ module Airbrake
|
|
113
125
|
# @since v4.12.0
|
114
126
|
attr_accessor :job_stats
|
115
127
|
|
128
|
+
# @return [Boolean] true if the library should send error reports to
|
129
|
+
# Airbrake, false otherwise
|
130
|
+
# @api public
|
131
|
+
# @since ?.?.?
|
132
|
+
attr_accessor :error_notifications
|
133
|
+
|
134
|
+
# @note Not for public use!
|
135
|
+
# @return [Boolean]
|
136
|
+
# @api private
|
137
|
+
# @since ?.?.?
|
138
|
+
attr_accessor :__remote_configuration
|
139
|
+
|
116
140
|
class << self
|
117
141
|
# @return [Config]
|
118
142
|
attr_writer :instance
|
@@ -134,7 +158,8 @@ module Airbrake
|
|
134
158
|
self.logger = ::Logger.new(File::NULL).tap { |l| l.level = Logger::WARN }
|
135
159
|
self.project_id = user_config[:project_id]
|
136
160
|
self.project_key = user_config[:project_key]
|
137
|
-
self.
|
161
|
+
self.error_host = 'https://api.airbrake.io'
|
162
|
+
self.apm_host = 'https://api.airbrake.io'
|
138
163
|
|
139
164
|
self.ignore_environments = []
|
140
165
|
|
@@ -153,6 +178,8 @@ module Airbrake
|
|
153
178
|
self.performance_stats_flush_period = 15
|
154
179
|
self.query_stats = true
|
155
180
|
self.job_stats = true
|
181
|
+
self.error_notifications = true
|
182
|
+
self.__remote_configuration = false
|
156
183
|
|
157
184
|
merge(user_config)
|
158
185
|
end
|
@@ -176,14 +203,14 @@ module Airbrake
|
|
176
203
|
self.allowlist_keys = keys
|
177
204
|
end
|
178
205
|
|
179
|
-
# The full URL to the Airbrake Notice API. Based on the +:
|
206
|
+
# The full URL to the Airbrake Notice API. Based on the +:error_host+ option.
|
180
207
|
# @return [URI] the endpoint address
|
181
|
-
def
|
182
|
-
@
|
208
|
+
def error_endpoint
|
209
|
+
@error_endpoint ||=
|
183
210
|
begin
|
184
|
-
self.
|
211
|
+
self.error_host = ('https://' << error_host) if error_host !~ %r{\Ahttps?://}
|
185
212
|
api = "api/v3/projects/#{project_id}/notices"
|
186
|
-
URI.join(
|
213
|
+
URI.join(error_host, api)
|
187
214
|
end
|
188
215
|
end
|
189
216
|
|
@@ -261,4 +288,5 @@ module Airbrake
|
|
261
288
|
raise Airbrake::Error, "unknown option '#{option}'"
|
262
289
|
end
|
263
290
|
end
|
291
|
+
# rubocop:enable Metrics/ClassLength
|
264
292
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Airbrake
|
2
|
+
class Config
|
3
|
+
# Processor is a helper class, which is responsible for setting default
|
4
|
+
# config values, default notifier filters and remote configuration changes.
|
5
|
+
#
|
6
|
+
# @since v?.?.?
|
7
|
+
# @api private
|
8
|
+
class Processor
|
9
|
+
# @param [Airbrake::Config] config
|
10
|
+
# @return [Airbrake::Config::Processor]
|
11
|
+
def self.process(config)
|
12
|
+
new(config).process
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [Airbrake::Config] config
|
16
|
+
def initialize(config)
|
17
|
+
@config = config
|
18
|
+
@blocklist_keys = @config.blocklist_keys
|
19
|
+
@allowlist_keys = @config.allowlist_keys
|
20
|
+
@project_id = @config.project_id
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [Airbrake::NoticeNotifier] notifier
|
24
|
+
# @return [void]
|
25
|
+
def process_blocklist(notifier)
|
26
|
+
return if @blocklist_keys.none?
|
27
|
+
|
28
|
+
blocklist = Airbrake::Filters::KeysBlocklist.new(@blocklist_keys)
|
29
|
+
notifier.add_filter(blocklist)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [Airbrake::NoticeNotifier] notifier
|
33
|
+
# @return [void]
|
34
|
+
def process_allowlist(notifier)
|
35
|
+
return if @allowlist_keys.none?
|
36
|
+
|
37
|
+
allowlist = Airbrake::Filters::KeysAllowlist.new(@allowlist_keys)
|
38
|
+
notifier.add_filter(allowlist)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Airbrake::RemoteSettings]
|
42
|
+
def process_remote_configuration
|
43
|
+
return if !@project_id || !@config.__remote_configuration
|
44
|
+
|
45
|
+
RemoteSettings.poll(@project_id, &method(:poll_callback))
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param [Airbrake::NoticeNotifier] notifier
|
49
|
+
# @return [void]
|
50
|
+
def add_filters(notifier)
|
51
|
+
return unless @config.root_directory
|
52
|
+
|
53
|
+
[
|
54
|
+
Airbrake::Filters::RootDirectoryFilter,
|
55
|
+
Airbrake::Filters::GitRevisionFilter,
|
56
|
+
Airbrake::Filters::GitRepositoryFilter,
|
57
|
+
Airbrake::Filters::GitLastCheckoutFilter,
|
58
|
+
].each do |filter|
|
59
|
+
next if notifier.has_filter?(filter)
|
60
|
+
|
61
|
+
notifier.add_filter(filter.new(@config.root_directory))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param [Airbrake::RemoteSettings::SettingsData] data
|
66
|
+
# @return [void]
|
67
|
+
def poll_callback(data)
|
68
|
+
@config.logger.debug(
|
69
|
+
"#{LOG_LABEL} applying remote settings: #{data.to_h}",
|
70
|
+
)
|
71
|
+
|
72
|
+
@config.error_host = data.error_host if data.error_host
|
73
|
+
@config.apm_host = data.apm_host if data.apm_host
|
74
|
+
|
75
|
+
@config.error_notifications = data.error_notifications?
|
76
|
+
@config.performance_stats = data.performance_stats?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -44,6 +44,10 @@ module Airbrake
|
|
44
44
|
def check_notify_ability(config)
|
45
45
|
promise = Airbrake::Promise.new
|
46
46
|
|
47
|
+
unless config.error_notifications
|
48
|
+
return promise.reject('error notifications are disabled')
|
49
|
+
end
|
50
|
+
|
47
51
|
if ignored_environment?(config)
|
48
52
|
return promise.reject(
|
49
53
|
"current environment '#{config.environment}' is ignored",
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# RemoteSettings polls the remote config of the passed project at fixed
|
3
|
+
# intervals. The fetched config is yielded as a callback parameter so that the
|
4
|
+
# invoker can define read config values.
|
5
|
+
#
|
6
|
+
# @example Disable/enable error notifications based on the remote value
|
7
|
+
# RemoteSettings.poll do |data|
|
8
|
+
# config.error_notifications = data.error_notifications?
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# When {#poll} is called, it will try to load remote settings from disk, so
|
12
|
+
# that it doesn't wait on the result from the API call.
|
13
|
+
#
|
14
|
+
# When {#stop_polling} is called, the current config will be dumped to disk.
|
15
|
+
#
|
16
|
+
# @since ?.?.?
|
17
|
+
# @api private
|
18
|
+
class RemoteSettings
|
19
|
+
include Airbrake::Loggable
|
20
|
+
|
21
|
+
# @return [String] the path to the persistent config
|
22
|
+
CONFIG_DUMP_PATH = File.join(
|
23
|
+
File.expand_path(__dir__),
|
24
|
+
'../../config/config.json',
|
25
|
+
).freeze
|
26
|
+
|
27
|
+
# Polls remote config of the given project.
|
28
|
+
#
|
29
|
+
# @param [Integer] project_id
|
30
|
+
# @yield [data]
|
31
|
+
# @yieldparam data [Airbrake::RemoteSettings::SettingsData]
|
32
|
+
# @return [Airbrake::RemoteSettings]
|
33
|
+
def self.poll(project_id, &block)
|
34
|
+
new(project_id, &block).poll
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [Integer] project_id
|
38
|
+
# @yield [data]
|
39
|
+
# @yieldparam data [Airbrake::RemoteSettings::SettingsData]
|
40
|
+
def initialize(project_id, &block)
|
41
|
+
@data = SettingsData.new(project_id, {})
|
42
|
+
@block = block
|
43
|
+
@poll = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# Polls remote config of the given project in background. Loads local config
|
47
|
+
# first (if exists).
|
48
|
+
#
|
49
|
+
# @return [self]
|
50
|
+
def poll
|
51
|
+
@poll ||= Thread.new do
|
52
|
+
begin
|
53
|
+
load_config
|
54
|
+
rescue StandardError => ex
|
55
|
+
logger.error("#{LOG_LABEL} config loading failed: #{ex}")
|
56
|
+
end
|
57
|
+
|
58
|
+
@block.call(@data)
|
59
|
+
|
60
|
+
loop do
|
61
|
+
@block.call(@data.merge!(fetch_config))
|
62
|
+
sleep(@data.interval)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Stops the background poller thread. Dumps current config to disk.
|
70
|
+
#
|
71
|
+
# @return [void]
|
72
|
+
def stop_polling
|
73
|
+
@poll.kill if @poll
|
74
|
+
|
75
|
+
begin
|
76
|
+
dump_config
|
77
|
+
rescue StandardError => ex
|
78
|
+
logger.error("#{LOG_LABEL} config dumping failed: #{ex}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def fetch_config
|
85
|
+
response = nil
|
86
|
+
begin
|
87
|
+
response = Net::HTTP.get(URI(@data.config_route))
|
88
|
+
rescue StandardError => ex
|
89
|
+
logger.error(ex)
|
90
|
+
return {}
|
91
|
+
end
|
92
|
+
|
93
|
+
# AWS S3 API returns XML when request is not valid. In this case we just
|
94
|
+
# print the returned body and exit the method.
|
95
|
+
if response.start_with?('<?xml ')
|
96
|
+
logger.error(response)
|
97
|
+
return {}
|
98
|
+
end
|
99
|
+
|
100
|
+
json = nil
|
101
|
+
begin
|
102
|
+
json = JSON.parse(response)
|
103
|
+
rescue JSON::ParserError => ex
|
104
|
+
logger.error(ex)
|
105
|
+
return {}
|
106
|
+
end
|
107
|
+
|
108
|
+
json
|
109
|
+
end
|
110
|
+
|
111
|
+
def load_config
|
112
|
+
config_dir = File.dirname(CONFIG_DUMP_PATH)
|
113
|
+
Dir.mkdir(config_dir) unless File.directory?(config_dir)
|
114
|
+
|
115
|
+
return unless File.exist?(CONFIG_DUMP_PATH)
|
116
|
+
|
117
|
+
config = File.read(CONFIG_DUMP_PATH)
|
118
|
+
@data.merge!(JSON.parse(config))
|
119
|
+
end
|
120
|
+
|
121
|
+
def dump_config
|
122
|
+
config_dir = File.dirname(CONFIG_DUMP_PATH)
|
123
|
+
Dir.mkdir(config_dir) unless File.directory?(config_dir)
|
124
|
+
|
125
|
+
File.write(CONFIG_DUMP_PATH, JSON.dump(@data.to_h))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Airbrake
|
2
|
+
class RemoteSettings
|
3
|
+
# SettingsData is a container, which wraps JSON payload returned by the
|
4
|
+
# remote settings API. It exposes the payload via convenient methods and
|
5
|
+
# also ensures that in case some data from the payload is missing, a default
|
6
|
+
# value would be returned instead.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # Create the object and pass initial data (empty hash).
|
10
|
+
# settings_data = SettingsData.new({})
|
11
|
+
#
|
12
|
+
# settings_data.interval #=> 600
|
13
|
+
#
|
14
|
+
# @since ?.?.?
|
15
|
+
# @api private
|
16
|
+
class SettingsData
|
17
|
+
# @return [Integer] how frequently we should poll the config API
|
18
|
+
DEFAULT_INTERVAL = 600
|
19
|
+
|
20
|
+
# @return [String] API version of the S3 API to poll
|
21
|
+
API_VER = '2020-06-18'.freeze
|
22
|
+
|
23
|
+
# @return [String] what URL to poll
|
24
|
+
CONFIG_ROUTE_PATTERN =
|
25
|
+
'https://%<bucket>s.s3.amazonaws.com/' \
|
26
|
+
"#{API_VER}/config/%<project_id>s/config.json".freeze
|
27
|
+
|
28
|
+
# @return [Hash{Symbol=>String}] the hash of all supported settings where
|
29
|
+
# the value is the name of the setting returned by the API
|
30
|
+
SETTINGS = {
|
31
|
+
errors: 'errors',
|
32
|
+
apm: 'apm',
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
# @param [Integer] project_id
|
36
|
+
# @param [Hash{String=>Object}] data
|
37
|
+
def initialize(project_id, data)
|
38
|
+
@project_id = project_id
|
39
|
+
@data = data
|
40
|
+
end
|
41
|
+
|
42
|
+
# Merges the given +hash+ with internal data.
|
43
|
+
#
|
44
|
+
# @param [Hash{String=>Object}] hash
|
45
|
+
# @return [self]
|
46
|
+
def merge!(hash)
|
47
|
+
@data.merge!(hash)
|
48
|
+
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Integer] how frequently we should poll for the config
|
53
|
+
def interval
|
54
|
+
return DEFAULT_INTERVAL if !@data.key?('poll_sec') || !@data['poll_sec']
|
55
|
+
|
56
|
+
@data['poll_sec'] > 0 ? @data['poll_sec'] : DEFAULT_INTERVAL
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [String] where the config is stored on S3.
|
60
|
+
def config_route
|
61
|
+
if !@data.key?('config_route') || !@data['config_route']
|
62
|
+
return format(
|
63
|
+
CONFIG_ROUTE_PATTERN,
|
64
|
+
bucket: 'staging-notifier-configs',
|
65
|
+
project_id: @project_id,
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
@data['config_route']
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [Boolean] whether error notifications are enabled
|
73
|
+
def error_notifications?
|
74
|
+
return true unless (s = find_setting(SETTINGS[:errors]))
|
75
|
+
|
76
|
+
s['enabled']
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [Boolean] whether APM is enabled
|
80
|
+
def performance_stats?
|
81
|
+
return true unless (s = find_setting(SETTINGS[:apm]))
|
82
|
+
|
83
|
+
s['enabled']
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [String, nil] the host, which provides the API endpoint to which
|
87
|
+
# exceptions should be sent
|
88
|
+
def error_host
|
89
|
+
return unless (s = find_setting(SETTINGS[:errors]))
|
90
|
+
|
91
|
+
s['endpoint']
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [String, nil] the host, which provides the API endpoint to which
|
95
|
+
# APM data should be sent
|
96
|
+
def apm_host
|
97
|
+
return unless (s = find_setting(SETTINGS[:apm]))
|
98
|
+
|
99
|
+
s['endpoint']
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Hash{String=>Object}] raw representation of JSON payload
|
103
|
+
def to_h
|
104
|
+
@data.dup
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def find_setting(name)
|
110
|
+
return unless @data.key?('settings')
|
111
|
+
|
112
|
+
@data['settings'].find { |s| s['name'] == name }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|