instana 1.10.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.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +23 -0
  3. data/.gitignore +16 -0
  4. data/.rubocop.yml +1156 -0
  5. data/.travis.yml +43 -0
  6. data/Configuration.md +149 -0
  7. data/Dockerfile +13 -0
  8. data/Gemfile +41 -0
  9. data/LICENSE +21 -0
  10. data/README.md +102 -0
  11. data/Rakefile +56 -0
  12. data/Tracing.md +145 -0
  13. data/Troubleshooting.md +32 -0
  14. data/benchmarks/Gemfile +7 -0
  15. data/benchmarks/id_generation.rb +12 -0
  16. data/benchmarks/opentracing.rb +26 -0
  17. data/benchmarks/rack_vanilla_vs_traced.rb +80 -0
  18. data/benchmarks/stackprof_rack_tracing.rb +77 -0
  19. data/benchmarks/time_processing.rb +12 -0
  20. data/bin/console +7 -0
  21. data/bin/setup +8 -0
  22. data/examples/opentracing.rb +31 -0
  23. data/examples/tracing.rb +80 -0
  24. data/gemfiles/libraries.gemfile +71 -0
  25. data/gemfiles/rails32.gemfile +51 -0
  26. data/gemfiles/rails42.gemfile +50 -0
  27. data/gemfiles/rails50.gemfile +52 -0
  28. data/instana.gemspec +46 -0
  29. data/lib/instana.rb +12 -0
  30. data/lib/instana/agent.rb +441 -0
  31. data/lib/instana/agent/helpers.rb +61 -0
  32. data/lib/instana/agent/hooks.rb +37 -0
  33. data/lib/instana/agent/tasks.rb +48 -0
  34. data/lib/instana/base.rb +54 -0
  35. data/lib/instana/collector.rb +116 -0
  36. data/lib/instana/collectors/gc.rb +57 -0
  37. data/lib/instana/collectors/memory.rb +34 -0
  38. data/lib/instana/collectors/thread.rb +30 -0
  39. data/lib/instana/config.rb +79 -0
  40. data/lib/instana/eum/eum-test.js.erb +16 -0
  41. data/lib/instana/eum/eum.js.erb +14 -0
  42. data/lib/instana/frameworks/cuba.rb +6 -0
  43. data/lib/instana/frameworks/instrumentation/abstract_mysql_adapter.rb +58 -0
  44. data/lib/instana/frameworks/instrumentation/action_controller.rb +183 -0
  45. data/lib/instana/frameworks/instrumentation/action_view.rb +43 -0
  46. data/lib/instana/frameworks/instrumentation/active_record.rb +27 -0
  47. data/lib/instana/frameworks/instrumentation/mysql2_adapter.rb +81 -0
  48. data/lib/instana/frameworks/instrumentation/mysql_adapter.rb +56 -0
  49. data/lib/instana/frameworks/instrumentation/postgresql_adapter.rb +71 -0
  50. data/lib/instana/frameworks/rails.rb +42 -0
  51. data/lib/instana/frameworks/roda.rb +6 -0
  52. data/lib/instana/frameworks/sinatra.rb +9 -0
  53. data/lib/instana/helpers.rb +40 -0
  54. data/lib/instana/instrumentation.rb +21 -0
  55. data/lib/instana/instrumentation/dalli.rb +78 -0
  56. data/lib/instana/instrumentation/excon.rb +74 -0
  57. data/lib/instana/instrumentation/grpc.rb +84 -0
  58. data/lib/instana/instrumentation/net-http.rb +66 -0
  59. data/lib/instana/instrumentation/rack.rb +77 -0
  60. data/lib/instana/instrumentation/redis.rb +82 -0
  61. data/lib/instana/instrumentation/resque.rb +131 -0
  62. data/lib/instana/instrumentation/rest-client.rb +34 -0
  63. data/lib/instana/instrumentation/sidekiq-client.rb +45 -0
  64. data/lib/instana/instrumentation/sidekiq-worker.rb +54 -0
  65. data/lib/instana/opentracing/carrier.rb +4 -0
  66. data/lib/instana/opentracing/tracer.rb +18 -0
  67. data/lib/instana/rack.rb +10 -0
  68. data/lib/instana/setup.rb +36 -0
  69. data/lib/instana/test.rb +40 -0
  70. data/lib/instana/thread_local.rb +15 -0
  71. data/lib/instana/tracer.rb +392 -0
  72. data/lib/instana/tracing/processor.rb +92 -0
  73. data/lib/instana/tracing/span.rb +401 -0
  74. data/lib/instana/tracing/span_context.rb +33 -0
  75. data/lib/instana/util.rb +261 -0
  76. data/lib/instana/version.rb +4 -0
  77. data/lib/oj_check.rb +16 -0
  78. data/lib/opentracing.rb +6 -0
  79. data/test/agent/agent_test.rb +143 -0
  80. data/test/apps/cuba.rb +15 -0
  81. data/test/apps/grpc_server.rb +81 -0
  82. data/test/apps/roda.rb +10 -0
  83. data/test/apps/sinatra.rb +5 -0
  84. data/test/benchmarks/bench_id_generation.rb +12 -0
  85. data/test/benchmarks/bench_opentracing.rb +13 -0
  86. data/test/config_test.rb +37 -0
  87. data/test/frameworks/cuba_test.rb +44 -0
  88. data/test/frameworks/rack_test.rb +167 -0
  89. data/test/frameworks/rails/actioncontroller_test.rb +93 -0
  90. data/test/frameworks/rails/actionview3_test.rb +255 -0
  91. data/test/frameworks/rails/actionview4_test.rb +254 -0
  92. data/test/frameworks/rails/actionview5_test.rb +221 -0
  93. data/test/frameworks/rails/activerecord3_test.rb +134 -0
  94. data/test/frameworks/rails/activerecord4_test.rb +134 -0
  95. data/test/frameworks/rails/activerecord5_test.rb +87 -0
  96. data/test/frameworks/roda_test.rb +44 -0
  97. data/test/frameworks/sinatra_test.rb +44 -0
  98. data/test/instana_test.rb +27 -0
  99. data/test/instrumentation/dalli_test.rb +253 -0
  100. data/test/instrumentation/excon_test.rb +147 -0
  101. data/test/instrumentation/grpc_test.rb +377 -0
  102. data/test/instrumentation/net-http_test.rb +160 -0
  103. data/test/instrumentation/redis_test.rb +119 -0
  104. data/test/instrumentation/resque_test.rb +128 -0
  105. data/test/instrumentation/rest-client_test.rb +55 -0
  106. data/test/instrumentation/sidekiq-client_test.rb +125 -0
  107. data/test/instrumentation/sidekiq-worker_test.rb +173 -0
  108. data/test/jobs/resque_error_job.rb +22 -0
  109. data/test/jobs/resque_fast_job.rb +20 -0
  110. data/test/jobs/sidekiq_job_1.rb +6 -0
  111. data/test/jobs/sidekiq_job_2.rb +7 -0
  112. data/test/models/block.rb +18 -0
  113. data/test/servers/grpc_50051.rb +20 -0
  114. data/test/servers/helpers/sidekiq_worker_initializer.rb +27 -0
  115. data/test/servers/rackapp_6511.rb +25 -0
  116. data/test/servers/rails_3205.rb +167 -0
  117. data/test/servers/sidekiq/worker.rb +27 -0
  118. data/test/test_helper.rb +145 -0
  119. data/test/tracing/custom_test.rb +158 -0
  120. data/test/tracing/id_management_test.rb +130 -0
  121. data/test/tracing/opentracing_test.rb +335 -0
  122. data/test/tracing/trace_test.rb +67 -0
  123. data/test/tracing/tracer_async_test.rb +198 -0
  124. data/test/tracing/tracer_test.rb +223 -0
  125. metadata +327 -0
