sqreen 1.19.3-java → 1.21.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.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +38 -0
  3. data/lib/sqreen/actions/block_user.rb +1 -1
  4. data/lib/sqreen/actions/redirect_ip.rb +1 -1
  5. data/lib/sqreen/actions/redirect_user.rb +1 -1
  6. data/lib/sqreen/agent_message.rb +20 -0
  7. data/lib/sqreen/aggregated_metric.rb +25 -0
  8. data/lib/sqreen/attack_detected.html +1 -2
  9. data/lib/sqreen/ca.crt +24 -0
  10. data/lib/sqreen/condition_evaluator.rb +8 -2
  11. data/lib/sqreen/configuration.rb +11 -5
  12. data/lib/sqreen/deferred_logger.rb +50 -14
  13. data/lib/sqreen/deliveries/batch.rb +12 -2
  14. data/lib/sqreen/deliveries/simple.rb +4 -0
  15. data/lib/sqreen/deprecation.rb +38 -0
  16. data/lib/sqreen/ecosystem.rb +123 -0
  17. data/lib/sqreen/ecosystem/databases/database_connection_data.rb +23 -0
  18. data/lib/sqreen/ecosystem/databases/mongo.rb +39 -0
  19. data/lib/sqreen/ecosystem/databases/mysql.rb +54 -0
  20. data/lib/sqreen/ecosystem/databases/postgres.rb +51 -0
  21. data/lib/sqreen/ecosystem/databases/redis.rb +36 -0
  22. data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
  23. data/lib/sqreen/ecosystem/exception_reporting.rb +28 -0
  24. data/lib/sqreen/ecosystem/http/net_http.rb +50 -0
  25. data/lib/sqreen/ecosystem/http/rack_request.rb +39 -0
  26. data/lib/sqreen/ecosystem/loggable.rb +13 -0
  27. data/lib/sqreen/ecosystem/messaging/bunny.rb +61 -0
  28. data/lib/sqreen/ecosystem/messaging/kafka.rb +70 -0
  29. data/lib/sqreen/ecosystem/messaging/kinesis.rb +66 -0
  30. data/lib/sqreen/ecosystem/messaging/sqs.rb +68 -0
  31. data/lib/sqreen/ecosystem/module_api.rb +30 -0
  32. data/lib/sqreen/ecosystem/module_api/event_listener.rb +18 -0
  33. data/lib/sqreen/ecosystem/module_api/instrumentation.rb +23 -0
  34. data/lib/sqreen/ecosystem/module_api/message_producer.rb +57 -0
  35. data/lib/sqreen/ecosystem/module_api/signal_producer.rb +24 -0
  36. data/lib/sqreen/ecosystem/module_api/tracing.rb +45 -0
  37. data/lib/sqreen/ecosystem/module_api/tracing/client_data.rb +31 -0
  38. data/lib/sqreen/ecosystem/module_api/tracing/consumer_data.rb +13 -0
  39. data/lib/sqreen/ecosystem/module_api/tracing/messaging_data.rb +35 -0
  40. data/lib/sqreen/ecosystem/module_api/tracing/producer_data.rb +13 -0
  41. data/lib/sqreen/ecosystem/module_api/tracing/server_data.rb +27 -0
  42. data/lib/sqreen/ecosystem/module_api/tracing_id_generation.rb +16 -0
  43. data/lib/sqreen/ecosystem/module_api/transaction_storage.rb +71 -0
  44. data/lib/sqreen/ecosystem/module_registry.rb +48 -0
  45. data/lib/sqreen/ecosystem/tracing/modules/client.rb +35 -0
  46. data/lib/sqreen/ecosystem/tracing/modules/consumer.rb +35 -0
  47. data/lib/sqreen/ecosystem/tracing/modules/determine_ip.rb +28 -0
  48. data/lib/sqreen/ecosystem/tracing/modules/producer.rb +35 -0
  49. data/lib/sqreen/ecosystem/tracing/modules/server.rb +30 -0
  50. data/lib/sqreen/ecosystem/tracing/sampler.rb +160 -0
  51. data/lib/sqreen/ecosystem/tracing/sampling_configuration.rb +150 -0
  52. data/lib/sqreen/ecosystem/tracing/signals/tracing_client.rb +53 -0
  53. data/lib/sqreen/ecosystem/tracing/signals/tracing_consumer.rb +56 -0
  54. data/lib/sqreen/ecosystem/tracing/signals/tracing_producer.rb +56 -0
  55. data/lib/sqreen/ecosystem/tracing/signals/tracing_server.rb +53 -0
  56. data/lib/sqreen/ecosystem/tracing_broker.rb +101 -0
  57. data/lib/sqreen/ecosystem/tracing_id_setup.rb +34 -0
  58. data/lib/sqreen/ecosystem/transaction_storage.rb +64 -0
  59. data/lib/sqreen/ecosystem/util/call_writers_from_init.rb +13 -0
  60. data/lib/sqreen/ecosystem_integration.rb +81 -0
  61. data/lib/sqreen/ecosystem_integration/around_callbacks.rb +89 -0
  62. data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +38 -0
  63. data/lib/sqreen/ecosystem_integration/request_lifecycle_tracking.rb +58 -0
  64. data/lib/sqreen/ecosystem_integration/signal_consumption.rb +35 -0
  65. data/lib/sqreen/endpoint_testing.rb +184 -0
  66. data/lib/sqreen/event.rb +7 -5
  67. data/lib/sqreen/events/attack.rb +23 -18
  68. data/lib/sqreen/events/remote_exception.rb +0 -22
  69. data/lib/sqreen/events/request_record.rb +15 -71
  70. data/lib/sqreen/frameworks/generic.rb +24 -1
  71. data/lib/sqreen/frameworks/rails.rb +0 -7
  72. data/lib/sqreen/frameworks/request_recorder.rb +15 -2
  73. data/lib/sqreen/graft/call.rb +85 -18
  74. data/lib/sqreen/graft/callback.rb +1 -1
  75. data/lib/sqreen/graft/hook.rb +192 -88
  76. data/lib/sqreen/graft/hook_point.rb +18 -11
  77. data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
  78. data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
  79. data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
  80. data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
  81. data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
  82. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +59 -0
  83. data/lib/sqreen/legacy/instrumentation.rb +22 -10
  84. data/lib/sqreen/legacy/old_event_submission_strategy.rb +228 -0
  85. data/lib/sqreen/legacy/waf_redactions.rb +49 -0
  86. data/lib/sqreen/log.rb +3 -2
  87. data/lib/sqreen/log/loggable.rb +2 -1
  88. data/lib/sqreen/logger.rb +24 -0
  89. data/lib/sqreen/metrics/base.rb +3 -0
  90. data/lib/sqreen/metrics_store.rb +33 -12
  91. data/lib/sqreen/null_logger.rb +22 -0
  92. data/lib/sqreen/performance_notifications/binned_metrics.rb +8 -2
  93. data/lib/sqreen/remote_command.rb +4 -0
  94. data/lib/sqreen/rules.rb +12 -6
  95. data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -2
  96. data/lib/sqreen/rules/custom_error_cb.rb +3 -3
  97. data/lib/sqreen/rules/rule_cb.rb +4 -0
  98. data/lib/sqreen/rules/waf_cb.rb +14 -11
  99. data/lib/sqreen/runner.rb +122 -15
  100. data/lib/sqreen/sensitive_data_redactor.rb +19 -31
  101. data/lib/sqreen/session.rb +53 -43
  102. data/lib/sqreen/signals/conversions.rb +288 -0
  103. data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
  104. data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
  105. data/lib/sqreen/version.rb +1 -1
  106. data/lib/sqreen/weave/budget.rb +46 -0
  107. data/lib/sqreen/weave/legacy/instrumentation.rb +194 -103
  108. data/lib/sqreen/worker.rb +6 -2
  109. metadata +96 -7
  110. data/lib/sqreen/backport.rb +0 -9
  111. data/lib/sqreen/backport/clock_gettime.rb +0 -74
  112. data/lib/sqreen/backport/original_name.rb +0 -88
  113. data/lib/sqreen/encoding_sanitizer.rb +0 -27
