appoptics_apm 4.12.2 → 4.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_and_release_gem.yml +103 -0
  3. data/.github/workflows/build_for_packagecloud.yml +70 -0
  4. data/.github/workflows/docker-images.yml +47 -0
  5. data/.github/workflows/run_cpluplus_tests.yml +73 -0
  6. data/.github/workflows/run_tests.yml +168 -0
  7. data/.github/workflows/scripts/test_install.rb +23 -0
  8. data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
  9. data/.github/workflows/test_on_4_linux.yml +159 -0
  10. data/.gitignore +17 -25
  11. data/.travis.yml +17 -14
  12. data/Gemfile +1 -25
  13. data/README.md +4 -6
  14. data/appoptics_apm.gemspec +11 -5
  15. data/examples/prepend.rb +13 -0
  16. data/examples/sdk_examples.rb +16 -0
  17. data/ext/oboe_metal/extconf.rb +25 -31
  18. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
  19. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
  20. data/ext/oboe_metal/src/README.md +6 -0
  21. data/ext/oboe_metal/src/VERSION +2 -1
  22. data/ext/oboe_metal/src/frames.cc +246 -0
  23. data/ext/oboe_metal/src/frames.h +40 -0
  24. data/ext/oboe_metal/src/init_appoptics_apm.cc +5 -4
  25. data/ext/oboe_metal/src/logging.cc +95 -0
  26. data/ext/oboe_metal/src/logging.h +35 -0
  27. data/ext/oboe_metal/src/oboe.h +8 -5
  28. data/ext/oboe_metal/src/oboe_api.cpp +40 -14
  29. data/ext/oboe_metal/src/oboe_api.hpp +29 -8
  30. data/ext/oboe_metal/src/oboe_debug.h +1 -0
  31. data/ext/oboe_metal/src/oboe_swig_wrap.cc +85 -21
  32. data/ext/oboe_metal/src/profiling.cc +435 -0
  33. data/ext/oboe_metal/src/profiling.h +78 -0
  34. data/ext/oboe_metal/test/CMakeLists.txt +53 -0
  35. data/ext/oboe_metal/test/FindGMock.cmake +43 -0
  36. data/ext/oboe_metal/test/README.md +56 -0
  37. data/ext/oboe_metal/test/frames_test.cc +164 -0
  38. data/ext/oboe_metal/test/profiling_test.cc +93 -0
  39. data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
  40. data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
  41. data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
  42. data/ext/oboe_metal/test/test.h +11 -0
  43. data/ext/oboe_metal/test/test_main.cc +32 -0
  44. data/lib/appoptics_apm/api/metrics.rb +3 -0
  45. data/lib/appoptics_apm/base.rb +1 -1
  46. data/lib/appoptics_apm/config.rb +11 -2
  47. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +7 -1
  48. data/lib/appoptics_apm/inst/rack.rb +13 -6
  49. data/lib/appoptics_apm/inst/redis.rb +1 -2
  50. data/lib/appoptics_apm/noop/context.rb +3 -0
  51. data/lib/appoptics_apm/noop/metadata.rb +4 -1
  52. data/lib/appoptics_apm/noop/profiling.rb +21 -0
  53. data/lib/appoptics_apm/oboe_init_options.rb +26 -22
  54. data/lib/appoptics_apm/support/profiling.rb +18 -0
  55. data/lib/appoptics_apm/support/transaction_metrics.rb +1 -1
  56. data/lib/appoptics_apm/support/transaction_settings.rb +2 -2
  57. data/lib/appoptics_apm/support/x_trace_options.rb +2 -2
  58. data/lib/appoptics_apm/support_report.rb +2 -2
  59. data/lib/appoptics_apm/test.rb +4 -3
  60. data/lib/appoptics_apm/util.rb +1 -1
  61. data/lib/appoptics_apm/version.rb +3 -3
  62. data/lib/appoptics_apm/xtrace.rb +1 -1
  63. data/lib/appoptics_apm.rb +3 -1
  64. data/lib/oboe_metal.rb +2 -2
  65. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +24 -0
  66. data/log/.keep +0 -0
  67. metadata +46 -16
  68. data/.travis/bundle.sh +0 -9
