apisonator 2.100.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.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +317 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.base +65 -0
  5. data/Gemfile.lock +319 -0
  6. data/Gemfile.on_prem +1 -0
  7. data/Gemfile.on_prem.lock +297 -0
  8. data/LICENSE +202 -0
  9. data/NOTICE +15 -0
  10. data/README.md +230 -0
  11. data/Rakefile +287 -0
  12. data/apisonator.gemspec +47 -0
  13. data/app/api/api.rb +13 -0
  14. data/app/api/internal/alert_limits.rb +32 -0
  15. data/app/api/internal/application_keys.rb +49 -0
  16. data/app/api/internal/application_referrer_filters.rb +43 -0
  17. data/app/api/internal/applications.rb +77 -0
  18. data/app/api/internal/errors.rb +54 -0
  19. data/app/api/internal/events.rb +42 -0
  20. data/app/api/internal/internal.rb +104 -0
  21. data/app/api/internal/metrics.rb +40 -0
  22. data/app/api/internal/service_tokens.rb +46 -0
  23. data/app/api/internal/services.rb +58 -0
  24. data/app/api/internal/stats.rb +42 -0
  25. data/app/api/internal/usagelimits.rb +62 -0
  26. data/app/api/internal/utilization.rb +23 -0
  27. data/bin/3scale_backend +223 -0
  28. data/bin/3scale_backend_worker +26 -0
  29. data/config.ru +4 -0
  30. data/config/puma.rb +192 -0
  31. data/config/schedule.rb +9 -0
  32. data/ext/mkrf_conf.rb +64 -0
  33. data/lib/3scale/backend.rb +67 -0
  34. data/lib/3scale/backend/alert_limit.rb +56 -0
  35. data/lib/3scale/backend/alerts.rb +137 -0
  36. data/lib/3scale/backend/analytics/kinesis.rb +3 -0
  37. data/lib/3scale/backend/analytics/kinesis/adapter.rb +180 -0
  38. data/lib/3scale/backend/analytics/kinesis/exporter.rb +86 -0
  39. data/lib/3scale/backend/analytics/kinesis/job.rb +135 -0
  40. data/lib/3scale/backend/analytics/redshift.rb +3 -0
  41. data/lib/3scale/backend/analytics/redshift/adapter.rb +367 -0
  42. data/lib/3scale/backend/analytics/redshift/importer.rb +83 -0
  43. data/lib/3scale/backend/analytics/redshift/job.rb +33 -0
  44. data/lib/3scale/backend/application.rb +330 -0
  45. data/lib/3scale/backend/application_events.rb +76 -0
  46. data/lib/3scale/backend/background_job.rb +65 -0
  47. data/lib/3scale/backend/configurable.rb +20 -0
  48. data/lib/3scale/backend/configuration.rb +151 -0
  49. data/lib/3scale/backend/configuration/loader.rb +42 -0
  50. data/lib/3scale/backend/constants.rb +19 -0
  51. data/lib/3scale/backend/cors.rb +84 -0
  52. data/lib/3scale/backend/distributed_lock.rb +67 -0
  53. data/lib/3scale/backend/environment.rb +21 -0
  54. data/lib/3scale/backend/error_storage.rb +52 -0
  55. data/lib/3scale/backend/errors.rb +343 -0
  56. data/lib/3scale/backend/event_storage.rb +120 -0
  57. data/lib/3scale/backend/experiment.rb +84 -0
  58. data/lib/3scale/backend/extensions.rb +5 -0
  59. data/lib/3scale/backend/extensions/array.rb +19 -0
  60. data/lib/3scale/backend/extensions/hash.rb +26 -0
  61. data/lib/3scale/backend/extensions/nil_class.rb +13 -0
  62. data/lib/3scale/backend/extensions/redis.rb +44 -0
  63. data/lib/3scale/backend/extensions/string.rb +13 -0
  64. data/lib/3scale/backend/extensions/time.rb +110 -0
  65. data/lib/3scale/backend/failed_jobs_scheduler.rb +141 -0
  66. data/lib/3scale/backend/job_fetcher.rb +122 -0
  67. data/lib/3scale/backend/listener.rb +728 -0
  68. data/lib/3scale/backend/listener_metrics.rb +99 -0
  69. data/lib/3scale/backend/logging.rb +48 -0
  70. data/lib/3scale/backend/logging/external.rb +44 -0
  71. data/lib/3scale/backend/logging/external/impl.rb +93 -0
  72. data/lib/3scale/backend/logging/external/impl/airbrake.rb +66 -0
  73. data/lib/3scale/backend/logging/external/impl/bugsnag.rb +69 -0
  74. data/lib/3scale/backend/logging/external/impl/default.rb +18 -0
  75. data/lib/3scale/backend/logging/external/resque.rb +57 -0
  76. data/lib/3scale/backend/logging/logger.rb +18 -0
  77. data/lib/3scale/backend/logging/middleware.rb +62 -0
  78. data/lib/3scale/backend/logging/middleware/json_writer.rb +21 -0
  79. data/lib/3scale/backend/logging/middleware/text_writer.rb +60 -0
  80. data/lib/3scale/backend/logging/middleware/writer.rb +143 -0
  81. data/lib/3scale/backend/logging/worker.rb +107 -0
  82. data/lib/3scale/backend/manifest.rb +80 -0
  83. data/lib/3scale/backend/memoizer.rb +277 -0
  84. data/lib/3scale/backend/metric.rb +275 -0
  85. data/lib/3scale/backend/metric/collection.rb +91 -0
  86. data/lib/3scale/backend/oauth.rb +4 -0
  87. data/lib/3scale/backend/oauth/token.rb +26 -0
  88. data/lib/3scale/backend/oauth/token_key.rb +30 -0
  89. data/lib/3scale/backend/oauth/token_storage.rb +313 -0
  90. data/lib/3scale/backend/oauth/token_value.rb +25 -0
  91. data/lib/3scale/backend/period.rb +3 -0
  92. data/lib/3scale/backend/period/boundary.rb +107 -0
  93. data/lib/3scale/backend/period/cache.rb +28 -0
  94. data/lib/3scale/backend/period/period.rb +402 -0
  95. data/lib/3scale/backend/queue_storage.rb +16 -0
  96. data/lib/3scale/backend/rack.rb +49 -0
  97. data/lib/3scale/backend/rack/exception_catcher.rb +136 -0
  98. data/lib/3scale/backend/rack/internal_error_catcher.rb +23 -0
  99. data/lib/3scale/backend/rack/prometheus.rb +19 -0
  100. data/lib/3scale/backend/saas.rb +6 -0
  101. data/lib/3scale/backend/saas_analytics.rb +4 -0
  102. data/lib/3scale/backend/server.rb +30 -0
  103. data/lib/3scale/backend/server/falcon.rb +52 -0
  104. data/lib/3scale/backend/server/puma.rb +71 -0
  105. data/lib/3scale/backend/service.rb +317 -0
  106. data/lib/3scale/backend/service_token.rb +97 -0
  107. data/lib/3scale/backend/stats.rb +8 -0
  108. data/lib/3scale/backend/stats/aggregator.rb +170 -0
  109. data/lib/3scale/backend/stats/aggregators/base.rb +72 -0
  110. data/lib/3scale/backend/stats/aggregators/response_code.rb +58 -0
  111. data/lib/3scale/backend/stats/aggregators/usage.rb +34 -0
  112. data/lib/3scale/backend/stats/bucket_reader.rb +135 -0
  113. data/lib/3scale/backend/stats/bucket_storage.rb +108 -0
  114. data/lib/3scale/backend/stats/cleaner.rb +195 -0
  115. data/lib/3scale/backend/stats/codes_commons.rb +14 -0
  116. data/lib/3scale/backend/stats/delete_job_def.rb +60 -0
  117. data/lib/3scale/backend/stats/key_generator.rb +73 -0
  118. data/lib/3scale/backend/stats/keys.rb +104 -0
  119. data/lib/3scale/backend/stats/partition_eraser_job.rb +58 -0
  120. data/lib/3scale/backend/stats/partition_generator_job.rb +46 -0
  121. data/lib/3scale/backend/stats/period_commons.rb +34 -0
  122. data/lib/3scale/backend/stats/stats_parser.rb +141 -0
  123. data/lib/3scale/backend/stats/storage.rb +113 -0
  124. data/lib/3scale/backend/statsd.rb +14 -0
  125. data/lib/3scale/backend/storable.rb +35 -0
  126. data/lib/3scale/backend/storage.rb +40 -0
  127. data/lib/3scale/backend/storage_async.rb +4 -0
  128. data/lib/3scale/backend/storage_async/async_redis.rb +21 -0
  129. data/lib/3scale/backend/storage_async/client.rb +205 -0
  130. data/lib/3scale/backend/storage_async/pipeline.rb +79 -0
  131. data/lib/3scale/backend/storage_async/resque_extensions.rb +30 -0
  132. data/lib/3scale/backend/storage_helpers.rb +278 -0
  133. data/lib/3scale/backend/storage_key_helpers.rb +9 -0
  134. data/lib/3scale/backend/storage_sync.rb +43 -0
  135. data/lib/3scale/backend/transaction.rb +62 -0
  136. data/lib/3scale/backend/transactor.rb +177 -0
  137. data/lib/3scale/backend/transactor/limit_headers.rb +54 -0
  138. data/lib/3scale/backend/transactor/notify_batcher.rb +139 -0
  139. data/lib/3scale/backend/transactor/notify_job.rb +47 -0
  140. data/lib/3scale/backend/transactor/process_job.rb +33 -0
  141. data/lib/3scale/backend/transactor/report_job.rb +84 -0
  142. data/lib/3scale/backend/transactor/status.rb +236 -0
  143. data/lib/3scale/backend/transactor/usage_report.rb +182 -0
  144. data/lib/3scale/backend/usage.rb +63 -0
  145. data/lib/3scale/backend/usage_limit.rb +115 -0
  146. data/lib/3scale/backend/use_cases/provider_key_change_use_case.rb +60 -0
  147. data/lib/3scale/backend/util.rb +17 -0
  148. data/lib/3scale/backend/validators.rb +26 -0
  149. data/lib/3scale/backend/validators/base.rb +36 -0
  150. data/lib/3scale/backend/validators/key.rb +17 -0
  151. data/lib/3scale/backend/validators/limits.rb +57 -0
  152. data/lib/3scale/backend/validators/oauth_key.rb +15 -0
  153. data/lib/3scale/backend/validators/oauth_setting.rb +15 -0
  154. data/lib/3scale/backend/validators/redirect_uri.rb +33 -0
  155. data/lib/3scale/backend/validators/referrer.rb +60 -0
  156. data/lib/3scale/backend/validators/service_state.rb +15 -0
  157. data/lib/3scale/backend/validators/state.rb +15 -0
  158. data/lib/3scale/backend/version.rb +5 -0
  159. data/lib/3scale/backend/views/oauth_access_tokens.builder +14 -0
  160. data/lib/3scale/backend/views/oauth_app_id_by_token.builder +4 -0
  161. data/lib/3scale/backend/worker.rb +87 -0
  162. data/lib/3scale/backend/worker_async.rb +88 -0
  163. data/lib/3scale/backend/worker_metrics.rb +44 -0
  164. data/lib/3scale/backend/worker_sync.rb +32 -0
  165. data/lib/3scale/bundler_shim.rb +17 -0
  166. data/lib/3scale/prometheus_server.rb +10 -0
  167. data/lib/3scale/tasks/connectivity.rake +41 -0
  168. data/lib/3scale/tasks/helpers.rb +3 -0
  169. data/lib/3scale/tasks/helpers/environment.rb +23 -0
  170. data/lib/3scale/tasks/stats.rake +131 -0
  171. data/lib/3scale/tasks/swagger.rake +46 -0
  172. data/licenses.xml +1215 -0
  173. metadata +227 -0
