appoptics_apm 4.12.2 → 4.13.0

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 (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
@@ -22,14 +22,13 @@ ext_dir = File.expand_path(File.dirname(__FILE__))
22
22
 
23
23
  # Check if we're running in JRuby
24
24
  jruby = defined?(JRUBY_VERSION) ? true : false
25
-
26
25
  # Set the mkmf lib paths so we have no issues linking to
27
26
  # the AppOpticsAPM libs.
28
27
  ao_lib_dir = File.join(ext_dir, 'lib')
29
28
  ao_include = File.join(ext_dir, 'src')
30
29
 
31
30
  # Download the appropriate liboboe from S3(via rake for testing) or files.appoptics.com (production)
32
- version = File.read(File.join(ao_include, 'VERSION')).chomp
31
+ version = File.read(File.join(ao_include, 'VERSION')).strip
33
32
  if ENV['APPOPTICS_FROM_S3'].to_s.downcase == 'true'
34
33
  ao_path = File.join('https://rc-files-t2.s3-us-west-2.amazonaws.com/c-lib/', version)
35
34
  puts 'Fetching c-lib from S3'
@@ -39,12 +38,7 @@ end
39
38
 
40
39
  ao_arch = 'x86_64'
41
40
  if File.exist?('/etc/alpine-release')
42
-
43
- if RUBY_VERSION < '2.5.0'
44
- version = open('/etc/alpine-release').read.chomp
45
- else
46
- version = URI.open('/etc/alpine-release').read.chomp
47
- end
41
+ version = File.read('/etc/alpine-release').strip
48
42
 
49
43
  ao_arch =
50
44
  if Gem::Version.new(version) < Gem::Version.new('3.9')
@@ -56,34 +50,31 @@ end
56
50
 
57
51
  ao_clib = "liboboe-1.0-#{ao_arch}.so.0.0.0"
58
52
  ao_item = File.join(ao_path, ao_clib)
59
- ao_checksum_item = "#{ao_item}.sha256"
53
+ ao_checksum_file = File.join(ao_lib_dir, "#{ao_clib}.sha256")
60
54
  clib = File.join(ao_lib_dir, ao_clib)
61
55
 
62
56
  retries = 3
63
57
  success = false
64
58
  while retries > 0
65
59
  begin
66
- # download
67
- if RUBY_VERSION < '2.5.0'
68
- download = open(ao_item, 'rb')
69
- checksum = open(ao_checksum_item, 'r').read.chomp
70
- else
71
- download = URI.open(ao_item, 'rb')
72
- checksum = URI.open(ao_checksum_item, 'r').read.chomp
73
- end
60
+ download = RUBY_VERSION < '2.5.0' ? open(ao_item, 'rb') : URI.open(ao_item, 'rb')
74
61
  IO.copy_stream(download, clib)
62
+
75
63
  clib_checksum = Digest::SHA256.file(clib).hexdigest
76
64
  download.close
65
+ checksum = File.read(ao_checksum_file).strip
77
66
 
78
- # verify_checksum
67
+ # unfortunately these messages only show if the install command is run
68
+ # with the `--verbose` flag
79
69
  if clib_checksum != checksum
80
70
  $stderr.puts '== ERROR ================================================================='
81
- $stderr.puts 'Checksum Verification failed for the c-extension of the appoptics_apm gem.'
82
- $stderr.puts 'appoptics_apm will not instrument the code. No tracing will occur.'
83
- $stderr.puts 'Contact support@appoptics.com if the problem persists.'
71
+ $stderr.puts 'Checksum Verification failed for the c-extension of the appoptics_apm gem'
72
+ $stderr.puts 'Installation cannot continue'
73
+ $stderr.puts "\nChecksum packaged with gem: #{checksum}"
74
+ $stderr.puts "Checksum calculated from lib: #{clib_checksum}"
75
+ $stderr.puts 'Contact technicalsupport@solarwinds.com if the problem persists'
84
76
  $stderr.puts '=========================================================================='
85
- create_makefile('oboe_noop', 'noop')
86
- retries = 0
77
+ exit 1
87
78
  else
88
79
  success = true
89
80
  retries = 0
@@ -95,7 +86,7 @@ while retries > 0
95
86
  $stderr.puts '== ERROR =========================================================='
96
87
  $stderr.puts 'Download of the c-extension for the appoptics_apm gem failed.'
97
88
  $stderr.puts 'appoptics_apm will not instrument the code. No tracing will occur.'
98
- $stderr.puts 'Contact support@appoptics.com if the problem persists.'
89
+ $stderr.puts 'Contact technicalsupport@solarwinds.com if the problem persists.'
99
90
  $stderr.puts "error: #{ao_item}\n#{e.message}"
100
91
  $stderr.puts '==================================================================='
101
92
  create_makefile('oboe_noop', 'noop')
@@ -128,17 +119,20 @@ if success
128
119
  $CFLAGS << " #{ENV['CFLAGS']}"
129
120
  # $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11"
130
121
  # TODO for debugging: -pg -gdwarf-2, remove for production
131
- # $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11 -pg -gdwarf-2 -I$$ORIGIN/../ext/oboe_metal/include -I$$ORIGIN/../ext/oboe_metal/src"
132
- $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11 -I$$ORIGIN/../ext/oboe_metal/include"
122
+ # -pg does not work on alpine https://www.openwall.com/lists/musl/2014/11/05/2
123
+ $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11 -gdwarf-2 -I$$ORIGIN/../ext/oboe_metal/include -I$$ORIGIN/../ext/oboe_metal/src"
124
+ # $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11 -I$$ORIGIN/../ext/oboe_metal/include"
133
125
  $LIBS << " #{ENV['LIBS']}"
134
- $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib' -pg -lrt"
135
- # $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib'"
126
+
127
+ # use "z,defs" to see what happens during linking
128
+ # $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib,-z,defs' -lrt"
129
+ $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib' -lrt"
136
130
  $CXXFLAGS += " -std=c++11 "
137
131
 
138
132
  # ____ include debug info, comment out when not debugging
139
133
  # ____ -pg -> profiling info for gprof
140
- # CONFIG["debugflags"] = "-ggdb3 -pg"
141
- # CONFIG["optflags"] = "-O0"
134
+ CONFIG["debugflags"] = "-ggdb3 "
135
+ CONFIG["optflags"] = "-O0"
142
136
 
143
137
  create_makefile('libappoptics_apm', 'src')
144
138
 
@@ -150,7 +144,7 @@ if success
150
144
  else
151
145
  $stderr.puts 'Could not find a matching c-library. No tracing will occur.'
152
146
  end
153
- $stderr.puts 'Contact support@appoptics.com if the problem persists.'
147
+ $stderr.puts 'Contact technicalsupport@solarwinds.com if the problem persists.'
154
148
  $stderr.puts '=================================================================='
155
149
  create_makefile('oboe_noop', 'noop')
156
150
  end
@@ -0,0 +1 @@
1
+ af7d764a88cec323940fc6040947f2dcf8041c389744bdfc46b7f2fe0a465dab
@@ -0,0 +1 @@
1
+ 092e232d0e1aa1826b77c98d96f7bb2db39058c9bec3e2c0387cc6fb51b5b83c
@@ -0,0 +1,6 @@
1
+
2
+ oboe_api.hpp and oboe_api.cpp are copied here from the oboe repo during install
3
+
4
+ it is best to edit these file in the oboe repo and use the OBOE_WIP=true env
5
+ var to include the development version while they aren't deploy to s3.
6
+
@@ -1 +1,2 @@
1
- 10.1.0
1
+ 10.2.0
2
+
@@ -0,0 +1,246 @@
1
+ // Copyright (c) 2021 SolarWinds, LLC.
2
+ // All rights reserved.
3
+
4
+ #include "frames.h"
5
+
6
+ using namespace std;
7
+
8
+ unordered_map<VALUE, FrameData> cached_frames;
9
+
10
+ // in theory the mutex is not needed, because Ruby does not context switch
11
+ // while executing a foreign function, but will this always hold true?
12
+ mutex cached_frames_mutex;
13
+
14
+ void Frames::reserve_cached_frames() {
15
+ lock_guard<mutex> guard(cached_frames_mutex);
16
+ // unordered_maps grow automatically, but it starts at 1 and then
17
+ // doubles when it is full, so lets avoid the warmup
18
+ cached_frames.reserve(500); // it will round to a prime number: 503
19
+ }
20
+
21
+ void Frames::clear_cached_frames() {
22
+ lock_guard<mutex> guard(cached_frames_mutex);
23
+ // unordered_maps grow automatically, but it starts at 1 and then
24
+ // doubles when it is full, so lets avoid the warmup
25
+ cached_frames.clear();
26
+ }
27
+
28
+ // this is a private function
29
+ int Frames::cache_frame(VALUE frame) {
30
+ VALUE val;
31
+ FrameData data;
32
+
33
+ // only cache it if it does not exist
34
+ if (cached_frames.count(frame) == 0) {
35
+ val = rb_profile_frame_label(frame); // returns method or block
36
+ if (RB_TYPE_P(val, T_STRING))
37
+ data.method = RSTRING_PTR(val);
38
+
39
+ if (data.method.rfind("block ", 0) == 0) {
40
+ // we don't need more info if it is a block
41
+ // we ignore block level info because they make things messy
42
+ lock_guard<mutex> guard(cached_frames_mutex);
43
+ cached_frames.insert({frame, data});
44
+ return 0;
45
+ }
46
+
47
+ val = rb_profile_frame_classpath(frame); // returns class or nil
48
+ if (RB_TYPE_P(val, T_STRING)) data.klass = RSTRING_PTR(val);
49
+
50
+ val = rb_profile_frame_absolute_path(frame); // returns file, use rb_profile_frame_path() if nil
51
+ if (!RB_TYPE_P(val, T_STRING)) val = rb_profile_frame_path(frame);
52
+ if (RB_TYPE_P(val, T_STRING)) data.file = RSTRING_PTR(val);
53
+
54
+ // Ruby 3 reports <cfunc>, but the linenumbers are bogus
55
+ // the default line number is 0
56
+ if (!data.file.compare("<cfunc>") == 0) {
57
+ val = rb_profile_frame_first_lineno(frame); // returns line number
58
+ if (RB_TYPE_P(val, T_FIXNUM)) {
59
+ data.lineno = NUM2INT(val);
60
+ }
61
+ }
62
+ lock_guard<mutex> guard(cached_frames_mutex);
63
+ cached_frames.insert({frame, data});
64
+ }
65
+ return 0;
66
+ }
67
+
68
+ // all frames in frames_buffer must be in cached_frames
69
+ // before calling this function
70
+ // we are saving the check for better performance
71
+ int Frames::collect_frame_data(VALUE *frames_buffer, int num, vector<FrameData> &frame_data) {
72
+ if (num == 1) {
73
+ if (frames_buffer[0] == PR_IN_GC) {
74
+ FrameData data;
75
+ data.method = "GARBAGE COLLECTION";
76
+ frame_data.push_back(data);
77
+ return 0;
78
+ } else if (frames_buffer[0] == PR_OTHER_THREAD) {
79
+ FrameData data;
80
+ data.method = "OTHER THREADS";
81
+ frame_data.push_back(data);
82
+ return 0;
83
+ }
84
+ }
85
+
86
+ for (int i = 0; i < num; i++) {
87
+ VALUE frame = frames_buffer[i];
88
+ frame_data.push_back(cached_frames[frame]);
89
+ }
90
+ return 0;
91
+ }
92
+
93
+ /////
94
+ // For the sake of efficiency this function filters uninteresting frames and
95
+ // does the caching of frames at the same time
96
+ //
97
+ // in-place removal of
98
+ // - frames with line number == 0
99
+ // - all but last of repeated frames
100
+ // - "block" frames (they are confusing) <- revisit
101
+ // and cache uncached frames
102
+ int Frames::remove_garbage(VALUE *frames_buffer, int num) {
103
+ if (num == 1 && (frames_buffer[0] == PR_OTHER_THREAD || frames_buffer[0] == PR_IN_GC))
104
+ return 1;
105
+
106
+ // TODO decide what to do with <cfunc> frames in Ruby 3
107
+
108
+ // 1) ignore top frames where the line number is 0
109
+ // does that mean there is no line number???
110
+ bool found = true;
111
+
112
+ while (found && num > 0) {
113
+ if (cached_frames.count(frames_buffer[num - 1]) == 1) {
114
+ found = (cached_frames[frames_buffer[num - 1]].lineno == 0);
115
+ if (found) num--;
116
+ } else {
117
+ VALUE val = rb_profile_frame_first_lineno(frames_buffer[num - 1]);
118
+ found = (!RB_TYPE_P(val, T_FIXNUM) || !NUM2INT(val));
119
+ if (found) {
120
+ lock_guard<mutex> guard(cached_frames_mutex);
121
+ cached_frames[frames_buffer[num - 1]].lineno = 0;
122
+ num--;
123
+ }
124
+ }
125
+ }
126
+
127
+ // 2) remove all repeated frames, keep the last one
128
+ int count = 0;
129
+ int k = 0;
130
+ found = false;
131
+ while (count < num - k) {
132
+ // is this frame repeated ahead?
133
+ // if so we will replace it with the next one in line
134
+ for (int j = count + k + 1; j < num; j++) {
135
+ if (frames_buffer[count] == frames_buffer[j]) {
136
+ found = true;
137
+ break;
138
+ }
139
+ }
140
+
141
+ if (found) {
142
+ // if we found this frame again later in the snapshot
143
+ // we are going to override this one
144
+ // but not if this is going beyond the boundary
145
+ k++;
146
+ if (count + k < num - 1) frames_buffer[count] = frames_buffer[count + k];
147
+ } else {
148
+ count++;
149
+ frames_buffer[count] = frames_buffer[count + k];
150
+ }
151
+ found = false;
152
+ }
153
+
154
+ // 3) remove "block" frames, they are reported inconsistently and mess up
155
+ // the profile in the dashboard
156
+ // 4) while we are at it we also cache all the frames
157
+ // these 2 are combined so we don't have to run this loop twice
158
+ num = count;
159
+ count = 0, k = 0;
160
+ string method;
161
+
162
+ while (count < num - k) {
163
+ frames_buffer[count] = frames_buffer[count + k];
164
+ cache_frame(frames_buffer[count]);
165
+ method = cached_frames[frames_buffer[count]].method;
166
+
167
+ // TODO revisit need to remove block frames, they only appear when the Ruby
168
+ // ____ script is not started with a method and has blocks outside of the
169
+ // ____ methods called and sometimes inside of rack
170
+ if (method.rfind("block ", 0) == 0) {
171
+ k++;
172
+ } else {
173
+ count++;
174
+ }
175
+ }
176
+ return count;
177
+ }
178
+
179
+ // returns the number of the matching frames
180
+ int Frames::num_matching(VALUE *frames_buffer, int num,
181
+ VALUE *prev_frames_buffer, int prev_num) {
182
+ int i;
183
+ int min = std::min(num, prev_num);
184
+
185
+ for (i = 0; i < min; i++) {
186
+ // we have to start from the "top"
187
+ if (frames_buffer[num - 1 - i] != prev_frames_buffer[prev_num - 1 - i]) {
188
+ return i;
189
+ }
190
+ }
191
+ return i;
192
+ }
193
+
194
+ /////////////////////// DEBUGGING HELPER FUNCTIONS /////////////////////////////
195
+ // helper function to print frame from ruby pointers to frame
196
+ void Frames::print_raw_frame_info(VALUE frame) {
197
+ if (frame == PR_IN_GC || frame == PR_OTHER_THREAD) {
198
+ return;
199
+ }
200
+
201
+ VALUE val;
202
+ int lineno;
203
+ string file, klass, method;
204
+
205
+ val = rb_profile_frame_first_lineno(frame); // returns line number
206
+ if (RB_TYPE_P(val, T_FIXNUM)) lineno = NUM2INT(val);
207
+
208
+ val = rb_profile_frame_classpath(frame); // returns class or nil
209
+ if (RB_TYPE_P(val, T_STRING)) klass = RSTRING_PTR(val);
210
+
211
+ val = rb_profile_frame_absolute_path(frame); // returns file, use rb_profile_frame_path() if nil
212
+ if (!RB_TYPE_P(val, T_STRING)) val = rb_profile_frame_path(frame);
213
+ if (RB_TYPE_P(val, T_STRING)) file = RSTRING_PTR(val);
214
+
215
+ val = rb_profile_frame_label(frame); // returns method or block
216
+ if (RB_TYPE_P(val, T_STRING)) method = RSTRING_PTR(val);
217
+
218
+ cout << " " << frame << " "
219
+ << "L: " << lineno << " "
220
+ << "F: " << file << " "
221
+ << "C: " << klass << " "
222
+ << "M: " << method << endl;
223
+ }
224
+
225
+ void Frames::print_all_raw_frames(VALUE *frames_buffer, int num) {
226
+ for (int i = 0; i < num; i++) {
227
+ print_raw_frame_info(frames_buffer[i]);
228
+ }
229
+ }
230
+
231
+ // helper function to print frame info
232
+ void Frames::print_frame_info(VALUE frame) {
233
+ if (cached_frames.find(frame) != cached_frames.end())
234
+ std::cout << cached_frames[frame].lineno << " "
235
+ << cached_frames[frame].file << " "
236
+ << cached_frames[frame].klass << " "
237
+ << cached_frames[frame].method << std::endl;
238
+ }
239
+
240
+ // helper function for printing the cached frames
241
+ void Frames::print_cached_frames() {
242
+ std::cout << "cached_frames contains:" << endl;
243
+ for (auto it = cached_frames.cbegin(); it != cached_frames.cend(); ++it)
244
+ std::cout << " " << it->first << " - " << it->second.method << ":" << it->second.lineno << endl; // cannot modify *it
245
+ std::cout << std::endl;
246
+ }
@@ -0,0 +1,40 @@
1
+ // Copyright (c) 2021 SolarWinds, LLC.
2
+ // All rights reserved.
3
+
4
+ #ifndef FRAMES_H
5
+ #define FRAMES_H
6
+
7
+ #include <vector>
8
+
9
+ #include <mutex>
10
+ #include <unordered_map>
11
+
12
+ #include <ruby/ruby.h>
13
+ #include <ruby/debug.h>
14
+
15
+ #include "profiling.h"
16
+ #include "oboe_api.hpp"
17
+
18
+ using namespace std;
19
+
20
+ class Frames {
21
+ public:
22
+ static void clear_cached_frames();
23
+ static void reserve_cached_frames();
24
+ static int collect_frame_data(VALUE *frames_buffer, int num, vector<FrameData> &frame_data);
25
+ static int remove_garbage(VALUE *frames_buffer, int num);
26
+ static int num_matching(VALUE *frames_buffer, int num,
27
+ VALUE *prev_frames_buffer, int prev_num);
28
+
29
+ private:
30
+ static int cache_frame(VALUE frame);
31
+
32
+ // Debugging helper functions
33
+ public:
34
+ static void print_raw_frame_info(VALUE frame);
35
+ static void print_all_raw_frames(VALUE *frames_buffer, int num);
36
+ static void print_frame_info(VALUE frame);
37
+ static void print_cached_frames();
38
+ };
39
+
40
+ #endif //FRAMES_H
@@ -1,3 +1,6 @@
1
+ // Copyright (c) 2019 SolarWinds, LLC.
2
+ // All rights reserved.
3
+
1
4
  #include <iostream>
2
5
 
3
6
  #ifdef __cplusplus
@@ -6,13 +9,11 @@ extern "C" {
6
9
 
7
10
  void Init_oboe_metal(void);
8
11
 
9
- //void Init_profiling(void);
12
+ void Init_profiling(void);
10
13
 
11
14
  void Init_libappoptics_apm() {
12
15
  Init_oboe_metal();
13
- // std::cout << "*** oboe_metal initialized ***" << std::endl;
14
- // Init_profiling();
15
- // std::cout << "*** profiling intitialized ***" << std::endl;
16
+ Init_profiling();
16
17
  }
17
18
 
18
19
  #ifdef __cplusplus