@@ -0,0 +1,11 @@
1
+ #ifndef TEST_H
2
+ #define TEST_H
3
+
4
+ class RubyCallsFrames {
5
+ public:
6
+ static VALUE c_get_frames();
7
+ };
8
+
9
+ void Init_RubyCallsFrames();
10
+
11
+ #endif //TEST_H
@@ -0,0 +1,32 @@
1
+ #include "gtest/gtest.h"
2
+ // #include "gmock/gmock.h"
3
+ #include <ruby/ruby.h>
4
+ #include "../src/profiling.h"
5
+ #include "../src/frames.h"
6
+ #include "test.h"
7
+
8
+ #ifndef FRAMES_BUFFER
9
+ #define FRAMES_BUFFER
10
+
11
+ using namespace std;
12
+
13
+ int main(int argc, char **argv) {
14
+ int state = -1;
15
+
16
+ // order important! init ruby before adding functions!
17
+ ruby_init();
18
+ Init_RubyCallsFrames();
19
+
20
+ // !!! if the require path is wrong, cmake will segfault !!!
21
+ string path(std::getenv("TEST_DIR"));
22
+ string cmd("require '" + path + "/" + "ruby_test_helper.rb" + "'");
23
+ rb_eval_string(cmd.c_str());
24
+
25
+ ::testing::InitGoogleTest(&argc, argv);
26
+
27
+ state = RUN_ALL_TESTS();
28
+
29
+ ruby_cleanup(0);
30
+ return state;
31
+ }
32
+ #endif //FRAMES_BUFFER
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2019 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
1
4
  module AppOpticsAPM
2
5
  module API
3
6
  module Metrics
@@ -136,7 +136,7 @@ module AppOpticsAPMBase
136
136
  #
137
137
  def tracing_layer_op?(operation)
138
138
  unless AppOpticsAPM.layer_op.nil? || AppOpticsAPM.layer_op.is_a?(Array)
139
- AppOpticsAPM.logger.error('[appopticsapm/logging] INTERNAL: layer_op should be nil or an array, please report to support@appoptics.com')
139
+ AppOpticsAPM.logger.error('[appopticsapm/logging] INTERNAL: layer_op should be nil or an array, please report to technicalsupport@solarwinds.com')
140
140
  return false
141
141
  end
142
142
 
@@ -224,6 +224,17 @@ module AppOpticsAPM
224
224
  Regexp.new(AppOpticsAPM::Config[:dnt_regexp], AppOpticsAPM::Config[:dnt_opts] || nil)
225
225
  end
226
226
 
227
+ elsif key == :profiling_interval
228
+ if value.is_a?(Integer) && value > 0
229
+ value = [100, value].min
230
+ else
231
+ value = 10
232
+ end
233
+ @@config[:profiling_interval] = value
234
+ # CProfiler may not be loaded yet, the profiler will send the value
235
+ # after it is loaded
236
+ AppOpticsAPM::CProfiler.set_interval(value) if defined? AppOpticsAPM::CProfiler
237
+
227
238
  elsif key == :transaction_settings
228
239
  if value.is_a?(Hash)
229
240
  AppOpticsAPM::TransactionSettings.compile_url_settings(value[:url])
@@ -262,8 +273,6 @@ module AppOpticsAPM
262
273
  end
263
274
  # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
264
275
 
265
-
266
-
267
276
  def self.method_missing(sym, *args)
268
277
  class_var_name = "@@#{sym}"
269
278
 
@@ -26,7 +26,13 @@ module AppOpticsAPM
26
26
  opts[:Backtrace] = AppOpticsAPM::API.backtrace
27
27
  end
28
28
 
29
- config = ActiveRecord::Base.connection_config
29
+ if ActiveRecord::Base.method_defined?(:connection_db_config)
30
+ # Rails 6.1++ deprecates connection_config
31
+ config = ActiveRecord::Base.connection_db_config.configuration_hash
32
+ else
33
+ config = ActiveRecord::Base.connection_config
34
+ end
35
+
30
36
  if config
31
37
  opts[:Database] = config[:database] if config.key?(:database)
32
38
  opts[:RemoteHost] = config[:host] if config.key?(:host)