@@ -0,0 +1,99 @@
1
+ require 'yabeda/prometheus'
2
+ require 'rack'
3
+
4
+ module ThreeScale
5
+ module Backend
6
+ class ListenerMetrics
7
+ REQUEST_TYPES = {
8
+ '/transactions/authorize.xml' => 'authorize',
9
+ '/transactions/oauth_authorize.xml' => 'authorize_oauth',
10
+ '/transactions/authrep.xml' => 'authrep',
11
+ '/transactions/oauth_authrep.xml' => 'authrep_oauth',
12
+ '/transactions.xml' => 'report'
13
+ }
14
+ private_constant :REQUEST_TYPES
15
+
16
+ class << self
17
+ ERRORS_4XX_TO_TRACK = Set[403, 404, 409].freeze
18
+ private_constant :ERRORS_4XX_TO_TRACK
19
+
20
+ def start_metrics_server(port = nil)
21
+ configure_data_store
22
+ define_metrics
23
+
24
+ # Yabeda does not accept the port as a param
25
+ ENV['PROMETHEUS_EXPORTER_PORT'] = port.to_s if port
26
+ Yabeda::Prometheus::Exporter.start_metrics_server!
27
+ end
28
+
29
+ def report_resp_code(path, resp_code)
30
+ Yabeda.apisonator_listener.response_codes.increment(
31
+ {
32
+ request_type: REQUEST_TYPES[path],
33
+ resp_code: code_group(resp_code)
34
+ },
35
+ by: 1
36
+ )
37
+ end
38
+
39
+ def report_response_time(path, request_time)
40
+ Yabeda.apisonator_listener.response_times.measure(
41
+ { request_type: REQUEST_TYPES[path] },
42
+ request_time
43
+ )
44
+ end
45
+
46
+ private
47
+
48
+ def configure_data_store
49
+ # Needed to aggregate metrics across processes.
50
+ # Ref: https://github.com/yabeda-rb/yabeda-prometheus#multi-process-server-support
51
+ Dir['/tmp/prometheus/*.bin'].each do |file_path|
52
+ File.unlink(file_path)
53
+ end
54
+
55
+ Prometheus::Client.config.data_store = Prometheus::Client::DataStores::DirectFileStore.new(
56
+ dir: '/tmp/prometheus'
57
+ )
58
+ end
59
+
60
+ def define_metrics
61
+ Yabeda.configure do
62
+ group :apisonator_listener do
63
+ counter :response_codes do
64
+ comment 'Response codes'
65
+ tags %i[request_type resp_code]
66
+ end
67
+
68
+ histogram :response_times do
69
+ comment 'Response times'
70
+ unit :seconds
71
+ tags %i[request_type]
72
+ # Most requests will be under 100ms, so use a higher granularity from there
73
+ buckets [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.25, 0.5, 0.75, 1]
74
+ end
75
+ end
76
+ end
77
+
78
+ # Note that this method raises if called more than once. Both
79
+ # listeners and workers define their metrics, but that's fine because
80
+ # a process cannot act as both.
81
+ Yabeda.configure!
82
+ end
83
+
84
+ def code_group(resp_code)
85
+ case resp_code
86
+ when (200...300)
87
+ '2xx'.freeze
88
+ when (400...500)
89
+ ERRORS_4XX_TO_TRACK.include?(resp_code) ? resp_code : '4xx'.freeze
90
+ when (500...600)
91
+ '5xx'.freeze
92
+ else
93
+ 'unknown'.freeze
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,48 @@
1
+ require '3scale/backend/environment'
2
+ require '3scale/backend/configuration'
3
+ require '3scale/backend/logging/logger'
4
+ require '3scale/backend/logging/external'
5
+
6
+ module ThreeScale
7
+ module Backend
8
+ # include this module to have a handy access to the default logger
9
+ module Logging
10
+ def self.included(base)
11
+ enable! on: base
12
+ end
13
+
14
+ def self.enable!(on:, with: [], as: :logger)
15
+ logger = if with.empty?
16
+ Backend.logger
17
+ else
18
+ Backend::Logging::Logger.new(*with)
19
+ end
20
+
21
+ # define the method before yielding
22
+ on.send :define_method, as do
23
+ logger
24
+ end
25
+
26
+ yield logger if block_given?
27
+ end
28
+ end
29
+
30
+ class << self
31
+
32
+ private
33
+
34
+ def enable_logging
35
+ Logging.enable! on: self.singleton_class,
36
+ with: [configuration.log_file, 10] do |logger|
37
+ logger.define_singleton_method(:notify, logger_notify_proc(logger))
38
+ end
39
+ end
40
+
41
+ def logger_notify_proc(logger)
42
+ Logging::External.notify_proc || logger.method(:error).to_proc
43
+ end
44
+ end
45
+
46
+ enable_logging
47
+ end
48
+ end
@@ -0,0 +1,44 @@
1
+ require '3scale/backend/configuration'
2
+ require '3scale/backend/logging/external/impl'
3
+
4
+ module ThreeScale
5
+ module Backend
6
+ module Logging
7
+ module External
8
+ class << self
9
+ private
10
+
11
+ attr_accessor :impl, :enabled
12
+ alias_method :enabled?, :enabled
13
+ public :enabled?
14
+
15
+ public
16
+
17
+ def setup
18
+ config = Backend.configuration.hoptoad
19
+
20
+ service = if config.service && !config.service.empty?
21
+ config.service.to_sym
22
+ else
23
+ :default
24
+ end
25
+ self.impl = Impl.load service
26
+ self.enabled = impl.setup(config.api_key)
27
+ end
28
+
29
+ def reset
30
+ self.enabled = false
31
+ end
32
+
33
+ # delegate methods not overriden to the impl
34
+ (Impl::METHODS - public_instance_methods(false)).each do |m|
35
+ define_method(m) do |*args|
36
+ setup unless enabled?
37
+ impl.public_send m, *args
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,93 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module Logging
4
+ module External
5
+ # This is the module that each implementation has to populate with its
6
+ # own class. The implementation file must be named after the class and
7
+ # live in a specific subdirectory relative to this file matching this
8
+ # file's name.
9
+ #
10
+ # To load the class one must specify a symbol with the base name without
11
+ # extension as the file that implements it. The class name is expected
12
+ # to be the capitalized symbol.
13
+ module Impl
14
+ # methods to be implemented by each external logging service
15
+ #
16
+ # setup - Meant to configure the service for a general use. Each other
17
+ # method in the list calls setup if it has not been called
18
+ # before.
19
+ # setup_rake - Perform additional configuration for Rake
20
+ # setup_rack - Receives the Rack object, meant to add a middleware.
21
+ # setup_worker - Additional configuration for job worker usage.
22
+ # notify_proc - The global logger's notify method will call the proc
23
+ # returned by this. If nil is returned a fallback will
24
+ # be chosen for that method (typically local logging).
25
+ #
26
+ METHODS = [:setup, :setup_rake, :setup_rack,
27
+ :setup_worker, :notify_proc].freeze
28
+
29
+ class Error < StandardError
30
+ class FileNotFound < self
31
+ def initialize(impl)
32
+ super "external logging implementation not found for #{impl.inspect}"
33
+ end
34
+ end
35
+
36
+ class ClassNotFound < self
37
+ def initialize(impl)
38
+ super "external logging implementation does not provide a " \
39
+ "similarly named class: #{impl.inspect}"
40
+ end
41
+ end
42
+ end
43
+
44
+ class << self
45
+ # returns the class implementing the logging service
46
+ def load(impl)
47
+ require(find_file impl)
48
+
49
+ fetch_impl_klass impl
50
+ end
51
+
52
+ private
53
+
54
+ def find_file(impl)
55
+ re = build_regexp impl
56
+
57
+ impl_file = Dir[glob].find do |path|
58
+ re.match(File.basename path)
59
+ end
60
+
61
+ impl_file || raise(Error::FileNotFound.new(impl))
62
+ end
63
+
64
+ def fetch_impl_klass(impl)
65
+ const_get(impl.capitalize)
66
+ rescue NameError
67
+ raise Error::ClassNotFound.new(impl)
68
+ end
69
+
70
+ def build_regexp(impl)
71
+ Regexp.new("\\A#{Regexp.escape(impl.to_s + extname)}\\z")
72
+ end
73
+
74
+ # these are almost constants, but since this is meant to be init
75
+ # code with throw-away strings they are left here as helper methods
76
+ def glob
77
+ directory << File::SEPARATOR << '*' << File.extname(__FILE__)
78
+ end
79
+
80
+ def directory
81
+ __FILE__.chomp(extname) + File::SEPARATOR
82
+ end
83
+
84
+ def extname
85
+ # assume implementations will be coded in our own language
86
+ File.extname __FILE__
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,66 @@
1
+ require '3scale/backend/environment'
2
+ require '3scale/backend/configuration'
3
+
4
+ module ThreeScale
5
+ module Backend
6
+ module Logging
7
+ module External
8
+ module Impl
9
+ module Airbrake
10
+ class << self
11
+ def setup(api_key)
12
+ do_require
13
+
14
+ configure api_key
15
+ end
16
+
17
+ def setup_rack(rack)
18
+ rack.use middleware
19
+ end
20
+
21
+ def setup_rake
22
+ require 'airbrake/tasks'
23
+ require 'airbrake/rake_handler'
24
+
25
+ ::Airbrake.configure do |config|
26
+ config.rescue_rake_exceptions = true
27
+ end
28
+ end
29
+
30
+ def setup_worker
31
+ require '3scale/backend/logging/external/resque'
32
+
33
+ External::Resque.setup klass
34
+ end
35
+
36
+ def notify_proc
37
+ klass.method(:notify).to_proc
38
+ end
39
+
40
+ private
41
+
42
+ def do_require
43
+ require 'airbrake'
44
+ end
45
+
46
+ def klass
47
+ ::Airbrake
48
+ end
49
+
50
+ def middleware
51
+ ::Airbrake::Sinatra
52
+ end
53
+
54
+ def configure(api_key)
55
+ ::Airbrake.configure do |config|
56
+ config.api_key = api_key
57
+ config.environment_name = Backend.environment
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,69 @@
1
+ require '3scale/backend/version'
2
+ require '3scale/backend/environment'
3
+ require '3scale/backend/util'
4
+ require '3scale/backend/logging'
5
+
6
+ module ThreeScale
7
+ module Backend
8
+ module Logging
9
+ module External
10
+ module Impl
11
+ module Bugsnag
12
+ class << self
13
+ def setup(api_key)
14
+ do_require
15
+
16
+ configure api_key
17
+ end
18
+
19
+ def setup_rack(rack)
20
+ rack.use middleware
21
+ end
22
+
23
+ def setup_rake
24
+ # no-op
25
+ end
26
+
27
+ def setup_worker
28
+ require '3scale/backend/logging/external/resque'
29
+
30
+ External::Resque.setup klass
31
+ end
32
+
33
+ def notify_proc
34
+ klass.method(:notify).to_proc
35
+ end
36
+
37
+ private
38
+
39
+ def do_require
40
+ require 'bugsnag'
41
+ end
42
+
43
+ def klass
44
+ ::Bugsnag
45
+ end
46
+
47
+ def middleware
48
+ ::Bugsnag::Rack
49
+ end
50
+
51
+ def configure(api_key)
52
+ ::Bugsnag.configure do |config|
53
+ config.api_key = api_key
54
+ config.release_stage = Backend.environment
55
+ config.app_version = Backend::VERSION
56
+ config.timeout = 3
57
+ config.logger = Backend.logger
58
+ config.meta_data_filters = []
59
+ config.notify_release_stages = ['production', 'preview']
60
+ config.project_root = Backend::Util.root_dir
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module Logging
4
+ module External
5
+ module Impl
6
+ # the default implementation does nothing
7
+ class Default
8
+ class << self
9
+ (Impl::METHODS - public_instance_methods(false)).each do |m|
10
+ define_method(m) { |*| }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,57 @@
1
+ # This is a module to configure an external error logging service for Resque.
2
+ #
3
+ # The requirement is that an object be passed in that implements the same
4
+ # interface as Airbrake.
5
+ #
6
+ # This requires a Resque version with https://github.com/resque/resque/pull/1602
7
+ #
8
+ module ThreeScale
9
+ module Backend
10
+ module Logging
11
+ module External
12
+ module Resque
13
+ class << self
14
+ def setup(klass)
15
+ load_resque_failure_for klass
16
+
17
+ ::Resque::Failure::Multiple.classes = [
18
+ ::Resque::Failure::Redis,
19
+ Class.new(::Resque::Failure::Airbrake) do
20
+ def self.configure(&block)
21
+ # calling this hook is an error
22
+ raise "error: tried to configure #{self.inspect} from Resque"
23
+ end
24
+ end,
25
+ ]
26
+ ::Resque::Failure.backend = ::Resque::Failure::Multiple
27
+ end
28
+
29
+ private
30
+
31
+ # set the argument as ::Airbrake and load Resque::Failure
32
+ def load_resque_failure_for(klass)
33
+ require 'resque/failure/base'
34
+ require 'resque/failure/multiple'
35
+ require 'resque/failure/redis'
36
+
37
+ # ensure we have a matching ::Airbrake top-level constant or
38
+ # define it if missing
39
+ begin
40
+ airbrake = ::Kernel.const_get(:Airbrake)
41
+ rescue NameError
42
+ # not defined, so set our own
43
+ ::Kernel.const_set(:Airbrake, klass)
44
+ else
45
+ # defined, expect it's our own object
46
+ raise "Airbrake constant pre-defined as #{airbrake.inspect}, " \
47
+ " required to be #{klass.inspect}!" if airbrake != klass
48
+ end
49
+
50
+ require 'resque/failure/airbrake'
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end