@@ -0,0 +1,39 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/event_listener'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing/server_data'
5
+
6
+ module Sqreen
7
+ module Ecosystem
8
+ module Http
9
+ class RackRequest
10
+ class HttpServerData
11
+ include ModuleApi::Tracing::ServerData
12
+ end
13
+
14
+ include ModuleApi::EventListener
15
+ include ModuleApi::MessageProducer
16
+
17
+ def setup
18
+ advice = wrap_for_interest(
19
+ ModuleApi::Tracing::ServerData,
20
+ &method(:handle_request)
21
+ )
22
+ on_request_start(&advice)
23
+ end
24
+
25
+ private
26
+
27
+ def handle_request(rack_request)
28
+ trace_id = rack_request.env[ModuleApi::TRACE_ID_ENV_KEY]
29
+
30
+ HttpServerData.new(
31
+ transport: 'http',
32
+ client_ip: rack_request.ip,
33
+ tracing_identifier: trace_id
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module Loggable
6
+ private
7
+
8
+ def logger
9
+ DispatchTable.fetch_logger.call
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,61 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/instrumentation'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing/consumer_data'
5
+ require 'sqreen/ecosystem/module_api/tracing/producer_data'
6
+
7
+ module Sqreen
8
+ module Ecosystem
9
+ module Messaging
10
+ class Bunny
11
+ include ModuleApi::Loggable
12
+ include ModuleApi::Instrumentation
13
+ include ModuleApi::MessageProducer
14
+
15
+ def setup
16
+ advice_send = wrap_for_interest(ModuleApi::Tracing::ProducerData, &method(:after_send_advice))
17
+ advice_receive = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive_advice))
18
+ advice_receive_consumer = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive_advice_consumer))
19
+ instrument 'Bunny::Queue#publish', after: advice_send
20
+ instrument 'Bunny::Queue#pop', after: advice_receive
21
+ instrument 'Bunny::Consumer#call', after: advice_receive_consumer
22
+ end
23
+
24
+ private
25
+
26
+ # @param [Sqreen::Graft::CallbackCall] call
27
+ def after_send_advice(call, _ball)
28
+ return if call.raised
29
+
30
+ create_signal(call.instance, ModuleApi::Tracing::ProducerData)
31
+ end
32
+
33
+ # @param [Sqreen::Graft::CallbackCall] call
34
+ def after_receive_advice(call, _ball)
35
+ return if call.raised
36
+
37
+ create_signal(call.instance, ModuleApi::Tracing::ConsumerData)
38
+ end
39
+
40
+ # @param [Sqreen::Graft::CallbackCall] call
41
+ def after_receive_advice_consumer(call, _ball)
42
+ return if call.raised
43
+
44
+ queue = call.instance.queue
45
+ create_signal(queue, ModuleApi::Tracing::ConsumerData)
46
+ end
47
+
48
+ # @param [Bunny::Queue] q
49
+ def create_signal(q, clazz)
50
+ conn = q.channel.connection
51
+
52
+ clazz.new(
53
+ message_type: :amqp,
54
+ host: conn.host,
55
+ topic: q.name,
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,70 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/instrumentation'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing/consumer_data'
5
+ require 'sqreen/ecosystem/module_api/tracing/producer_data'
6
+
7
+ module Sqreen
8
+ module Ecosystem
9
+ module Messaging
10
+ class Kafka
11
+ include ModuleApi::Loggable
12
+ include ModuleApi::Instrumentation
13
+ include ModuleApi::MessageProducer
14
+
15
+ def setup
16
+ advice_send = wrap_for_interest(ModuleApi::Tracing::ProducerData, &method(:after_send))
17
+ advice_receive = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive))
18
+ instrument 'Kafka::Broker#produce', after: advice_send
19
+ instrument 'Kafka::Broker#fetch_messages', after: advice_receive
20
+ end
21
+
22
+ private
23
+
24
+ # @param [Sqreen::Graft::CallbackCall] call
25
+ def after_send(call, _ball)
26
+ return if call.raised
27
+ if call.args.length != 1
28
+ logger.info "Expected 1 arguments to Kafka::Broker#produce"
29
+ return
30
+ end
31
+ options = call.args.first
32
+ topics = options[:messages_for_topics].keys
33
+
34
+ create_signal_data(ModuleApi::Tracing::ProducerData,
35
+ call.instance,
36
+ topics)
37
+ end
38
+
39
+ # @param [Sqreen::Graft::CallbackCall] call
40
+ def after_receive(call, _ball)
41
+ return if call.raised
42
+ if call.args.length != 1
43
+ logger.info "Expected 1 arguments to Kafka::Broker#fetch_messages"
44
+ return
45
+ end
46
+ options = call.args.first
47
+ topics = options[:topics].keys
48
+
49
+ create_signal_data(ModuleApi::Tracing::ConsumerData,
50
+ call.instance,
51
+ topics)
52
+ end
53
+
54
+ # @param [Class] clazz
55
+ # @param [Kafka::Broker] broker
56
+ # @param [Array<String>] topics
57
+ def create_signal_data(clazz, broker, topics)
58
+ host = broker.instance_variable_get :@host
59
+ topics.map do |top|
60
+ clazz.new(
61
+ message_type: :kafka,
62
+ host: host,
63
+ topic: top,
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,66 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/instrumentation'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing/consumer_data'
5
+ require 'sqreen/ecosystem/module_api/tracing/producer_data'
6
+
7
+ # see https://aws.amazon.com/blogs/developer/announcing-amazon-kinesis-subscribetoshard-api-support-in-the-aws-sdk-for-ruby/
8
+ module Sqreen
9
+ module Ecosystem
10
+ module Messaging
11
+ class Kinesis
12
+ include ModuleApi::Loggable
13
+ include ModuleApi::Instrumentation
14
+ include ModuleApi::MessageProducer
15
+
16
+ def setup
17
+ advice_send = wrap_for_interest(ModuleApi::Tracing::ProducerData, &method(:after_send_advice))
18
+ advice_receive = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive_advice))
19
+ instrument 'Aws::Kinesis::Client#put_record', after: advice_send
20
+ instrument 'Aws::Kinesis::Client#put_records', after: advice_send
21
+ # more sophisticated usages (register_stream_consumer, possibly with AsyncClient)
22
+ # are not supported. They are more difficult to test, as kinesalite doesn't support them
23
+ instrument 'Aws::Kinesis::Client#get_shard_iterator', after: advice_receive
24
+ end
25
+
26
+ private
27
+
28
+ # @param [Sqreen::Graft::CallbackCall] call
29
+ def after_send_advice(call, _ball)
30
+ return if call.raised
31
+ unless call.args.length > 0 && call.args[0].is_a?(Hash)
32
+ logger.info "Unexpected arguments to put_record(s)"
33
+ return
34
+ end
35
+
36
+ create_signal(call.instance, call.args, ModuleApi::Tracing::ProducerData)
37
+ end
38
+
39
+ # @param [Sqreen::Graft::CallbackCall] call
40
+ def after_receive_advice(call, _ball)
41
+ return if call.raised
42
+ unless call.args.length > 0 && call.args[0].is_a?(Hash)
43
+ logger.info "Unexpected arguments to get_shared_iterator"
44
+ return
45
+ end
46
+
47
+ create_signal(call.instance, call.args, ModuleApi::Tracing::ConsumerData)
48
+ end
49
+
50
+ def create_signal(client, args, clazz)
51
+ hash = args[0]
52
+ stream_name = hash[:stream_name] || hash['stream_name']
53
+ return unless stream_name
54
+
55
+ endpoint = client.instance_variable_get(:@config).endpoint
56
+
57
+ clazz.new(
58
+ message_type: :'aws-kinesis',
59
+ host: endpoint.host,
60
+ topic: stream_name,
61
+ )
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,68 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/instrumentation'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing/consumer_data'
5
+ require 'sqreen/ecosystem/module_api/tracing/producer_data'
6
+
7
+ module Sqreen
8
+ module Ecosystem
9
+ module Messaging
10
+ class Sqs
11
+ include ModuleApi::Loggable
12
+ include ModuleApi::Instrumentation
13
+ include ModuleApi::MessageProducer
14
+
15
+ def setup
16
+ advice_send = wrap_for_interest(ModuleApi::Tracing::ProducerData, &method(:after_send_advice))
17
+ advice_receive = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive_advice))
18
+ instrument 'Aws::SQS::Client#send_message', after: advice_send
19
+ instrument 'Aws::SQS::Client#send_message_batch', after: advice_send
20
+ instrument 'Aws::SQS::Client#receive_message', after: advice_receive
21
+ end
22
+
23
+ private
24
+
25
+ # @param [Sqreen::Graft::CallbackCall] call
26
+ def after_send_advice(call, _ball)
27
+ return if call.raised
28
+ unless call.args.length > 0 && call.args[0].is_a?(Hash)
29
+ logger.info "Unexpected arguments to send_message(_batch)"
30
+ return
31
+ end
32
+
33
+ create_signal(call.args, ModuleApi::Tracing::ProducerData)
34
+ end
35
+
36
+ # @param [Sqreen::Graft::CallbackCall] call
37
+ def after_receive_advice(call, _ball)
38
+ return if call.raised
39
+ unless call.args.length > 0 && call.args[0].is_a?(Hash)
40
+ logger.info "Unexpected arguments to receive_message"
41
+ return
42
+ end
43
+
44
+ create_signal(call.args, ModuleApi::Tracing::ConsumerData)
45
+ end
46
+
47
+ def create_signal(args, clazz)
48
+ hash = args[0]
49
+ queue_url = hash[:queue_url] || hash['queue_url']
50
+ return unless queue_url
51
+
52
+ begin
53
+ uri = URI.parse(queue_url)
54
+ rescue URI::InvalidURIError
55
+ logger.info { "Invalid URI: #{uri}" }
56
+ return
57
+ end
58
+
59
+ clazz.new(
60
+ message_type: :'aws-sqs',
61
+ host: uri.host,
62
+ topic: ($1 if uri.path =~ /\A\/queue\/(?:[^\/]+\/)?([^\/]+)\z/),
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,30 @@
1
+ require 'sqreen/ecosystem/loggable'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ # The API that the transport/tracing modules are written against
6
+ module ModuleApi
7
+ TRACE_ID_HEADER = 'X-Sqreen-Trace-Identifier'.freeze
8
+ TRACE_ID_ENV_KEY = 'HTTP_X_SQREEN_TRACE_IDENTIFIER'.freeze
9
+
10
+ Loggable = Sqreen::Ecosystem::Loggable
11
+
12
+ module ClassMethods
13
+ attr_writer :module_name
14
+
15
+ def module_name
16
+ if instance_variable_defined?(:@module_name)
17
+ @module_name
18
+ else
19
+ # to snake case
20
+ @module_name = to_s.sub(/.*::/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.included(mod)
26
+ mod.extend(ClassMethods)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module EventListener
7
+ private
8
+
9
+ # XXX: callbacks need to be wrapped in order ot handle
10
+ # perfcap, exceptions, and maybe other concerns applying
11
+ # across the board
12
+ def on_request_start(&cb)
13
+ DispatchTable.add_request_start_listener.call(cb)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module Instrumentation
7
+ def self.included(mod)
8
+ mod.send :include, ModuleApi unless mod.ancestors.include?(ModuleApi)
9
+ end
10
+
11
+ private
12
+
13
+ # Just forwards the call to the instrumentation service
14
+ # @param [String] method
15
+ # @param [Hash{Symbol=>Proc}] advice keys are one of: :before, :after,
16
+ # :raised,
17
+ def instrument(method, advice)
18
+ DispatchTable.instrument.call(self.class.module_name, method, advice)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,57 @@
1
+ require 'sqreen/ecosystem/loggable'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module MessageProducer
7
+ include Loggable
8
+
9
+ # method for ecosystem to inject the config
10
+ # @param [Sqreen::Ecosystem::TracingBroker]
11
+ attr_writer :tracing_broker
12
+
13
+ private
14
+
15
+ def determine_interest(type, hints = {})
16
+ @tracing_broker.interested_consumers(type, hints)
17
+ end
18
+
19
+ def publish(data, interested)
20
+ @tracing_broker.publish(data, interested)
21
+ end
22
+
23
+ # Convenience wrapper.
24
+ # Wraps a callback, skipping it if there is no interest in the type
25
+ # produced and submitting the return value as a message to the
26
+ # tracing broker
27
+ def wrap_for_interest(type, gen_hints = nil, &block)
28
+ raise ArgumentError, 'no block passed' if block.nil?
29
+
30
+ proc do |*args|
31
+ hints = gen_hints[*args] if gen_hints
32
+ interested = determine_interest(type, hints || {})
33
+
34
+ unless interested
35
+ logger.debug { "No interested consumers in #{type}" }
36
+ next
37
+ end
38
+
39
+ res = block[*args]
40
+
41
+ next if res.nil?
42
+
43
+ if res.is_a?(Array)
44
+ res.each do |d|
45
+ raise "unexpected return type: #{d.class}" unless d.is_a?(type)
46
+ @tracing_broker.publish(d, interested)
47
+ end
48
+ else
49
+ raise "unexpected return type: #{res.class}" unless res.is_a?(type)
50
+ @tracing_broker.publish(res, interested)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end