@@ -40,12 +40,15 @@ if AppOpticsAPM.loaded
40
40
  options = AppOpticsAPM::XTraceOptions.new(env['HTTP_X_TRACE_OPTIONS'], env['HTTP_X_TRACE_OPTIONS_SIGNATURE'])
41
41
  xtrace = AppOpticsAPM::XTrace.valid?(env['HTTP_X_TRACE']) ? (env['HTTP_X_TRACE']) : nil
42
42
  settings = AppOpticsAPM::TransactionSettings.new(url, xtrace, options)
43
+ profile_spans = AppOpticsAPM::Config['profiling'] == :enabled ? 1 : -1
43
44
 
44
45
  response =
45
46
  propagate_xtrace(env, settings, xtrace) do
46
- sample(env, settings, options) do
47
- AppOpticsAPM::TransactionMetrics.metrics(env, settings) do
48
- @app.call(env)
47
+ sample(env, settings, options, profile_spans) do
48
+ AppOpticsAPM::Profiling.run do
49
+ AppOpticsAPM::TransactionMetrics.metrics(env, settings) do
50
+ @app.call(env)
51
+ end
49
52
  end
50
53
  end
51
54
  end || [500, {}, nil]
@@ -124,7 +127,7 @@ if AppOpticsAPM.loaded
124
127
  [status, headers, response]
125
128
  end
126
129
 
127
- def sample(env, settings, options)
130
+ def sample(env, settings, options, profile_spans)
128
131
  xtrace = env['HTTP_X_TRACE']
129
132
  if settings.do_sample
130
133
  begin
@@ -137,13 +140,17 @@ if AppOpticsAPM.loaded
137
140
  status, headers, response = yield
138
141
 
139
142
  AppOpticsAPM::API.log_exit(:rack, { Status: status,
140
- TransactionName: AppOpticsAPM.transaction_name })
143
+ TransactionName: AppOpticsAPM.transaction_name,
144
+ ProfileSpans: profile_spans})
145
+
141
146
  [status, headers, response]
142
147
  rescue Exception => e
143
148
  # it is ok to rescue Exception here because we are reraising it (we just need a chance to log_end)
144
149
  AppOpticsAPM::API.log_exception(:rack, e)
145
150
  AppOpticsAPM::API.log_exit(:rack, { Status: status,
146
- TransactionName: AppOpticsAPM.transaction_name })
151
+ TransactionName: AppOpticsAPM.transaction_name,
152
+ ProfileSpans: profile_spans
153
+ })
147
154
  raise
148
155
  end
149
156
  else
@@ -76,8 +76,7 @@ module AppOpticsAPM
76
76
 
77
77
  kvs[:KVOp] = command[0]
78
78
  kvs[:RemoteHost] = @options[:host]
79
-
80
- unless NO_KEY_OPS.include?(op) || (command[1].is_a?(Array) && command[1].count > 1)
79
+ unless NO_KEY_OPS.include?(op) || op == :del && command[1..-1].flatten.count > 1
81
80
  if command[1].is_a?(Array)
82
81
  kvs[:KVKey] = command[1].first
83
82
  else
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2019 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
1
4
  ####
2
5
  # noop version of AppOpticsAPM::Context
3
6
  #
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2019 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
1
4
  ####
2
5
  # noop version of AppOpticsAPM::Metadata
3
6
  #
@@ -19,4 +22,4 @@ module AppOpticsAPM
19
22
  false
20
23
  end
21
24
  end
22
- end
25
+ end
@@ -0,0 +1,21 @@
1
+ module AppOpticsAPM
2
+
3
+ # override the Ruby method, so that no code related to profiling gets executed
4
+ class Profiling
5
+
6
+ def self.run
7
+ yield
8
+ end
9
+ end
10
+
11
+ # these put the c-functions into "noop"
12
+ module CProfiler
13
+ def self.set_interval(_)
14
+ # do nothing
15
+ end
16
+
17
+ def self.get_tid
18
+ return 0
19
+ end
20
+ end
21
+ end
@@ -72,6 +72,8 @@ module AppOpticsAPM
72
72
  # timeout for ec2 metadata
73
73
  @ec2_md_timeout = read_and_validate_ec2_md_timeout