@@ -0,0 +1,56 @@
1
+ module Instana
2
+ module Instrumentation
3
+ module MysqlAdapter
4
+ IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE).freeze
5
+ EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
6
+
7
+ # This module supports instrumenting ActiveRecord with the mysql2 adapter.
8
+ #
9
+ def self.included(klass)
10
+ if ActiveRecord::VERSION::STRING >= '3.2'
11
+ Instana::Util.method_alias(klass, :exec_query)
12
+
13
+ @@sanitize_regexp = Regexp.new('(\'[\s\S][^\']*\'|\d*\.\d+|\d+|NULL)', Regexp::IGNORECASE)
14
+ end
15
+ end
16
+
17
+ # Collect up this DB connection info for reporting.
18
+ #
19
+ # @param sql [String]
20
+ # @return [Hash] Hash of collected KVs
21
+ #
22
+ def collect(sql)
23
+ payload = { :activerecord => {} }
24
+ payload[:activerecord][:sql] = sql.gsub(@@sanitize_regexp, '?')
25
+ payload[:activerecord][:adapter] = @config[:adapter]
26
+ payload[:activerecord][:host] = @config[:host]
27
+ payload[:activerecord][:db] = @config[:database]
28
+ payload[:activerecord][:username] = @config[:username]
29
+ payload
30
+ end
31
+
32
+ # In the spirit of ::ActiveRecord::ExplainSubscriber.ignore_payload? There are
33
+ # only certain calls that we're interested in tracing. e.g. No use to instrument
34
+ # framework caches.
35
+ #
36
+ # @param payload [String]
37
+ # @return [Boolean]
38
+ #
39
+ def ignore_payload?(name, sql)
40
+ IGNORED_PAYLOADS.include?(name) || sql !~ EXPLAINED_SQLS
41
+ end
42
+
43
+ def exec_query_with_instana(sql, name = 'SQL', binds = [], *args)
44
+ if !::Instana.tracer.tracing? || ignore_payload?(name, sql) ||
45
+ ::Instana.tracer.current_span[:n] == :activerecord
46
+ return exec_query_without_instana(sql, name, binds, *args)
47
+ end
48
+
49
+ kv_payload = collect(sql)
50
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
51
+ exec_query_without_instana(sql, name, binds, *args)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,71 @@
1
+ module Instana
2
+ module Instrumentation
3
+ module PostgreSQLAdapter
4
+ IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE).freeze
5
+ EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
6
+
7
+ # This module supports instrumenting ActiveRecord with the postgresql adapter. Only
8
+ # versions >= 3.1 are supported.
9
+ #
10
+ def self.included(klass)
11
+ if (::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR > 0) ||
12
+ ::ActiveRecord::VERSION::MAJOR >= 4
13
+
14
+ # ActiveRecord 3.1 and up
15
+ Instana::Util.method_alias(klass, :exec_query)
16
+ Instana::Util.method_alias(klass, :exec_delete)
17
+
18
+ @@sanitize_regexp = Regexp.new('(\'[\s\S][^\']*\'|\d*\.\d+|\d+|NULL)', Regexp::IGNORECASE)
19
+ end
20
+ end
21
+
22
+ # Collect up this DB connection info for reporting.
23
+ #
24
+ # @param sql [String]
25
+ # @return [Hash] Hash of collected KVs
26
+ #
27
+ def collect(sql)
28
+ payload = { :activerecord => {} }
29
+ payload[:activerecord][:sql] = sql.gsub(@@sanitize_regexp, '?')
30
+ payload[:activerecord][:adapter] = @config[:adapter]
31
+ payload[:activerecord][:host] = @config[:host]
32
+ payload[:activerecord][:db] = @config[:database]
33
+ payload[:activerecord][:username] = @config[:username]
34
+ payload
35
+ end
36
+
37
+ # In the spirit of ::ActiveRecord::ExplainSubscriber.ignore_payload? There are
38
+ # only certain calls that we're interested in tracing. e.g. No use to instrument
39
+ # framework caches.
40
+ #
41
+ # @param payload [String]
42
+ # @return [Boolean]
43
+ #
44
+ def ignore_payload?(name, sql)
45
+ IGNORED_PAYLOADS.include?(name) || sql !~ EXPLAINED_SQLS
46
+ end
47
+
48
+ def exec_query_with_instana(sql, name = 'SQL', binds = [], *args)
49
+ if !::Instana.tracer.tracing? || ignore_payload?(name, sql)
50
+ return exec_query_without_instana(sql, name, binds, *args)
51
+ end
52
+
53
+ kv_payload = collect(sql)
54
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
55
+ exec_query_without_instana(sql, name, binds, *args)
56
+ end
57
+ end
58
+
59
+ def exec_delete_with_instana(sql, name = nil, binds = [])
60
+ if !::Instana.tracer.tracing? || ignore_payload?(name, sql)
61
+ return exec_delete_without_instana(sql, name, binds)
62
+ end
63
+
64
+ kv_payload = collect(sql)
65
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
66
+ exec_delete_without_instana(sql, name, binds)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,42 @@
1
+ require "instana/rack"
2
+
3
+ if defined?(::Rails)
4
+
5
+ if ::Rails::VERSION::MAJOR < 3
6
+ ::Rails.configuration.after_initialize do
7
+ # In Rails, let's use the Rails logger
8
+ ::Instana.logger = ::Rails.logger if ::Rails.logger
9
+
10
+ if ::Instana.config[:tracing][:enabled]
11
+ ::Instana.logger.info "Instrumenting Rack"
12
+ ::Rails.configuration.middleware.insert 0, ::Instana::Rack
13
+ else
14
+ ::Instana.logger.info "Rack: Tracing disabled via config. Not enabling middleware."
15
+ end
16
+ end
17
+ else
18
+ module ::Instana
19
+ class Railtie < ::Rails::Railtie
20
+ initializer 'instana.rack' do |app|
21
+ # In Rails, let's use the Rails logger
22
+ ::Instana.logger = ::Rails.logger if ::Rails.logger
23
+
24
+ if ::Instana.config[:tracing][:enabled]
25
+ ::Instana.logger.info "Instrumenting Rack"
26
+ app.config.middleware.insert 0, ::Instana::Rack
27
+ else
28
+ ::Instana.logger.info "Rack: Tracing disabled via config. Not enabling middleware."
29
+ end
30
+ end
31
+
32
+ if ::Instana.config[:tracing][:enabled]
33
+ config.after_initialize do
34
+ require "instana/frameworks/instrumentation/active_record"
35
+ require "instana/frameworks/instrumentation/action_controller"
36
+ require "instana/frameworks/instrumentation/action_view"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ require "instana/rack"
2
+
3
+ if defined?(::Roda)
4
+ ::Instana.logger.info "Instrumenting Roda"
5
+ Roda.use ::Instana::Rack
6
+ end
@@ -0,0 +1,9 @@
1
+ require "instana/rack"
2
+
3
+ # This instrumentation will insert Rack into Sinatra _and_ Padrino since
4
+ # the latter is based on Sinatra
5
+
6
+ if defined?(::Sinatra)
7
+ ::Instana.logger.info "Instrumenting Sinatra"
8
+ ::Sinatra::Base.use ::Instana::Rack
9
+ end
@@ -0,0 +1,40 @@
1
+ module Instana
2
+ module Helpers
3
+ EUM_SNIPPET= (File.read(File.dirname(__FILE__) + '/eum/eum.js.erb')).freeze
4
+ EUM_TEST_SNIPPET= (File.read(File.dirname(__FILE__) + '/eum/eum-test.js.erb')).freeze
5
+
6
+ class << self
7
+
8
+ # Returns a processed javascript snippet to be placed within the HEAD tag of an HTML page.
9
+ #
10
+ def eum_snippet(api_key, kvs = {})
11
+ return nil if !::Instana.tracer.tracing?
12
+
13
+ ::Instana.config[:eum_api_key] = api_key
14
+ ::Instana.config[:eum_baggage] = kvs
15
+
16
+ ERB.new(EUM_SNIPPET).result
17
+ rescue => e
18
+ Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
19
+ Instana.logger.debug { e.backtrace.join("\r\n") }
20
+ return nil
21
+ end
22
+
23
+ # Returns a processed javascript snippet to be placed within the HEAD tag of an HTML page.
24
+ # This one is used for testing only
25
+ #
26
+ def eum_test_snippet(api_key, kvs = {})
27
+ return nil if !::Instana.tracer.tracing?
28
+
29
+ ::Instana.config[:eum_api_key] = api_key
30
+ ::Instana.config[:eum_baggage] = kvs
31
+
32
+ ERB.new(EUM_TEST_SNIPPET).result
33
+ rescue => e
34
+ Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
35
+ Instana.logger.debug { e.backtrace.join("\r\n") }
36
+ return nil
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module Instana
2
+ AUTOLOAD_DIRECTORIES = [:instrumentation, :frameworks].freeze
3
+ end
4
+
5
+
6
+ if !ENV.key?('INSTANA_DISABLE_AUTO_INSTR') || ENV['INSTANA_DISABLE_AUTO_INSTR'] === 'false'
7
+ #
8
+ # Load all of the files in the specified subdirectories
9
+ #
10
+ ::Instana::AUTOLOAD_DIRECTORIES.each do |d|
11
+ pattern = File.join(File.dirname(__FILE__), d.to_s, '*.rb')
12
+ Dir.glob(pattern) do |f|
13
+ begin
14
+ require f
15
+ rescue => e
16
+ Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
17
+ Instana.logger.debug { e.backtrace.join("\r\n") }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,78 @@
1
+ module Instana
2
+ module Instrumentation
3
+ module Dalli
4
+ def self.included(klass)
5
+ ::Instana::Util.method_alias(klass, :perform)
6
+ ::Instana::Util.method_alias(klass, :get_multi)
7
+ end
8
+
9
+ def perform_with_instana(*args, &blk)
10
+ if !::Instana.tracer.tracing? || ::Instana.tracer.tracing_span?(:memcache)
11
+ do_skip = true
12
+ return perform_without_instana(*args, &blk)
13
+ end
14
+
15
+ op, key, *_opts = args
16
+
17
+ entry_payload = { :memcache => {} }
18
+ entry_payload[:memcache][:namespace] = @options[:namespace] if @options.key?(:namespace)
19
+ entry_payload[:memcache][:command] = op
20
+ entry_payload[:memcache][:key] = key
21
+
22
+ ::Instana.tracer.log_entry(:memcache, entry_payload)
23
+ result = perform_without_instana(*args, &blk)
24
+
25
+ kv_payload = { :memcache => {}}
26
+ if op == :get
27
+ kv_payload[:memcache][:hit] = result ? 1 : 0
28
+ end
29
+ result
30
+ rescue => e
31
+ ::Instana.tracer.log_error(e)
32
+ raise
33
+ ensure
34
+ ::Instana.tracer.log_exit(:memcache, kv_payload) unless do_skip
35
+ end
36
+
37
+ def get_multi_with_instana(*keys)
38
+ entry_payload = { :memcache => {} }
39
+ entry_payload[:memcache][:namespace] = @options[:namespace] if @options.key?(:namespace)
40
+ entry_payload[:memcache][:command] = :get_multi
41
+ entry_payload[:memcache][:keys] = keys.flatten.join(", ")
42
+
43
+ ::Instana.tracer.log_entry(:memcache, entry_payload)
44
+ result = get_multi_without_instana(*keys)
45
+
46
+ exit_payload = { :memcache => {} }
47
+ exit_payload[:memcache][:hits] = result.length
48
+ result
49
+ rescue => e
50
+ ::Instana.tracer.log_error(e)
51
+ raise
52
+ ensure
53
+ ::Instana.tracer.log_exit(:memcache, exit_payload)
54
+ end
55
+ end
56
+
57
+ module DalliServer
58
+ def self.included(klass)
59
+ ::Instana::Util.method_alias(klass, :request)
60
+ end
61
+
62
+ def request_with_instana(op, *args)
63
+ if ::Instana.tracer.tracing? || ::Instana.tracer.tracing_span?(:memcache)
64
+ info_payload = { :memcache => {} }
65
+ info_payload[:memcache][:server] = "#{@hostname}:#{@port}"
66
+ ::Instana.tracer.log_info(info_payload)
67
+ end
68
+ request_without_instana(op, *args)
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ if defined?(::Dalli) && ::Instana.config[:dalli][:enabled]
75
+ ::Instana.logger.info "Instrumenting Dalli"
76
+ ::Dalli::Client.send(:include, ::Instana::Instrumentation::Dalli)
77
+ ::Dalli::Server.send(:include, ::Instana::Instrumentation::DalliServer)
78
+ end
@@ -0,0 +1,74 @@
1
+ if defined?(::Excon) && ::Instana.config[:excon][:enabled]
2
+ module Instana
3
+ module Instrumentation
4
+ class Excon < ::Excon::Middleware::Base
5
+ def request_call(datum)
6
+ return @stack.request_call(datum) unless ::Instana.tracer.tracing?
7
+
8
+ payload = { :http => {} }
9
+ path = datum[:path].split('?').first
10
+ payload[:http][:url] = "#{datum[:connection].instance_variable_get(:@socket_key)}#{path}"
11
+ payload[:http][:method] = datum[:method] if datum.key?(:method)
12
+
13
+ if datum[:pipeline] == true
14
+ # Pass the context along in the datum so we get back on response
15
+ # and can close out the async span
16
+ datum[:instana_span] = ::Instana.tracer.log_async_entry(:excon, payload)
17
+ t_context = datum[:instana_span].context
18
+ else
19
+ ::Instana.tracer.log_entry(:excon, payload)
20
+ t_context = ::Instana.tracer.context
21
+ end
22
+
23
+ # Set request headers; encode IDs as hexadecimal strings
24
+ datum[:headers]['X-Instana-T'] = t_context.trace_id_header
25
+ datum[:headers]['X-Instana-S'] = t_context.span_id_header
26
+
27
+ @stack.request_call(datum)
28
+ end
29
+
30
+ def error_call(datum)
31
+ return @stack.error_call(datum) unless ::Instana.tracer.tracing?
32
+
33
+ if datum[:pipeline] == true
34
+ ::Instana.tracer.log_async_error(datum[:error], datum[:instana_span])
35
+ else
36
+ ::Instana.tracer.log_error(datum[:error])
37
+ end
38
+ @stack.error_call(datum)
39
+ end
40
+
41
+ def response_call(datum)
42
+ # FIXME: Will connect exceptions call a response?
43
+ #
44
+ return @stack.response_call(datum) unless ::Instana.tracer.tracing?
45
+
46
+ result = @stack.response_call(datum)
47
+
48
+ status = datum[:status]
49
+ if !status && datum.key?(:response) && datum[:response].is_a?(Hash)
50
+ status = datum[:response][:status]
51
+ end
52
+
53
+ if status.between?(500, 511)
54
+ # Because of the 5xx response, we flag this span as errored but
55
+ # without a backtrace (no exception)
56
+ ::Instana.tracer.log_error(nil)
57
+ end
58
+
59
+ if datum[:pipeline] == true
60
+ # Pickup context of this async span from datum[:instana_span]
61
+ ::Instana.tracer.log_async_exit(:excon, { :http => {:status => status } }, datum[:instana_span])
62
+ else
63
+ ::Instana.tracer.log_exit(:excon, { :http => {:status => status } })
64
+ end
65
+ result
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ ::Instana.logger.info "Instrumenting Excon"
72
+ ::Excon.defaults[:middlewares].unshift(::Instana::Instrumentation::Excon)
73
+ end
74
+
@@ -0,0 +1,84 @@
1
+ call_types = [:request_response, :client_streamer, :server_streamer, :bidi_streamer]
2
+
3
+ if defined?(GRPC::ActiveCall) && ::Instana.config[:grpc][:enabled]
4
+ call_types.each do |call_type|
5
+ GRPC::ClientStub.class_eval <<-RUBY, __FILE__, __LINE__ + 1
6
+ def #{call_type}_with_instana(method, *others, **options)
7
+ kvs = { rpc: {} }
8
+
9
+ unless ::Instana.tracer.tracing?
10
+ return #{call_type}_without_instana(method, *others, **options)
11
+ end
12
+
13
+ kvs[:rpc][:flavor] = :grpc
14
+ kvs[:rpc][:host] = @host
15
+ kvs[:rpc][:call] = method
16
+ kvs[:rpc][:call_type] = :#{call_type}
17
+
18
+ ::Instana.tracer.log_entry(:'rpc-client', kvs)
19
+
20
+ context = ::Instana.tracer.context
21
+ if context
22
+ options[:metadata] = (options[:metadata] || {}).merge(
23
+ 'x-instana-t' => context.trace_id_header,
24
+ 'x-instana-s' => context.span_id_header
25
+ )
26
+ end
27
+
28
+ #{call_type}_without_instana(method, *others, **options)
29
+ rescue => e
30
+ kvs[:rpc][:error] = true
31
+ ::Instana.tracer.log_info(kvs)
32
+ ::Instana.tracer.log_error(e)
33
+ raise
34
+ ensure
35
+ ::Instana.tracer.log_exit(:'rpc-client', {})
36
+ end
37
+
38
+ alias #{call_type}_without_instana #{call_type}
39
+ alias #{call_type} #{call_type}_with_instana
40
+ RUBY
41
+ end
42
+ ::Instana.logger.info 'Instrumenting GRPC client'
43
+ end
44
+
45
+ if defined?(GRPC::RpcDesc) && ::Instana.config[:grpc][:enabled]
46
+ call_types.each do |call_type|
47
+ GRPC::RpcDesc.class_eval <<-RUBY, __FILE__, __LINE__ + 1
48
+ def handle_#{call_type}_with_instana(active_call, mth, *others)
49
+ kvs = { rpc: {} }
50
+ metadata = active_call.metadata
51
+
52
+ incoming_context = {}
53
+ if metadata.key?('x-instana-t')
54
+ incoming_context[:trace_id] = ::Instana::Util.header_to_id(metadata['x-instana-t'])
55
+ incoming_context[:span_id] = ::Instana::Util.header_to_id(metadata['x-instana-s']) if metadata.key?('x-instana-s')
56
+ incoming_context[:level] = metadata['x-instana-l'] if metadata.key?('x-instana-l')
57
+ end
58
+
59
+ kvs[:rpc][:flavor] = :grpc
60
+ kvs[:rpc][:host] = Socket.gethostname
61
+ kvs[:rpc][:call] = "/\#{mth.owner.service_name}/\#{name}"
62
+ kvs[:rpc][:call_type] = :#{call_type}
63
+ kvs[:rpc][:peer] = { address: active_call.peer }
64
+
65
+ ::Instana.tracer.log_start_or_continue(
66
+ :'rpc-server', kvs, incoming_context
67
+ )
68
+
69
+ handle_#{call_type}_without_instana(active_call, mth, *others)
70
+ rescue => e
71
+ kvs[:rpc][:error] = true
72
+ ::Instana.tracer.log_info(kvs)
73
+ ::Instana.tracer.log_error(e)
74
+ raise
75
+ ensure
76
+ ::Instana.tracer.log_end(:'rpc-server', {}) if ::Instana.tracer.tracing?
77
+ end
78
+
79
+ alias handle_#{call_type}_without_instana handle_#{call_type}
80
+ alias handle_#{call_type} handle_#{call_type}_with_instana
81
+ RUBY
82
+ end
83
+ ::Instana.logger.info 'Instrumenting GRPC server'
84
+ end