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,79 @@
1
+ module Instana
2
+ class Config
3
+
4
+ def initialize
5
+ @config = {}
6
+ if ENV.key?('INSTANA_AGENT_HOST')
7
+ @config[:agent_host] = ENV['INSTANA_AGENT_HOST']
8
+ else
9
+ @config[:agent_host] = '127.0.0.1'
10
+ end
11
+ if ENV.key?('INSTANA_AGENT_PORT')
12
+ @config[:agent_port] = ENV['INSTANA_AGENT_PORT']
13
+ else
14
+ @config[:agent_port] = 42699
15
+ end
16
+
17
+ # Global on/off switch for prebuilt environments
18
+ # Setting this to false will disable this gem
19
+ # from doing anything.
20
+ @config[:enabled] = true
21
+
22
+ # Enable/disable metrics globally or individually (default: all enabled)
23
+ @config[:metrics] = { :enabled => true }
24
+ @config[:metrics][:gc] = { :enabled => true }
25
+ @config[:metrics][:memory] = { :enabled => true }
26
+ @config[:metrics][:thread] = { :enabled => true }
27
+
28
+ # Enable/disable tracing (default: enabled)
29
+ @config[:tracing] = { :enabled => true }
30
+
31
+ if ENV.key?('INSTANA_DEBUG')
32
+ @config[:collector] = { :enabled => true, :interval => 3 }
33
+ else
34
+ @config[:collector] = { :enabled => true, :interval => 1 }
35
+ end
36
+
37
+ # EUM Related
38
+ @config[:eum_api_key] = nil
39
+ @config[:eum_baggage] = {}
40
+
41
+ # In Ruby, backtrace collection is very expensive so it's
42
+ # (unfortunately) disabled by default. If you still want
43
+ # backtraces, it can be enabled with this config option.
44
+ # ::Instana.config[:collect_backtraces] = true
45
+ @config[:collect_backtraces] = false
46
+
47
+ @config[:action_controller] = { :enabled => true }
48
+ @config[:action_view] = { :enabled => true }
49
+ @config[:active_record] = { :enabled => true }
50
+ @config[:dalli] = { :enabled => true }
51
+ @config[:excon] = { :enabled => true }
52
+ @config[:grpc] = { :enabled => true }
53
+ @config[:nethttp] = { :enabled => true }
54
+ @config[:redis] = { :enabled => true }
55
+ @config[:'resque-client'] = { :enabled => true }
56
+ @config[:'resque-worker'] = { :enabled => true }
57
+ @config[:'rest-client'] = { :enabled => true }
58
+ @config[:'sidekiq-client'] = { :enabled => true }
59
+ @config[:'sidekiq-worker'] = { :enabled => true }
60
+ end
61
+
62
+ def [](key)
63
+ @config[key.to_sym]
64
+ end
65
+
66
+ def []=(key, value)
67
+ @config[key.to_sym] = value
68
+
69
+ if key == :enabled
70
+ # Configuring global enable/disable flag, then set the
71
+ # appropriate children flags.
72
+ @config[:metrics][:enabled] = value
73
+ @config[:tracing][:enabled] = value
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ ::Instana.config = ::Instana::Config.new
@@ -0,0 +1,16 @@
1
+ <script nonce="68afd870-ae85-48c6-9689-9a5c359d5a1f">
2
+ (function(i,s,o,g,r,a,m){i['InstanaEumObject']=r;i[r]=i[r]||function(){
3
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
4
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
5
+ })(window,document,'script','//eum-test-fullstack-0-us-west-2.instana.io/eum.min.js','ineum');
6
+
7
+ ineum('reportingUrl', '//eum-test-fullstack-0-us-west-2.instana.io');
8
+ ineum('apiKey', '<%=::Instana.config[:eum_api_key]%>');
9
+ ineum('traceId', '<%=::Instana.tracer.trace_id_header%>');
10
+
11
+ <% if !::Instana.config[:eum_baggage].empty? %>
12
+ <% ::Instana.config[:eum_baggage].each do |k, v| %>
13
+ ineum('meta', '<%=k%>', '<%=v%>');
14
+ <% end %>
15
+ <% end %>
16
+ </script>
@@ -0,0 +1,14 @@
1
+ <script>
2
+ (function(i,s,o,g,r,a,m){i['InstanaEumObject']=r;i[r]=i[r]||function(){
3
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
4
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
5
+ })(window,document,'script','//eum.instana.io/eum.min.js','ineum');
6
+ ineum('apiKey', '<%=::Instana.config[:eum_api_key]%>');
7
+ ineum('traceId', '<%=::Instana.tracer.trace_id_header%>');
8
+
9
+ <% if !::Instana.config[:eum_baggage].empty? %>
10
+ <% ::Instana.config[:eum_baggage].each do |k, v| %>
11
+ ineum('meta', '<%=k%>', '<%=v%>');
12
+ <% end %>
13
+ <% end %>
14
+ </script>
@@ -0,0 +1,6 @@
1
+ require "instana/rack"
2
+
3
+ if defined?(::Cuba)
4
+ ::Instana.logger.info "Instrumenting Cuba"
5
+ Cuba.use ::Instana::Rack
6
+ end
@@ -0,0 +1,58 @@
1
+ module Instana
2
+ module Instrumentation
3
+ module AbstractMysqlAdapter
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, :execute)
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 execute_with_instana(sql, name = nil)
44
+ tracing = ::Instana.tracer.tracing?
45
+ if !tracing || ignore_payload?(name, sql)
46
+ return execute_without_instana(sql, name)
47
+ elsif ::Instana.tracer.current_span[:n] == :activerecord
48
+ return execute_without_instana(sql, name)
49
+ end
50
+
51
+ kv_payload = collect(sql)
52
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
53
+ execute_without_instana(sql, name)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,183 @@
1
+ module Instana
2
+ module Instrumentation
3
+
4
+ # Contains the methods common to both ::Instana::Instrumentation::ActionController
5
+ # and ::Instana::Instrumentation::ActionControllerLegacy
6
+ #
7
+ module ActionControllerCommon
8
+
9
+ # Indicates whether a Controller rescue handler is in place. If so, this affects
10
+ # error logging and reporting. (Hence the need for this method).
11
+ #
12
+ # @return [Boolean]
13
+ #
14
+ def has_rails_handler?(exception)
15
+ found = false
16
+ rescue_handlers.detect do |klass_name, _handler|
17
+ # Rescue handlers can be specified as strings or constant names
18
+ klass = self.class.const_get(klass_name) rescue nil
19
+ klass ||= klass_name.constantize rescue nil
20
+ found = exception.is_a?(klass) if klass
21
+ end
22
+ found
23
+ rescue => e
24
+ ::Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
25
+ return false
26
+ end
27
+
28
+ # Render can be called with many options across the various supported
29
+ # versions of Rails. This method attempts to make sense and provide
30
+ # insight into what is happening (rendering a layout, file, nothing,
31
+ # plaintext etc.)
32
+ def get_render_topic(opts)
33
+ if opts.key?(:layout)
34
+ case opts[:layout]
35
+ when FalseClass
36
+ name = "Without layout"
37
+ when String
38
+ name = opts[:layout]
39
+ when Proc
40
+ name = "Proc"
41
+ else
42
+ name = "Default"
43
+ end
44
+ end
45
+
46
+ return name if name
47
+
48
+ if opts.key?(:template)
49
+ name ||= opts[:template]
50
+ elsif opts.key?(:file)
51
+ name ||= opts[:file]
52
+ elsif opts.key?(:nothing)
53
+ name = "Nothing"
54
+ elsif opts.key?(:plain)
55
+ name = "Plaintext"
56
+ elsif opts.key?(:json)
57
+ name = "JSON"
58
+ elsif opts.key?(:xml)
59
+ name = "XML"
60
+ elsif opts.key?(:body)
61
+ name = "Raw"
62
+ elsif opts.key?(:js)
63
+ name = "Javascript"
64
+ end
65
+ name
66
+ end
67
+ end
68
+
69
+ # Used in ActionPack versions 5 and beyond, this module provides
70
+ # instrumentation for ActionController (a part of ActionPack)
71
+ #
72
+ module ActionController
73
+ include ::Instana::Instrumentation::ActionControllerCommon
74
+
75
+ # This is the Rails 5 version of the process_action method where we use prepend to
76
+ # instrument the class method instead of using the older alias_method_chain.
77
+ #
78
+ def process_action(*args)
79
+ kv_payload = { :actioncontroller => {} }
80
+ kv_payload[:actioncontroller][:controller] = self.class.name
81
+ kv_payload[:actioncontroller][:action] = action_name
82
+
83
+ ::Instana.tracer.log_entry(:actioncontroller, kv_payload)
84
+
85
+ super(*args)
86
+ rescue Exception => e
87
+ ::Instana.tracer.log_error(e) unless has_rails_handler?(e)
88
+ raise
89
+ ensure
90
+ ::Instana.tracer.log_exit(:actioncontroller)
91
+ end
92
+
93
+ # The Instana wrapper method for ActionController::Base.render
94
+ # for versions 5+.
95
+ #
96
+ def render(*args, &blk)
97
+ # Figure out what's being rendered
98
+ if args.length > 0 && args[0].is_a?(Hash)
99
+ name = get_render_topic(args[0])
100
+ end
101
+ name ||= "Default"
102
+
103
+ ::Instana.tracer.log_entry(:actionview, :actionview => { :name => name })
104
+
105
+ super(*args, &blk)
106
+ rescue Exception => e
107
+ ::Instana.tracer.log_error(e) unless has_rails_handler?(e)
108
+ raise
109
+ ensure
110
+ ::Instana.tracer.log_exit(:actionview)
111
+ end
112
+ end
113
+
114
+ # Used in ActionPack versions 4 and earlier, this module provides
115
+ # instrumentation for ActionController (a part of ActionPack)
116
+ #
117
+ module ActionControllerLegacy
118
+ include ::Instana::Instrumentation::ActionControllerCommon
119
+
120
+ def self.included(klass)
121
+ klass.class_eval do
122
+ alias_method_chain :process_action, :instana
123
+ alias_method_chain :render, :instana
124
+ end
125
+ end
126
+
127
+ # The Instana wrapper method for ActionController::Base.process_action
128
+ # for versions 3 and 4.
129
+ #
130
+ def process_action_with_instana(*args)
131
+ kv_payload = { :actioncontroller => {} }
132
+ kv_payload[:actioncontroller][:controller] = self.class.name
133
+ kv_payload[:actioncontroller][:action] = action_name
134
+
135
+ ::Instana.tracer.log_entry(:actioncontroller, kv_payload)
136
+
137
+ process_action_without_instana(*args)
138
+ rescue Exception => e
139
+ ::Instana.tracer.log_error(e) unless has_rails_handler?(e)
140
+ raise
141
+ ensure
142
+ ::Instana.tracer.log_exit(:actioncontroller)
143
+ end
144
+
145
+ # The Instana wrapper method for ActionController::Base.render
146
+ # for versions 3 and 4.
147
+ #
148
+ def render_with_instana(*args, &blk)
149
+ if args.length > 0 && args[0].is_a?(Hash)
150
+ name = get_render_topic(args[0])
151
+ end
152
+ name ||= "Default"
153
+ ::Instana.tracer.log_entry(:actionview, :actionview => { :name => name })
154
+ render_without_instana(*args, &blk)
155
+ rescue Exception => e
156
+ ::Instana.tracer.log_error(e) unless has_rails_handler?(e)
157
+ raise
158
+ ensure
159
+ ::Instana.tracer.log_exit(:actionview)
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ if defined?(::ActionController) && ::Instana.config[:action_controller][:enabled] && ::ActionPack::VERSION::MAJOR >= 2
166
+ ::Instana.logger.info "Instrumenting ActionController"
167
+ if ActionPack::VERSION::MAJOR >= 5
168
+ ::ActionController::Base.send(:prepend, ::Instana::Instrumentation::ActionController)
169
+ else
170
+ ::ActionController::Base.send(:include, ::Instana::Instrumentation::ActionControllerLegacy)
171
+ end
172
+ end
173
+
174
+ # ActionController::API was introduced in Ruby on Rails 5 but was originally an independent project before being
175
+ # rolled into the Rails ActionPack. In case, someone is using the independent project or potentially backported
176
+ # the rails version to and older Ruby on Rails version, we only limit in a minimal way re: version checking.
177
+ #
178
+ # We allow ActionController::API instrumentation in version of Ruby on Rails 3 and higher.
179
+ #
180
+ if defined?(::ActionController::API) && ::Instana.config[:action_controller][:enabled] && ::ActionPack::VERSION::MAJOR >= 3
181
+ ::Instana.logger.info "Instrumenting ActionController API"
182
+ ::ActionController::API.send(:prepend, ::Instana::Instrumentation::ActionController)
183
+ end
@@ -0,0 +1,43 @@
1
+ module Instana
2
+ module Instrumentation
3
+ module ActionViewRenderer
4
+ def self.included(klass)
5
+ ::Instana::Util.method_alias(klass, :render_partial)
6
+ ::Instana::Util.method_alias(klass, :render_collection)
7
+ end
8
+
9
+ def render_partial_with_instana
10
+ kv_payload = { :render => {} }
11
+ kv_payload[:render][:type] = :partial
12
+ kv_payload[:render][:name] = @options[:partial].to_s if @options.is_a?(Hash)
13
+
14
+ ::Instana.tracer.log_entry(:render, kv_payload)
15
+ render_partial_without_instana
16
+ rescue Exception => e
17
+ ::Instana.tracer.log_error(e)
18
+ raise
19
+ ensure
20
+ ::Instana.tracer.log_exit(:render)
21
+ end
22
+
23
+ def render_collection_with_instana
24
+ kv_payload = { :render => {} }
25
+ kv_payload[:render][:type] = :collection
26
+ kv_payload[:render][:name] = @path.to_s
27
+
28
+ ::Instana.tracer.log_entry(:render, kv_payload)
29
+ render_collection_without_instana
30
+ rescue Exception => e
31
+ ::Instana.tracer.log_error(e)
32
+ raise
33
+ ensure
34
+ ::Instana.tracer.log_exit(:render)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ if defined?(::ActionView) && ::Instana.config[:action_view][:enabled] && ::ActionPack::VERSION::STRING >= '3.1'
41
+ ::Instana.logger.info "Instrumenting ActionView"
42
+ ::ActionView::PartialRenderer.send(:include, ::Instana::Instrumentation::ActionViewRenderer)
43
+ end
@@ -0,0 +1,27 @@
1
+
2
+ require "instana/frameworks/instrumentation/mysql_adapter"
3
+ require "instana/frameworks/instrumentation/abstract_mysql_adapter"
4
+ require "instana/frameworks/instrumentation/mysql2_adapter"
5
+ require "instana/frameworks/instrumentation/postgresql_adapter"
6
+
7
+ if defined?(::ActiveRecord) && ::Instana.config[:active_record][:enabled]
8
+
9
+ # Mysql
10
+ if defined?(ActiveRecord::ConnectionAdapters::MysqlAdapter)
11
+ ::Instana.logger.info "Instrumenting ActiveRecord (mysql)"
12
+ ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:include, ::Instana::Instrumentation::MysqlAdapter)
13
+ ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.send(:include, ::Instana::Instrumentation::AbstractMysqlAdapter)
14
+ end
15
+
16
+ # Mysql2
17
+ if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
18
+ ::Instana.logger.info "Instrumenting ActiveRecord (mysql2)"
19
+ ActiveRecord::ConnectionAdapters::Mysql2Adapter.send(:include, ::Instana::Instrumentation::Mysql2Adapter)
20
+ end
21
+
22
+ # Postgres
23
+ if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
24
+ ::Instana.logger.info "Instrumenting ActiveRecord (postgresql)"
25
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:include, ::Instana::Instrumentation::PostgreSQLAdapter)
26
+ end
27
+ end
@@ -0,0 +1,81 @@
1
+ module Instana
2
+ module Instrumentation
3
+ module Mysql2Adapter
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
+ # ActiveRecord 3.1 and up only (for now possibly)
11
+ if ActiveRecord::VERSION::STRING > '3.0'
12
+ Instana::Util.method_alias(klass, :exec_delete)
13
+ Instana::Util.method_alias(klass, :exec_insert)
14
+ Instana::Util.method_alias(klass, :exec_query)
15
+
16
+ @@sanitize_regexp = Regexp.new('(\'[\s\S][^\']*\'|\d*\.\d+|\d+|NULL)', Regexp::IGNORECASE)
17
+ end
18
+ end
19
+
20
+ # Collect up this DB connection info for reporting.
21
+ #
22
+ # @param sql [String]
23
+ # @return [Hash] Hash of collected KVs
24
+ #
25
+ def collect(sql)
26
+ payload = { :activerecord => {} }
27
+ payload[:activerecord][:sql] = sql.gsub(@@sanitize_regexp, '?')
28
+ payload[:activerecord][:adapter] = @config[:adapter]
29
+ payload[:activerecord][:host] = @config[:host]
30
+ payload[:activerecord][:db] = @config[:database]
31
+ payload[:activerecord][:username] = @config[:username]
32
+ payload
33
+ end
34
+
35
+ # In the spirit of ::ActiveRecord::ExplainSubscriber.ignore_payload? There are
36
+ # only certain calls that we're interested in tracing. e.g. No use to instrument
37
+ # framework caches.
38
+ #
39
+ # @param payload [String]
40
+ # @return [Boolean]
41
+ #
42
+ def ignore_payload?(name, sql)
43
+ IGNORED_PAYLOADS.include?(name) || sql !~ EXPLAINED_SQLS
44
+ end
45
+
46
+ def exec_delete_with_instana(sql, name = nil, binds = [])
47
+ if !::Instana.tracer.tracing? || ignore_payload?(name, sql)
48
+ return exec_delete_without_instana(sql, name, binds)
49
+ end
50
+
51
+ kv_payload = collect(sql)
52
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
53
+ exec_delete_without_instana(sql, name, binds)
54
+ end
55
+ end
56
+
57
+ def exec_insert_with_instana(sql, name = 'SQL', binds = [], *args)
58
+ if !::Instana.tracer.tracing? || ignore_payload?(name, sql)
59
+ return exec_insert_without_instana(sql, name, binds, *args)
60
+ end
61
+
62
+ kv_payload = collect(sql)
63
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
64
+ exec_insert_without_instana(sql, name, binds, *args)
65
+ end
66
+ end
67
+
68
+ def exec_query_with_instana(sql, name = 'SQL', binds = [], *args)
69
+ if !::Instana.tracer.tracing? || ignore_payload?(name, sql) ||
70
+ ::Instana.tracer.current_span[:n] == :activerecord
71
+ return exec_query_without_instana(sql, name, binds, *args)
72
+ end
73
+
74
+ kv_payload = collect(sql)
75
+ ::Instana.tracer.trace(:activerecord, kv_payload) do
76
+ exec_query_without_instana(sql, name, binds, *args)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end