74
74
  @grpc_proxy = read_and_validate_proxy
75
+ # hardcoded arg for lambda (lambda not supported yet)
76
+ # hardcoded arg for grpc hack
75
77
  end
76
78
 
77
79
  def re_init # for testing with changed ENV vars
@@ -80,26 +82,28 @@ module AppOpticsAPM
80
82
 
81
83
  def array_for_oboe
82
84
  [
83
- @hostname_alias,
84
- @debug_level,
85
- @log_file_path,
86
- @max_transactions,
87
- @max_flush_wait_time,
88
- @events_flush_interval,
89
- @event_flush_batch_size,
90
-
91
- @reporter,
92
- @host,
93
- @service_key,
94
- @trusted_path,
95
- @buffer_size,
96
- @trace_metrics,
97
- @histogram_precision,
98
- @token_bucket_capacity,
99
- @token_bucket_rate,
100
- @file_single,
101
- @ec2_md_timeout,
102
- @grpc_proxy
85
+ @hostname_alias, # 0
86
+ @debug_level, # 1
87
+ @log_file_path, # 2
88
+ @max_transactions, # 3
89
+ @max_flush_wait_time, # 4
90
+ @events_flush_interval, # 5
91
+ @event_flush_batch_size, # 6
92
+
93
+ @reporter, # 7
94
+ @host, # 8
95
+ @service_key, # 9
96
+ @trusted_path, #10
97
+ @buffer_size, #11
98
+ @trace_metrics, #12
99
+ @histogram_precision, #13
100
+ @token_bucket_capacity, #14
101
+ @token_bucket_rate, #15
102
+ @file_single, #16
103
+ @ec2_md_timeout, #17
104
+ @grpc_proxy, #18
105
+ 0, # arg for lambda
106
+ 1 # arg for grpc hack, hardcoded to include hack
103
107
  ]
104
108
  end
105
109
 
@@ -155,7 +159,7 @@ module AppOpticsAPM
155
159
  end
156
160
 
157
161
  def validate_token(token)
158
- if (token !~ /^[0-9a-fA-F]{64}|[0-9a-zA-Z_-]{71}$/) && ENV['APPOPTICS_COLLECTOR'] != "sslcollector:12222"
162
+ if (token !~ /^[0-9a-fA-F]{64}|[0-9a-zA-Z_-]{71}$/) && ENV['APPOPTICS_COLLECTOR'] !~ /java-collector:1222/
159
163
  masked = "#{token[0..3]}...#{token[-4..-1]}"
160
164
  AppOpticsAPM.logger.error "[appoptics_apm/oboe_options] APPOPTICS_SERVICE_KEY problem. API Token in wrong format. Masked token: #{masked}"
161
165
  return false
@@ -165,7 +169,7 @@ module AppOpticsAPM
165
169
  end
166
170
 
167
171
  def validate_transform_service_name(service_name)
168
- service_name = 'test_ssl_collector' if ENV['APPOPTICS_COLLECTOR'] == "sslcollector:12222"
172
+ service_name = 'test_ssl_collector' if ENV['APPOPTICS_COLLECTOR'] =~ /java-collector:1222/
169
173
  if service_name.empty?
170
174
  AppOpticsAPM.logger.error "[appoptics_apm/oboe_options] APPOPTICS_SERVICE_KEY problem. Service Name is missing"
171
175
  return false
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2020 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ class Profiling
6
+
7
+ def self.run
8
+ # allow enabling and disabling and setting interval interactively
9
+ return yield unless AppOpticsAPM::Config.profiling == :enabled && AppOpticsAPM.tracing?
10
+
11
+ CProfiler.run(Thread.current, AppOpticsAPM::Config.profiling_interval) do
12
+ # for some reason `return` is needed here
13
+ # this is yielded by c-code, but why it needs `return` ... ????
14
+ return yield
15
+ end
16
+ end
17
+ end
18
+ end
@@ -6,7 +6,7 @@ module AppOpticsAPM
6
6
  # This module sends the duration of the call and
7
7
  # sets the transaction_name
8
8
  #
9
- module TransactionMetrics
9
+ class TransactionMetrics
10
10
  class << self
