shivam 0.0.0-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 +7 -0
- data/.github/workflows/test.yml +57 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +899 -0
- data/Gemfile +35 -0
- data/Guardfile +14 -0
- data/LICENSE +23 -0
- data/README.md +679 -0
- data/Rakefile +21 -0
- data/bin/ci/before_build.sh +20 -0
- data/bin/ci/before_build_docker.sh +20 -0
- data/bin/ci/install_on_debian.sh +46 -0
- data/bin/hutch +8 -0
- data/examples/consumer.rb +13 -0
- data/examples/producer.rb +10 -0
- data/hutch.gemspec +27 -0
- data/lib/hutch/acknowledgements/base.rb +16 -0
- data/lib/hutch/acknowledgements/nack_on_all_failures.rb +19 -0
- data/lib/hutch/adapter.rb +11 -0
- data/lib/hutch/adapters/bunny.rb +37 -0
- data/lib/hutch/adapters/march_hare.rb +41 -0
- data/lib/hutch/broker.rb +384 -0
- data/lib/hutch/cli.rb +246 -0
- data/lib/hutch/config.rb +305 -0
- data/lib/hutch/consumer.rb +125 -0
- data/lib/hutch/error_handlers/airbrake.rb +54 -0
- data/lib/hutch/error_handlers/base.rb +15 -0
- data/lib/hutch/error_handlers/bugsnag.rb +30 -0
- data/lib/hutch/error_handlers/honeybadger.rb +43 -0
- data/lib/hutch/error_handlers/logger.rb +22 -0
- data/lib/hutch/error_handlers/rollbar.rb +28 -0
- data/lib/hutch/error_handlers/sentry.rb +26 -0
- data/lib/hutch/error_handlers/sentry_raven.rb +31 -0
- data/lib/hutch/error_handlers.rb +11 -0
- data/lib/hutch/exceptions.rb +14 -0
- data/lib/hutch/logging.rb +32 -0
- data/lib/hutch/message.rb +31 -0
- data/lib/hutch/publisher.rb +75 -0
- data/lib/hutch/serializers/identity.rb +19 -0
- data/lib/hutch/serializers/json.rb +22 -0
- data/lib/hutch/tracers/datadog.rb +18 -0
- data/lib/hutch/tracers/newrelic.rb +19 -0
- data/lib/hutch/tracers/null_tracer.rb +15 -0
- data/lib/hutch/tracers.rb +7 -0
- data/lib/hutch/version.rb +3 -0
- data/lib/hutch/waiter.rb +104 -0
- data/lib/hutch/worker.rb +145 -0
- data/lib/hutch.rb +69 -0
- data/lib/yard-settings/handler.rb +38 -0
- data/lib/yard-settings/yard-settings.rb +2 -0
- data/spec/hutch/broker_spec.rb +462 -0
- data/spec/hutch/cli_spec.rb +93 -0
- data/spec/hutch/config_spec.rb +259 -0
- data/spec/hutch/consumer_spec.rb +208 -0
- data/spec/hutch/error_handlers/airbrake_spec.rb +49 -0
- data/spec/hutch/error_handlers/bugsnag_spec.rb +55 -0
- data/spec/hutch/error_handlers/honeybadger_spec.rb +58 -0
- data/spec/hutch/error_handlers/logger_spec.rb +28 -0
- data/spec/hutch/error_handlers/rollbar_spec.rb +45 -0
- data/spec/hutch/error_handlers/sentry_raven_spec.rb +37 -0
- data/spec/hutch/error_handlers/sentry_spec.rb +47 -0
- data/spec/hutch/logger_spec.rb +34 -0
- data/spec/hutch/message_spec.rb +38 -0
- data/spec/hutch/serializers/json_spec.rb +17 -0
- data/spec/hutch/tracers/datadog_spec.rb +44 -0
- data/spec/hutch/waiter_spec.rb +51 -0
- data/spec/hutch/worker_spec.rb +184 -0
- data/spec/hutch_spec.rb +87 -0
- data/spec/spec_helper.rb +42 -0
- data/templates/default/class/html/settings.erb +0 -0
- data/templates/default/class/setup.rb +4 -0
- data/templates/default/fulldoc/html/css/hutch.css +13 -0
- data/templates/default/layout/html/setup.rb +7 -0
- data/templates/default/method_details/html/settings.erb +5 -0
- data/templates/default/method_details/setup.rb +4 -0
- data/templates/default/method_details/text/settings.erb +0 -0
- data/templates/default/module/html/settings.erb +40 -0
- data/templates/default/module/setup.rb +4 -0
- metadata +205 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'airbrake'
|
3
|
+
require 'hutch/error_handlers/base'
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
module ErrorHandlers
|
7
|
+
class Airbrake < Base
|
8
|
+
|
9
|
+
def handle(properties, payload, consumer, ex)
|
10
|
+
message_id = properties.message_id
|
11
|
+
prefix = "message(#{message_id || '-'}):"
|
12
|
+
logger.error "#{prefix} Logging event to Airbrake"
|
13
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
14
|
+
|
15
|
+
if ::Airbrake.respond_to?(:notify_or_ignore)
|
16
|
+
::Airbrake.notify_or_ignore(ex, {
|
17
|
+
error_class: ex.class.name,
|
18
|
+
error_message: "#{ ex.class.name }: #{ ex.message }",
|
19
|
+
backtrace: ex.backtrace,
|
20
|
+
parameters: {
|
21
|
+
payload: payload,
|
22
|
+
consumer: consumer,
|
23
|
+
},
|
24
|
+
cgi_data: ENV.to_hash,
|
25
|
+
})
|
26
|
+
else
|
27
|
+
::Airbrake.notify(ex, {
|
28
|
+
payload: payload,
|
29
|
+
consumer: consumer,
|
30
|
+
cgi_data: ENV.to_hash,
|
31
|
+
})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def handle_setup_exception(ex)
|
36
|
+
logger.error "Logging setup exception to Airbrake"
|
37
|
+
logger.error "#{ex.class} - #{ex.message}"
|
38
|
+
|
39
|
+
if ::Airbrake.respond_to?(:notify_or_ignore)
|
40
|
+
::Airbrake.notify_or_ignore(ex, {
|
41
|
+
error_class: ex.class.name,
|
42
|
+
error_message: "#{ ex.class.name }: #{ ex.message }",
|
43
|
+
backtrace: ex.backtrace,
|
44
|
+
cgi_data: ENV.to_hash,
|
45
|
+
})
|
46
|
+
else
|
47
|
+
::Airbrake.notify(ex, {
|
48
|
+
cgi_data: ENV.to_hash,
|
49
|
+
})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Hutch
|
2
|
+
module ErrorHandlers
|
3
|
+
class Base
|
4
|
+
include Logging
|
5
|
+
|
6
|
+
def handle(properties, payload, consumer, ex)
|
7
|
+
raise NotImplementedError.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def handle_setup_exception(ex)
|
11
|
+
raise NotImplementedError.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "hutch/logging"
|
2
|
+
require "bugsnag"
|
3
|
+
require "hutch/error_handlers/base"
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
module ErrorHandlers
|
7
|
+
class Bugsnag < Base
|
8
|
+
def handle(properties, payload, consumer, ex)
|
9
|
+
message_id = properties.message_id
|
10
|
+
prefix = "message(#{message_id || "-"}):"
|
11
|
+
logger.error "#{prefix} Logging event to Bugsnag"
|
12
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
13
|
+
|
14
|
+
::Bugsnag.notify(ex) do |report|
|
15
|
+
report.add_tab(:hutch, {
|
16
|
+
payload: payload,
|
17
|
+
consumer: consumer
|
18
|
+
})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_setup_exception(ex)
|
23
|
+
logger.error "Logging setup exception to Bugsnag"
|
24
|
+
logger.error "#{ex.class} - #{ex.message}"
|
25
|
+
|
26
|
+
::Bugsnag.notify(ex)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'honeybadger'
|
3
|
+
require 'hutch/error_handlers/base'
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
module ErrorHandlers
|
7
|
+
# Error handler for the Honeybadger.io service
|
8
|
+
class Honeybadger < Base
|
9
|
+
|
10
|
+
def handle(properties, payload, consumer, ex)
|
11
|
+
message_id = properties.message_id
|
12
|
+
prefix = "message(#{message_id || '-'}):"
|
13
|
+
logger.error "#{prefix} Logging event to Honeybadger"
|
14
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
15
|
+
notify_honeybadger(error_class: ex.class.name,
|
16
|
+
error_message: "#{ex.class.name}: #{ex.message}",
|
17
|
+
backtrace: ex.backtrace,
|
18
|
+
context: { message_id: message_id,
|
19
|
+
consumer: consumer },
|
20
|
+
parameters: { payload: payload })
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_setup_exception(ex)
|
24
|
+
logger.error "Logging setup exception to Honeybadger"
|
25
|
+
logger.error "#{ex.class} - #{ex.message}"
|
26
|
+
notify_honeybadger(error_class: ex.class.name,
|
27
|
+
error_message: "#{ex.class.name}: #{ex.message}",
|
28
|
+
backtrace: ex.backtrace)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Wrap API to support 3.0.0+
|
32
|
+
#
|
33
|
+
# @see https://github.com/honeybadger-io/honeybadger-ruby/blob/master/CHANGELOG.md#300---2017-02-06
|
34
|
+
def notify_honeybadger(message)
|
35
|
+
if ::Honeybadger.respond_to?(:notify_or_ignore)
|
36
|
+
::Honeybadger.notify_or_ignore(message)
|
37
|
+
else
|
38
|
+
::Honeybadger.notify(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'hutch/error_handlers/base'
|
3
|
+
|
4
|
+
module Hutch
|
5
|
+
module ErrorHandlers
|
6
|
+
class Logger < ErrorHandlers::Base
|
7
|
+
|
8
|
+
def handle(properties, payload, consumer, ex)
|
9
|
+
message_id = properties.message_id
|
10
|
+
prefix = "message(#{message_id || '-'}):"
|
11
|
+
logger.error "#{prefix} error in consumer '#{consumer}'"
|
12
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
13
|
+
logger.error (['backtrace:'] + ex.backtrace).join("\n")
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_setup_exception(ex)
|
17
|
+
logger.error "#{ex.class} - #{ex.message}"
|
18
|
+
logger.error (['backtrace:'] + ex.backtrace).join("\n")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'rollbar'
|
3
|
+
require 'hutch/error_handlers/base'
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
module ErrorHandlers
|
7
|
+
class Rollbar < Base
|
8
|
+
def handle(properties, payload, consumer, ex)
|
9
|
+
message_id = properties.message_id
|
10
|
+
prefix = "message(#{message_id || '-'}):"
|
11
|
+
logger.error "#{prefix} Logging event to Rollbar"
|
12
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
13
|
+
|
14
|
+
::Rollbar.error(ex,
|
15
|
+
payload: payload,
|
16
|
+
consumer: consumer
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle_setup_exception(ex)
|
21
|
+
logger.error "Logging setup exception to Rollbar"
|
22
|
+
logger.error "#{ex.class} - #{ex.message}"
|
23
|
+
|
24
|
+
::Rollbar.error(ex)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'sentry-ruby'
|
3
|
+
require 'hutch/error_handlers/base'
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
module ErrorHandlers
|
7
|
+
class Sentry < Base
|
8
|
+
def handle(properties, payload, consumer, ex)
|
9
|
+
message_id = properties.message_id
|
10
|
+
prefix = "message(#{message_id || '-'}):"
|
11
|
+
logger.error "#{prefix} Logging event to Sentry"
|
12
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
13
|
+
::Sentry.configure_scope do |scope|
|
14
|
+
scope.set_context("payload", JSON.parse(payload))
|
15
|
+
end
|
16
|
+
::Sentry.capture_exception(ex)
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle_setup_exception(ex)
|
20
|
+
logger.error "Logging setup exception to Sentry"
|
21
|
+
logger.error "#{ex.class} - #{ex.message}"
|
22
|
+
::Sentry.capture_exception(ex)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
require 'raven'
|
3
|
+
require 'hutch/error_handlers/base'
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
module ErrorHandlers
|
7
|
+
class SentryRaven < Base
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
unless Raven.respond_to?(:capture_exception)
|
11
|
+
raise "The Hutch Sentry error handler requires Raven >= 0.4.0"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def handle(properties, payload, consumer, ex)
|
16
|
+
message_id = properties.message_id
|
17
|
+
prefix = "message(#{message_id || '-'}):"
|
18
|
+
logger.error "#{prefix} Logging event to Sentry"
|
19
|
+
logger.error "#{prefix} #{ex.class} - #{ex.message}"
|
20
|
+
Raven.capture_exception(ex, extra: { payload: payload })
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_setup_exception(ex)
|
24
|
+
logger.error "Logging setup exception to Sentry"
|
25
|
+
logger.error "#{ex.class} - #{ex.message}"
|
26
|
+
Raven.capture_exception(ex)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Hutch
|
2
|
+
module ErrorHandlers
|
3
|
+
autoload :Logger, 'hutch/error_handlers/logger'
|
4
|
+
autoload :Sentry, 'hutch/error_handlers/sentry'
|
5
|
+
autoload :SentryRaven, 'hutch/error_handlers/sentry_raven'
|
6
|
+
autoload :Honeybadger, 'hutch/error_handlers/honeybadger'
|
7
|
+
autoload :Airbrake, 'hutch/error_handlers/airbrake'
|
8
|
+
autoload :Rollbar, 'hutch/error_handlers/rollbar'
|
9
|
+
autoload :Bugsnag, 'hutch/error_handlers/bugsnag'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Hutch
|
2
|
+
if defined?(JRUBY_VERSION)
|
3
|
+
require 'march_hare/exceptions'
|
4
|
+
class Exception < MarchHare::Exception; end
|
5
|
+
else
|
6
|
+
require "bunny/exceptions"
|
7
|
+
# Bunny::Exception inherits from StandardError
|
8
|
+
class Exception < Bunny::Exception; end
|
9
|
+
end
|
10
|
+
class ConnectionError < Exception; end
|
11
|
+
class AuthenticationError < Exception; end
|
12
|
+
class WorkerSetupError < Exception; end
|
13
|
+
class PublishError < Exception; end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module Hutch
|
5
|
+
module Logging
|
6
|
+
class HutchFormatter < Logger::Formatter
|
7
|
+
def call(severity, time, program_name, message)
|
8
|
+
"#{time.utc.iso8601} #{Process.pid} #{severity} -- #{message}\n"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.setup_logger
|
13
|
+
require 'hutch/config'
|
14
|
+
@logger = Logger.new($stdout).tap do |l|
|
15
|
+
l.level = Hutch::Config.log_level
|
16
|
+
l.formatter = HutchFormatter.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.logger
|
21
|
+
@logger || setup_logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.logger=(logger)
|
25
|
+
@logger = logger
|
26
|
+
end
|
27
|
+
|
28
|
+
def logger
|
29
|
+
Hutch::Logging.logger
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Hutch
|
4
|
+
class Message
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :delivery_info, :properties, :payload
|
8
|
+
|
9
|
+
def initialize(delivery_info, properties, payload, serializer)
|
10
|
+
@delivery_info = delivery_info
|
11
|
+
@properties = properties
|
12
|
+
@payload = payload
|
13
|
+
@body = serializer.decode(payload)
|
14
|
+
end
|
15
|
+
|
16
|
+
def_delegator :@body, :[]
|
17
|
+
def_delegators :@properties, :message_id, :timestamp
|
18
|
+
def_delegators :@delivery_info, :routing_key, :exchange
|
19
|
+
|
20
|
+
attr_reader :body
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
attrs = { :@body => body.to_s, message_id: message_id,
|
24
|
+
timestamp: timestamp, routing_key: routing_key }
|
25
|
+
"#<Message #{attrs.map { |k,v| "#{k}=#{v.inspect}" }.join(', ')}>"
|
26
|
+
end
|
27
|
+
|
28
|
+
alias_method :inspect, :to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'hutch/logging'
|
3
|
+
require 'hutch/exceptions'
|
4
|
+
|
5
|
+
module Hutch
|
6
|
+
class Publisher
|
7
|
+
include Logging
|
8
|
+
attr_reader :connection, :channel, :exchange, :config
|
9
|
+
|
10
|
+
def initialize(connection, channel, exchange, config = Hutch::Config)
|
11
|
+
@connection = connection
|
12
|
+
@channel = channel
|
13
|
+
@exchange = exchange
|
14
|
+
@config = config
|
15
|
+
end
|
16
|
+
|
17
|
+
def publish(routing_key, message, properties = {}, options = {})
|
18
|
+
ensure_connection!(routing_key, message)
|
19
|
+
|
20
|
+
serializer = options[:serializer] || config[:serializer]
|
21
|
+
|
22
|
+
non_overridable_properties = {
|
23
|
+
routing_key: routing_key,
|
24
|
+
timestamp: connection.current_timestamp,
|
25
|
+
content_type: serializer.content_type,
|
26
|
+
}
|
27
|
+
properties[:message_id] ||= generate_id
|
28
|
+
|
29
|
+
payload = serializer.encode(message)
|
30
|
+
|
31
|
+
log_publication(serializer, payload, routing_key)
|
32
|
+
|
33
|
+
response = exchange.publish(payload, {persistent: true}.
|
34
|
+
merge(properties).
|
35
|
+
merge(global_properties).
|
36
|
+
merge(non_overridable_properties))
|
37
|
+
|
38
|
+
channel.wait_for_confirms if config[:force_publisher_confirms]
|
39
|
+
response
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def log_publication(serializer, payload, routing_key)
|
45
|
+
logger.debug {
|
46
|
+
spec =
|
47
|
+
if serializer.binary?
|
48
|
+
"#{payload.bytesize} bytes message"
|
49
|
+
else
|
50
|
+
"message '#{payload}'"
|
51
|
+
end
|
52
|
+
"publishing #{spec} to #{routing_key}"
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def raise_publish_error(reason, routing_key, message)
|
57
|
+
msg = "unable to publish - #{reason}. Message: #{JSON.dump(message)}, Routing key: #{routing_key}."
|
58
|
+
logger.error(msg)
|
59
|
+
raise PublishError, msg
|
60
|
+
end
|
61
|
+
|
62
|
+
def ensure_connection!(routing_key, message)
|
63
|
+
raise_publish_error('no connection to broker', routing_key, message) unless connection
|
64
|
+
raise_publish_error('connection is closed', routing_key, message) unless connection.open?
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_id
|
68
|
+
SecureRandom.uuid
|
69
|
+
end
|
70
|
+
|
71
|
+
def global_properties
|
72
|
+
Hutch.global_properties.respond_to?(:call) ? Hutch.global_properties.call : Hutch.global_properties
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Hutch
|
2
|
+
module Serializers
|
3
|
+
class Identity
|
4
|
+
|
5
|
+
def self.encode(payload)
|
6
|
+
payload
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.decode(payload)
|
10
|
+
payload
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.binary? ; false ; end
|
14
|
+
|
15
|
+
def self.content_type ; nil ; end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
+
|
4
|
+
module Hutch
|
5
|
+
module Serializers
|
6
|
+
class JSON
|
7
|
+
|
8
|
+
def self.encode(payload)
|
9
|
+
::MultiJson.dump(payload)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode(payload)
|
13
|
+
::MultiJson.load(payload).with_indifferent_access
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.binary? ; false ; end
|
17
|
+
|
18
|
+
def self.content_type ; 'application/json' ; end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'ddtrace'
|
2
|
+
require 'ddtrace/auto_instrument'
|
3
|
+
|
4
|
+
module Hutch
|
5
|
+
module Tracers
|
6
|
+
class Datadog
|
7
|
+
def initialize(klass)
|
8
|
+
@klass = klass
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle(message)
|
12
|
+
::Datadog::Tracing.trace(@klass.class.name, continue_from: nil, service: 'hutch', type: 'rabbitmq') do
|
13
|
+
@klass.process(message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'newrelic_rpm'
|
2
|
+
|
3
|
+
module Hutch
|
4
|
+
module Tracers
|
5
|
+
class NewRelic
|
6
|
+
include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
7
|
+
|
8
|
+
def initialize(klass)
|
9
|
+
@klass = klass
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle(message)
|
13
|
+
@klass.process(message)
|
14
|
+
end
|
15
|
+
|
16
|
+
add_transaction_tracer :handle, :category => 'OtherTransaction/HutchConsumer', :path => '#{@klass.class.name}'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/hutch/waiter.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'hutch/logging'
|
2
|
+
|
3
|
+
module Hutch
|
4
|
+
# Signal-handling class.
|
5
|
+
#
|
6
|
+
# Currently, the signal USR2 performs a thread dump,
|
7
|
+
# while QUIT, TERM and INT all perform a graceful shutdown.
|
8
|
+
class Waiter
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
class ContinueProcessingSignals < RuntimeError
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.supported_signals_of(list)
|
15
|
+
list.keep_if { |s| Signal.list.keys.include?(s) }.tap do |result|
|
16
|
+
result.delete('QUIT') if defined?(JRUBY_VERSION)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
SHUTDOWN_SIGNALS = supported_signals_of(%w(QUIT TERM INT)).freeze
|
21
|
+
# We have chosen a JRuby-supported signal
|
22
|
+
USER_SIGNALS = supported_signals_of(%w(USR2)).freeze
|
23
|
+
REGISTERED_SIGNALS = (SHUTDOWN_SIGNALS + USER_SIGNALS).freeze
|
24
|
+
|
25
|
+
def self.wait_until_signaled
|
26
|
+
new.wait_until_signaled
|
27
|
+
end
|
28
|
+
|
29
|
+
def wait_until_signaled
|
30
|
+
self.sig_read, self.sig_write = IO.pipe
|
31
|
+
|
32
|
+
register_signal_handlers
|
33
|
+
|
34
|
+
begin
|
35
|
+
wait_for_signal
|
36
|
+
|
37
|
+
sig = sig_read.gets.strip
|
38
|
+
handle_signal(sig)
|
39
|
+
rescue ContinueProcessingSignals
|
40
|
+
retry
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def handle_signal(sig)
|
45
|
+
raise ContinueProcessingSignals unless REGISTERED_SIGNALS.include?(sig)
|
46
|
+
if user_signal?(sig)
|
47
|
+
handle_user_signal(sig)
|
48
|
+
else
|
49
|
+
handle_shutdown_signal(sig)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @raise ContinueProcessingSignals
|
54
|
+
def handle_user_signal(sig)
|
55
|
+
case sig
|
56
|
+
when 'USR2' then log_thread_backtraces
|
57
|
+
else raise "Assertion failed - unhandled signal: #{sig.inspect}"
|
58
|
+
end
|
59
|
+
raise ContinueProcessingSignals
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_shutdown_signal(sig)
|
63
|
+
logger.info "caught SIG#{sig}, stopping hutch..."
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def log_thread_backtraces
|
69
|
+
logger.info 'Requested a VM-wide thread stack trace dump...'
|
70
|
+
Thread.list.each do |thread|
|
71
|
+
logger.info "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
72
|
+
logger.info backtrace_for(thread)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def backtrace_for(thread)
|
77
|
+
if thread.backtrace
|
78
|
+
thread.backtrace.join("\n")
|
79
|
+
else
|
80
|
+
'<no backtrace available>'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
attr_accessor :sig_read, :sig_write
|
85
|
+
|
86
|
+
def wait_for_signal
|
87
|
+
IO.select([sig_read])
|
88
|
+
end
|
89
|
+
|
90
|
+
def register_signal_handlers
|
91
|
+
REGISTERED_SIGNALS.each do |sig|
|
92
|
+
# This needs to be reentrant, so we queue up signals to be handled
|
93
|
+
# in the run loop, rather than acting on signals here
|
94
|
+
trap(sig) do
|
95
|
+
sig_write.puts(sig)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def user_signal?(sig)
|
101
|
+
USER_SIGNALS.include?(sig)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|