appoptics_apm_mnfst 4.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
  4. data/.gitignore +29 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +121 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +769 -0
  9. data/CONFIG.md +33 -0
  10. data/Gemfile +29 -0
  11. data/LICENSE +193 -0
  12. data/README.md +393 -0
  13. data/Rakefile +230 -0
  14. data/appoptics_apm.gemspec +61 -0
  15. data/bin/appoptics_apm_config +15 -0
  16. data/build_gem.sh +15 -0
  17. data/build_gem_upload_to_packagecloud.sh +20 -0
  18. data/examples/SDK/01_basic_tracing.rb +67 -0
  19. data/examples/carrying_context.rb +220 -0
  20. data/ext/oboe_metal/extconf.rb +114 -0
  21. data/ext/oboe_metal/lib/.keep +0 -0
  22. data/ext/oboe_metal/noop/noop.c +7 -0
  23. data/ext/oboe_metal/src/VERSION +1 -0
  24. data/init.rb +4 -0
  25. data/lib/appoptics_apm.rb +76 -0
  26. data/lib/appoptics_apm/api.rb +20 -0
  27. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  28. data/lib/appoptics_apm/api/logging.rb +375 -0
  29. data/lib/appoptics_apm/api/memcache.rb +37 -0
  30. data/lib/appoptics_apm/api/metrics.rb +55 -0
  31. data/lib/appoptics_apm/api/profiling.rb +203 -0
  32. data/lib/appoptics_apm/api/tracing.rb +53 -0
  33. data/lib/appoptics_apm/api/util.rb +122 -0
  34. data/lib/appoptics_apm/base.rb +230 -0
  35. data/lib/appoptics_apm/config.rb +254 -0
  36. data/lib/appoptics_apm/frameworks/grape.rb +97 -0
  37. data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
  38. data/lib/appoptics_apm/frameworks/rails.rb +94 -0
  39. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  40. data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -0
  41. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  42. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  43. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  44. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
  45. data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
  46. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  47. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  48. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  49. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  50. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  51. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +108 -0
  52. data/lib/appoptics_apm/frameworks/sinatra.rb +125 -0
  53. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  54. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  55. data/lib/appoptics_apm/inst/curb.rb +330 -0
  56. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  57. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  58. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  59. data/lib/appoptics_apm/inst/excon.rb +125 -0
  60. data/lib/appoptics_apm/inst/faraday.rb +94 -0
  61. data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
  62. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  63. data/lib/appoptics_apm/inst/http.rb +73 -0
  64. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  65. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  66. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  67. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  68. data/lib/appoptics_apm/inst/moped.rb +466 -0
  69. data/lib/appoptics_apm/inst/rack.rb +199 -0
  70. data/lib/appoptics_apm/inst/redis.rb +275 -0
  71. data/lib/appoptics_apm/inst/resque.rb +151 -0
  72. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  73. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  74. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  75. data/lib/appoptics_apm/inst/sidekiq-worker.rb +65 -0
  76. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  77. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  78. data/lib/appoptics_apm/instrumentation.rb +22 -0
  79. data/lib/appoptics_apm/legacy_method_profiling.rb +90 -0
  80. data/lib/appoptics_apm/loading.rb +65 -0
  81. data/lib/appoptics_apm/logger.rb +42 -0
  82. data/lib/appoptics_apm/method_profiling.rb +33 -0
  83. data/lib/appoptics_apm/noop/README.md +9 -0
  84. data/lib/appoptics_apm/noop/context.rb +26 -0
  85. data/lib/appoptics_apm/noop/metadata.rb +22 -0
  86. data/lib/appoptics_apm/ruby.rb +35 -0
  87. data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
  88. data/lib/appoptics_apm/sdk/tracing.rb +315 -0
  89. data/lib/appoptics_apm/support.rb +119 -0
  90. data/lib/appoptics_apm/test.rb +94 -0
  91. data/lib/appoptics_apm/thread_local.rb +26 -0
  92. data/lib/appoptics_apm/util.rb +319 -0
  93. data/lib/appoptics_apm/version.rb +15 -0
  94. data/lib/appoptics_apm/xtrace.rb +103 -0
  95. data/lib/joboe_metal.rb +212 -0
  96. data/lib/oboe.rb +7 -0
  97. data/lib/oboe/README +2 -0
  98. data/lib/oboe/backward_compatibility.rb +80 -0
  99. data/lib/oboe/inst/rack.rb +11 -0
  100. data/lib/oboe_metal.rb +198 -0
  101. data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
  102. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
  103. data/yardoc_frontpage.md +26 -0
  104. metadata +266 -0
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v4
11
+ #
12
+ module ActionController
13
+ include AppOpticsAPM::Inst::RailsBase
14
+
15
+ def self.included(base)
16
+ base.class_eval do
17
+ alias_method_chain :process_action, :appoptics
18
+ alias_method_chain :render, :appoptics
19
+ end
20
+ end
21
+
22
+ def process_action_with_appoptics(method_name, *args)
23
+ kvs = {
24
+ :Controller => self.class.name,
25
+ :Action => self.action_name,
26
+ }
27
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
28
+ request.env['appoptics_apm.action'] = kvs[:Action]
29
+
30
+ return process_action_without_appoptics(method_name, *args) unless AppOpticsAPM.tracing?
31
+ begin
32
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller][:collect_backtraces]
33
+
34
+ AppOpticsAPM::API.log_entry('rails', kvs)
35
+
36
+ process_action_without_appoptics(method_name, *args)
37
+
38
+ rescue Exception => e
39
+ AppOpticsAPM::API.log_exception('rails', e) if log_rails_error?(e)
40
+ raise
41
+ ensure
42
+ AppOpticsAPM::API.log_exit('rails')
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v5
11
+ #
12
+ module ActionController
13
+ include AppOpticsAPM::Inst::RailsBase
14
+
15
+ def process_action(method_name, *args)
16
+ kvs = {
17
+ :Controller => self.class.name,
18
+ :Action => self.action_name,
19
+ }
20
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
21
+ request.env['appoptics_apm.action'] = kvs[:Action]
22
+
23
+ return super(method_name, *args) unless AppOpticsAPM.tracing?
24
+ begin
25
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller][:collect_backtraces]
26
+
27
+ AppOpticsAPM::API.log_entry('rails', kvs)
28
+ super(method_name, *args)
29
+
30
+ rescue Exception => e
31
+ AppOpticsAPM::API.log_exception('rails', e) if log_rails_error?(e)
32
+ raise
33
+ ensure
34
+ AppOpticsAPM::API.log_exit('rails')
35
+ end
36
+ end
37
+
38
+ #
39
+ # render
40
+ #
41
+ # Our render wrapper that calls 'trace', which will log if we are tracing
42
+ #
43
+ def render(*args, &blk)
44
+ trace('actionview') do
45
+ super(*args, &blk)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v5.
11
+ #
12
+ module ActionControllerAPI
13
+ include AppOpticsAPM::Inst::RailsBase
14
+
15
+ def process_action(method_name, *args)
16
+ kvs = {
17
+ :Controller => self.class.name,
18
+ :Action => self.action_name
19
+ }
20
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
21
+ request.env['appoptics_apm.action'] = kvs[:Action]
22
+
23
+ return super(method_name, *args) unless AppOpticsAPM.tracing?
24
+ begin
25
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller_api][:collect_backtraces]
26
+
27
+ AppOpticsAPM::API.log_entry('rails-api', kvs)
28
+ super(method_name, *args)
29
+
30
+ rescue Exception => e
31
+ AppOpticsAPM::API.log_exception('rails', e) if log_rails_error?(e)
32
+ raise
33
+ ensure
34
+ AppOpticsAPM::API.log_exit('rails-api')
35
+ end
36
+ end
37
+
38
+ #
39
+ # render
40
+ #
41
+ # Our render wrapper that calls 'trace', which will log if we are tracing
42
+ #
43
+ def render(*args, &blk)
44
+ trace('actionview') do
45
+ super(*args, &blk)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ if defined?(ActionView::Base) && AppOpticsAPM::Config[:action_view][:enabled]
5
+
6
+ ##
7
+ # ActionView Instrumentation is version dependent. ActionView 2.x is separate
8
+ # and ActionView 3.0 is a special case.
9
+ # Everything else goes here. (ActionView 3.1 - 4.0 as of this writing)
10
+ #
11
+ if (Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR > 0) || Rails::VERSION::MAJOR >= 4
12
+
13
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting actionview' if AppOpticsAPM::Config[:verbose]
14
+
15
+ ActionView::PartialRenderer.class_eval do
16
+ alias :render_partial_without_appoptics :render_partial
17
+ def render_partial
18
+ entry_kvs = {}
19
+ begin
20
+ name = AppOpticsAPM::Util.prettify(@options[:partial]) if @options.is_a?(Hash)
21
+ entry_kvs[:FunctionName] = :render_partial
22
+ entry_kvs[:Class] = :PartialRenderer
23
+ entry_kvs[:Module] = :ActionView
24
+ entry_kvs[:File] = __FILE__
25
+ entry_kvs[:LineNumber] = __LINE__
26
+ rescue => e
27
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
28
+ end
29
+
30
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
31
+ render_partial_without_appoptics
32
+ end
33
+ end
34
+
35
+ alias :render_collection_without_appoptics :render_collection
36
+ def render_collection
37
+ entry_kvs = {}
38
+ begin
39
+ name = AppOpticsAPM::Util.prettify(@path)
40
+ entry_kvs[:FunctionName] = :render_collection
41
+ entry_kvs[:Class] = :PartialRenderer
42
+ entry_kvs[:Module] = :ActionView
43
+ entry_kvs[:File] = __FILE__
44
+ entry_kvs[:LineNumber] = __LINE__
45
+ rescue => e
46
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
47
+ end
48
+
49
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
50
+ render_collection_without_appoptics
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+
58
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ if defined?(ActionView::Base) && AppOpticsAPM::Config[:action_view][:enabled]
5
+
6
+ if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0
7
+
8
+ ActionView::Partials::PartialRenderer.class_eval do
9
+ alias :render_partial_without_appoptics :render_partial
10
+ def render_partial(object = @object)
11
+ entry_kvs = {}
12
+ begin
13
+ name = AppOpticsAPM::Util.prettify(@options[:partial]) if @options.is_a?(Hash)
14
+ entry_kvs[:FunctionName] = :render_partial
15
+ entry_kvs[:Class] = :PartialRenderer
16
+ entry_kvs[:Module] = 'ActionView::Partials'
17
+ entry_kvs[:File] = __FILE__
18
+ entry_kvs[:LineNumber] = __LINE__
19
+ rescue => e
20
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
21
+ end
22
+
23
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
24
+ render_partial_without_appoptics(object)
25
+ end
26
+ end
27
+
28
+ alias :render_collection_without_appoptics :render_collection
29
+ def render_collection
30
+ entry_kvs = {}
31
+ begin
32
+ name = AppOpticsAPM::Util.prettify(@path)
33
+ entry_kvs[:FunctionName] = :render_collection
34
+ entry_kvs[:Class] = :PartialRenderer
35
+ entry_kvs[:Module] = 'ActionView::Partials'
36
+ entry_kvs[:File] = __FILE__
37
+ entry_kvs[:LineNumber] = __LINE__
38
+ rescue => e
39
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
40
+ end
41
+
42
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
43
+ render_collection_without_appoptics
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,27 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/mysql'
5
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2'
6
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql'
7
+
8
+ if AppOpticsAPM::Config[:active_record][:enabled] && !defined?(JRUBY_VERSION)
9
+ begin
10
+ adapter = ActiveRecord::Base.connection_config[:adapter]
11
+
12
+ if Rails::VERSION::MAJOR < 5
13
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/utils'
14
+ else
15
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x'
16
+ end
17
+
18
+ AppOpticsAPM::Inst::ConnectionAdapters::FlavorInitializers.mysql if adapter == 'mysql'
19
+ AppOpticsAPM::Inst::ConnectionAdapters::FlavorInitializers.mysql2 if adapter == 'mysql2'
20
+ AppOpticsAPM::Inst::ConnectionAdapters::FlavorInitializers.postgresql if adapter == 'postgresql'
21
+
22
+ rescue StandardError => e
23
+ AppOpticsAPM.logger.error "[appoptics_apm/error] AppOpticsAPM/ActiveRecord error: #{e.inspect}"
24
+ AppOpticsAPM.logger.debug e.backtrace.join("\n")
25
+ end
26
+ end
27
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,43 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module FlavorInitializers
8
+ def self.mysql
9
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting activerecord mysqladapter' if AppOpticsAPM::Config[:verbose]
10
+
11
+ # ActiveRecord 3.2 and higher
12
+ if (ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR >= 2) ||
13
+ ActiveRecord::VERSION::MAJOR == 4
14
+
15
+ # AbstractMysqlAdapter
16
+ AppOpticsAPM::Util.send_include(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter,
17
+ AppOpticsAPM::Inst::ConnectionAdapters::Utils)
18
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, :execute)
19
+
20
+ # MysqlAdapter
21
+ AppOpticsAPM::Util.send_include(ActiveRecord::ConnectionAdapters::MysqlAdapter,
22
+ AppOpticsAPM::Inst::ConnectionAdapters::Utils)
23
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::MysqlAdapter, :exec_query)
24
+
25
+ else
26
+ # ActiveRecord 3.1 and below
27
+
28
+ # MysqlAdapter
29
+ AppOpticsAPM::Util.send_include(ActiveRecord::ConnectionAdapters::MysqlAdapter,
30
+ AppOpticsAPM::Inst::ConnectionAdapters::Utils)
31
+
32
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::MysqlAdapter, :execute)
33
+
34
+ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 1
35
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::MysqlAdapter, :begin_db_transaction)
36
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::MysqlAdapter, :exec_delete)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module FlavorInitializers
8
+ def self.mysql2
9
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting activerecord mysql2adapter' if AppOpticsAPM::Config[:verbose]
10
+
11
+ AppOpticsAPM::Util.send_include(ActiveRecord::ConnectionAdapters::Mysql2Adapter,
12
+ AppOpticsAPM::Inst::ConnectionAdapters::Utils)
13
+
14
+ if (ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0) ||
15
+ ActiveRecord::VERSION::MAJOR == 2
16
+ # ActiveRecord 3.0 and prior
17
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::Mysql2Adapter, :execute)
18
+ else
19
+ # ActiveRecord 3.1 and above
20
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_insert)
21
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_query)
22
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_update)
23
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_delete)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module FlavorInitializers
8
+ def self.postgresql
9
+
10
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting activerecord postgresqladapter' if AppOpticsAPM::Config[:verbose]
11
+
12
+ AppOpticsAPM::Util.send_include(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter,
13
+ AppOpticsAPM::Inst::ConnectionAdapters::Utils)
14
+
15
+ if (ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR > 0) ||
16
+ ActiveRecord::VERSION::MAJOR >= 4
17
+
18
+ # ActiveRecord 3.1 and up
19
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :exec_query)
20
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :exec_update)
21
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :exec_delete)
22
+
23
+ else
24
+ # ActiveRecord 3.0 and prior
25
+ AppOpticsAPM::Util.method_alias(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :execute)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,119 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module Utils
8
+
9
+ def extract_trace_details(sql, name = nil, binds = [])
10
+ opts = {}
11
+ if AppOpticsAPM::Config[:sanitize_sql]
12
+ # Sanitize SQL and don't report binds
13
+ opts[:Query] = AppOpticsAPM::Util.sanitize_sql(sql)
14
+ else
15
+ # Report raw SQL and any binds if they exist
16
+ opts[:Query] = sql.to_s
17
+ opts[:QueryArgs] = binds.map { |col, val| [col.name, val.to_s] } unless binds.empty?
18
+ end
19
+
20
+ opts[:Name] = name.to_s if name
21
+ opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:active_record][:collect_backtraces]
22
+
23
+ config = ActiveRecord::Base.connection_config
24
+ if config
25
+ opts[:Database] = config[:database] if config.key?(:database)
26
+ opts[:RemoteHost] = config[:host] if config.key?(:host)
27
+ adapter_name = config[:adapter]
28
+
29
+ case adapter_name
30
+ when /mysql/i
31
+ opts[:Flavor] = 'mysql'
32
+ when /postgres/i
33
+ opts[:Flavor] = 'postgresql'
34
+ end
35
+ end
36
+ rescue StandardError => e
37
+ AppOpticsAPM.logger.debug "[appoptics_apm/rails] Exception raised capturing ActiveRecord KVs: #{e.inspect}"
38
+ AppOpticsAPM.logger.debug e.backtrace.join('\n')
39
+ ensure
40
+ return opts
41
+ end
42
+
43
+ # We don't want to trace framework caches. Only instrument SQL that
44
+ # directly hits the database.
45
+ def ignore_payload?(name)
46
+ %w(SCHEMA EXPLAIN CACHE).include?(name.to_s) ||
47
+ (name && name.to_sym == :skip_logging) ||
48
+ name == 'ActiveRecord::SchemaMigration Load'
49
+ end
50
+
51
+ def execute_with_appoptics(sql, name = nil)
52
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
53
+
54
+ opts = extract_trace_details(sql, name)
55
+ AppOpticsAPM::API.trace('activerecord', opts, :ar_started) do
56
+ execute_without_appoptics(sql, name)
57
+ end
58
+ else
59
+ execute_without_appoptics(sql, name)
60
+ end
61
+ end
62
+
63
+ def exec_query_with_appoptics(sql, name = nil, binds = [])
64
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
65
+
66
+ opts = extract_trace_details(sql, name, binds)
67
+ AppOpticsAPM::API.trace('activerecord', opts, :ar_started) do
68
+ exec_query_without_appoptics(sql, name, binds)
69
+ end
70
+ else
71
+ exec_query_without_appoptics(sql, name, binds)
72
+ end
73
+ end
74
+
75
+ def exec_delete_with_appoptics(sql, name = nil, binds = [])
76
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
77
+
78
+ opts = extract_trace_details(sql, name, binds)
79
+ AppOpticsAPM::API.trace('activerecord', opts, :ar_started) do
80
+ exec_delete_without_appoptics(sql, name, binds)
81
+ end
82
+ else
83
+ exec_delete_without_appoptics(sql, name, binds)
84
+ end
85
+ end
86
+
87
+ def exec_update_with_appoptics(sql, name = nil, binds = [])
88
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
89
+
90
+ opts = extract_trace_details(sql, name, binds)
91
+ AppOpticsAPM::API.trace('activerecord', opts, :ar_started) do
92
+ exec_update_without_appoptics(sql, name, binds)
93
+ end
94
+ else
95
+ exec_update_without_appoptics(sql, name, binds)
96
+ end
97
+ end
98
+
99
+ def exec_insert_with_appoptics(sql, name = nil, binds = [], *args)
100
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
101
+
102
+ opts = extract_trace_details(sql, name, binds)
103
+ AppOpticsAPM::API.trace('activerecord', opts, :ar_started) do
104
+ exec_insert_without_appoptics(sql, name, binds, *args)
105
+ end
106
+ else
107
+ exec_insert_without_appoptics(sql, name, binds, *args)
108
+ end
109
+ end
110
+
111
+ def begin_db_transaction_with_appoptics
112
+ AppOpticsAPM::API.trace('activerecord', { :Query => 'BEGIN', :Flavor => :mysql }, :ar_started) do
113
+ begin_db_transaction_without_appoptics
114
+ end
115
+ end
116
+ end # Utils
117
+ end
118
+ end
119
+ end