11
11
 
12
12
  ##
@@ -20,11 +20,11 @@ module AppOpticsAPM
20
20
  attr_reader :auth_msg, :do_propagate, :status_msg, :type, :source, :rate, :xtrace
21
21
  #, :status
22
22
 
23
- def initialize(url = '', xtrace = '', options = nil)
23
+ def initialize(url = '', xtrace = nil, options = nil)
24
24
  @do_metrics = false
25
25
  @do_sample = false
26
26
  @do_propagate = true
27
- @xtrace = xtrace || ''
27
+ @xtrace = xtrace
28
28
  tracing_mode = AO_TRACING_ENABLED
29
29
 
30
30
  if AppOpticsAPM::Context.isValid
@@ -95,7 +95,7 @@ module AppOpticsAPM
95
95
  response << "auth=#{settings.auth_msg}" if @signature
96
96
  if settings.auth_ok?
97
97
  if @trigger_trace
98
- trigger_msg = !settings.xtrace.empty? && settings.type == 0 ? 'ignored' : settings.status_msg
98
+ trigger_msg = settings.xtrace && settings.type == 0 ? 'ignored' : settings.status_msg
99
99
  else
100
100
  trigger_msg = 'not-requested'
101
101
  end
@@ -107,4 +107,4 @@ module AppOpticsAPM
107
107
  end
108
108
 
109
109
  end
110
- end
110
+ end
@@ -25,7 +25,7 @@ module AppOpticsAPM
25
25
 
26
26
  AppOpticsAPM.logger.warn '********************************************************'
27
27
  AppOpticsAPM.logger.warn '* BEGIN AppOpticsAPM Support Report'
28
- AppOpticsAPM.logger.warn '* Please email the output of this report to support@appoptics.com'
28
+ AppOpticsAPM.logger.warn '* Please email the output of this report to technicalsupport@solarwinds.com'
29
29
  AppOpticsAPM.logger.warn '********************************************************'
30
30
  AppOpticsAPM.logger.warn "Ruby: #{RUBY_DESCRIPTION}"
31
31
  AppOpticsAPM.logger.warn "$0: #{$0}"
@@ -108,7 +108,7 @@ module AppOpticsAPM
108
108
 
109
109
  AppOpticsAPM.logger.warn '********************************************************'
110
110
  AppOpticsAPM.logger.warn '* END AppOpticsAPM Support Report'
111
- AppOpticsAPM.logger.warn '* Support Email: support@appoptics.com'
111
+ AppOpticsAPM.logger.warn '* Support Email: technicalsupport@solarwinds.com'
112
112
  AppOpticsAPM.logger.warn '* Github: https://github.com/librato/ruby-appoptics'
113
113
  AppOpticsAPM.logger.warn '********************************************************'
114
114
 
@@ -54,8 +54,8 @@ module AppOpticsAPM
54
54
  if ENV.key?('TRAVIS_PSQL_PASS')
55
55
  ENV['DATABASE_URL'] = "postgresql://postgres:#{ENV['TRAVIS_PSQL_PASS']}@127.0.0.1:5432/travis_ci_test"
56
56
  elsif ENV.key?('POSTGRES_USER')
57
- ENV['DATABASE_URL'] = "postgresql://#{ENV['POSTGRES_PASSWORD']}:#{ENV['POSTGRES_USER']}@#{ENV['PSQL_HOST']}:5432/travis_ci_test"
58
- # ENV['DATABASE_URL'] = "postgresql://postgres@#{ENV['PSQL_HOST']}:5432/travis_ci_test"
57
+ port = ENV.key?('POSTGRES_PORT') ? ENV['POSTGRES_PORT'] : 5432
58
+ ENV['DATABASE_URL'] = "postgresql://#{ENV['POSTGRES_PASSWORD']}:#{ENV['POSTGRES_USER']}@#{ENV['POSTGRES_HOST']}:#{port}/travis_ci_test"
59
59
  else
60
60
  ENV['DATABASE_URL'] = 'postgresql://postgres@127.0.0.1:5432/travis_ci_test'
61
61
  end
@@ -69,7 +69,8 @@ module AppOpticsAPM
69
69
  if ENV.key?('TRAVIS_MYSQL_PASS')
