appoptics_apm_mnfst 4.5.2

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 (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