hutch-java 1.3.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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 +383 -0
- data/lib/hutch/cli.rb +246 -0
- data/lib/hutch/config.rb +304 -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 +204 -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
|