70
70
  ENV['DATABASE_URL'] = "mysql://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test"
71
71
  elsif ENV.key?('DOCKER_MYSQL_PASS')
72
- ENV['DATABASE_URL'] = "mysql://root:#{ENV['DOCKER_MYSQL_PASS']}@#{ENV['MYSQL_HOST']}:3306/travis_ci_test"
72
+ port = ENV.key?('MYSQL_PORT') ? ENV['MYSQL_PORT'] : 3306
73
+ ENV['DATABASE_URL'] = "mysql://root:#{ENV['DOCKER_MYSQL_PASS']}@#{ENV['MYSQL_HOST']}:#{port}/travis_ci_test"
73
74
  else
74
75
  ENV['DATABASE_URL'] = 'mysql://root@127.0.0.1:3306/travis_ci_test'
75
76
  end
@@ -275,7 +275,7 @@ module AppOpticsAPM
275
275
 
276
276
  # oboe not loaded yet, can't use oboe_api function to read oboe VERSION
277
277
  clib_version_file = File.join(Gem::Specification.find_by_name('appoptics_apm').gem_dir, 'ext', 'oboe_metal', 'src', 'VERSION')
278
- platform_info['Ruby.AppOpticsExtension.Version'] = File.read(clib_version_file).chomp
278
+ platform_info['Ruby.AppOpticsExtension.Version'] = File.read(clib_version_file).strip
279
279
  platform_info['RubyHeroku.AppOpticsAPM.Version'] = AppOpticsAPMHeroku::Version::STRING if defined?(AppOpticsAPMHeroku)
280
280
  platform_info['Ruby.TraceMode.Version'] = AppOpticsAPM::Config[:tracing_mode]
281
281
 
@@ -6,9 +6,9 @@ module AppOpticsAPM
6
6
  # The current version of the gem. Used mainly by
7
7
  # appoptics_apm.gemspec during gem build process
8
8
  module Version
9
- MAJOR = 4 # breaking,
10
- MINOR = 12 # feature,
11
- PATCH = 2 # fix => BFF
9
+ MAJOR = 4 # breaking,
10
+ MINOR = 13 # feature,
11
+ PATCH = 0 # fix => BFF
12
12
  PRE = nil
13
13
 
14
14
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
@@ -7,7 +7,7 @@ module AppOpticsAPM
7
7
  # value
8
8
  #
9
9
  # TODO add unit tests
10
- module XTrace
10
+ class XTrace
11
11
  class << self
12
12
  ##
13
13
  # AppOpticsAPM::XTrace.valid?
data/lib/appoptics_apm.rb CHANGED
@@ -28,7 +28,7 @@ begin
28
28
  AppOpticsAPM.logger.warn "AppOptics warning: Platform #{RUBY_PLATFORM} not yet supported."
29
29
  AppOpticsAPM.logger.warn 'see: https://docs.appoptics.com/kb/apm_tracing/supported_platforms/'
30
30
  AppOpticsAPM.logger.warn 'Tracing disabled.'
31
- AppOpticsAPM.logger.warn 'Contact support@appoptics.com if this is unexpected.'
31
+ AppOpticsAPM.logger.warn 'Contact technicalsupport@solarwinds.com if this is unexpected.'
32
32
  AppOpticsAPM.logger.warn '==================================================================='
33
33
  end
34
34
  rescue LoadError => e
@@ -46,6 +46,7 @@ begin
46
46
 
47
47
  if AppOpticsAPM.loaded
48
48
  require 'appoptics_apm/instrumentation'
49
+ require 'appoptics_apm/support/profiling'
49
50
  require 'appoptics_apm/support/transaction_metrics'
50
51
  require 'appoptics_apm/support/x_trace_options'
51
52
 
@@ -62,6 +63,7 @@ begin
62
63
  AppOpticsAPM.logger.warn '=============================================================='
63
64
  require 'appoptics_apm/noop/context'
64
65
  require 'appoptics_apm/noop/metadata'
66
+ require 'appoptics_apm/noop/profiling'
65
67
  end
66
68
 
67
69
  # Load Ruby module last. If there is no framework detected,