solarwinds_apm 5.0.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.
- checksums.yaml +7 -0
- data/.dockerignore +5 -0
- data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
- data/.github/workflows/build_and_release_gem.yml +112 -0
- data/.github/workflows/build_for_packagecloud.yml +70 -0
- data/.github/workflows/docker-images.yml +47 -0
- data/.github/workflows/run_cpluplus_tests.yml +73 -0
- data/.github/workflows/run_tests.yml +155 -0
- data/.github/workflows/scripts/test_install.rb +23 -0
- data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
- data/.github/workflows/test_on_4_linux.yml +161 -0
- data/.gitignore +39 -0
- data/.rubocop.yml +29 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +31 -0
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/README.md +383 -0
- data/bin/solarwinds_apm_config +15 -0
- data/examples/prepend.rb +13 -0
- data/examples/sdk_examples.rb +158 -0
- data/ext/oboe_metal/README.md +69 -0
- data/ext/oboe_metal/extconf.rb +141 -0
- data/ext/oboe_metal/extconf_local.rb +75 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/noop/noop.c +8 -0
- data/ext/oboe_metal/src/README.md +6 -0
- data/ext/oboe_metal/src/VERSION +2 -0
- data/ext/oboe_metal/src/bson/bson.h +220 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/frames.cc +247 -0
- data/ext/oboe_metal/src/frames.h +40 -0
- data/ext/oboe_metal/src/init_solarwinds_apm.cc +21 -0
- data/ext/oboe_metal/src/logging.cc +95 -0
- data/ext/oboe_metal/src/logging.h +35 -0
- data/ext/oboe_metal/src/oboe.h +1169 -0
- data/ext/oboe_metal/src/oboe_api.cpp +658 -0
- data/ext/oboe_metal/src/oboe_api.hpp +433 -0
- data/ext/oboe_metal/src/oboe_debug.h +59 -0
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +7562 -0
- data/ext/oboe_metal/src/profiling.cc +435 -0
- data/ext/oboe_metal/src/profiling.h +78 -0
- data/ext/oboe_metal/test/CMakeLists.txt +53 -0
- data/ext/oboe_metal/test/FindGMock.cmake +43 -0
- data/ext/oboe_metal/test/README.md +56 -0
- data/ext/oboe_metal/test/frames_test.cc +164 -0
- data/ext/oboe_metal/test/profiling_test.cc +93 -0
- data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
- data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
- data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
- data/ext/oboe_metal/test/test.h +11 -0
- data/ext/oboe_metal/test/test_main.cc +32 -0
- data/init.rb +4 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +172 -0
- data/lib/rails/generators/solarwinds_apm/install_generator.rb +47 -0
- data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +424 -0
- data/lib/solarwinds_apm/api/layerinit.rb +41 -0
- data/lib/solarwinds_apm/api/logging.rb +356 -0
- data/lib/solarwinds_apm/api/memcache.rb +37 -0
- data/lib/solarwinds_apm/api/metrics.rb +63 -0
- data/lib/solarwinds_apm/api/util.rb +98 -0
- data/lib/solarwinds_apm/api.rb +21 -0
- data/lib/solarwinds_apm/base.rb +160 -0
- data/lib/solarwinds_apm/config.rb +301 -0
- data/lib/solarwinds_apm/frameworks/grape.rb +96 -0
- data/lib/solarwinds_apm/frameworks/padrino.rb +78 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller.rb +100 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_view.rb +88 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/active_record.rb +26 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +22 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +103 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/logger_formatters.rb +14 -0
- data/lib/solarwinds_apm/frameworks/rails.rb +100 -0
- data/lib/solarwinds_apm/frameworks/sinatra.rb +96 -0
- data/lib/solarwinds_apm/inst/bunny-client.rb +157 -0
- data/lib/solarwinds_apm/inst/bunny-consumer.rb +102 -0
- data/lib/solarwinds_apm/inst/curb.rb +288 -0
- data/lib/solarwinds_apm/inst/dalli.rb +89 -0
- data/lib/solarwinds_apm/inst/delayed_job.rb +100 -0
- data/lib/solarwinds_apm/inst/excon.rb +113 -0
- data/lib/solarwinds_apm/inst/faraday.rb +96 -0
- data/lib/solarwinds_apm/inst/graphql.rb +206 -0
- data/lib/solarwinds_apm/inst/grpc_client.rb +147 -0
- data/lib/solarwinds_apm/inst/grpc_server.rb +119 -0
- data/lib/solarwinds_apm/inst/httpclient.rb +181 -0
- data/lib/solarwinds_apm/inst/logger_formatter.rb +46 -0
- data/lib/solarwinds_apm/inst/logging_log_event.rb +24 -0
- data/lib/solarwinds_apm/inst/lumberjack_formatter.rb +9 -0
- data/lib/solarwinds_apm/inst/memcached.rb +86 -0
- data/lib/solarwinds_apm/inst/mongo.rb +246 -0
- data/lib/solarwinds_apm/inst/mongo2.rb +225 -0
- data/lib/solarwinds_apm/inst/moped.rb +466 -0
- data/lib/solarwinds_apm/inst/net_http.rb +60 -0
- data/lib/solarwinds_apm/inst/rack.rb +217 -0
- data/lib/solarwinds_apm/inst/rack_cache.rb +35 -0
- data/lib/solarwinds_apm/inst/redis.rb +273 -0
- data/lib/solarwinds_apm/inst/resque.rb +129 -0
- data/lib/solarwinds_apm/inst/rest-client.rb +43 -0
- data/lib/solarwinds_apm/inst/sequel.rb +241 -0
- data/lib/solarwinds_apm/inst/sidekiq-client.rb +63 -0
- data/lib/solarwinds_apm/inst/sidekiq-worker.rb +64 -0
- data/lib/solarwinds_apm/inst/typhoeus.rb +90 -0
- data/lib/solarwinds_apm/instrumentation.rb +22 -0
- data/lib/solarwinds_apm/loading.rb +65 -0
- data/lib/solarwinds_apm/logger.rb +14 -0
- data/lib/solarwinds_apm/noop/README.md +9 -0
- data/lib/solarwinds_apm/noop/context.rb +26 -0
- data/lib/solarwinds_apm/noop/metadata.rb +25 -0
- data/lib/solarwinds_apm/noop/profiling.rb +21 -0
- data/lib/solarwinds_apm/oboe_init_options.rb +191 -0
- data/lib/solarwinds_apm/ruby.rb +35 -0
- data/lib/solarwinds_apm/sdk/current_trace_info.rb +123 -0
- data/lib/solarwinds_apm/sdk/custom_metrics.rb +94 -0
- data/lib/solarwinds_apm/sdk/logging.rb +37 -0
- data/lib/solarwinds_apm/sdk/trace_context_headers.rb +69 -0
- data/lib/solarwinds_apm/sdk/tracing.rb +432 -0
- data/lib/solarwinds_apm/support/profiling.rb +22 -0
- data/lib/solarwinds_apm/support/trace_context.rb +53 -0
- data/lib/solarwinds_apm/support/trace_state.rb +69 -0
- data/lib/solarwinds_apm/support/trace_string.rb +89 -0
- data/lib/solarwinds_apm/support/transaction_metrics.rb +67 -0
- data/lib/solarwinds_apm/support/transaction_settings.rb +233 -0
- data/lib/solarwinds_apm/support/x_trace_options.rb +113 -0
- data/lib/solarwinds_apm/support.rb +12 -0
- data/lib/solarwinds_apm/support_report.rb +113 -0
- data/lib/solarwinds_apm/test.rb +165 -0
- data/lib/solarwinds_apm/thread_local.rb +26 -0
- data/lib/solarwinds_apm/util.rb +334 -0
- data/lib/solarwinds_apm/version.rb +17 -0
- data/lib/solarwinds_apm.rb +72 -0
- data/log/.keep +0 -0
- data/log/postgresql/.keep +0 -0
- data/solarwinds_apm.gemspec +52 -0
- data/yardoc_frontpage.md +24 -0
- metadata +228 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
#include <string.h>
|
|
4
|
+
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
|
|
7
|
+
#include "../src/profiling.h"
|
|
8
|
+
#include "../src/frames.h"
|
|
9
|
+
#include "gtest/gtest.h"
|
|
10
|
+
#include "ruby/debug.h"
|
|
11
|
+
#include "ruby/ruby.h"
|
|
12
|
+
#include "test.h"
|
|
13
|
+
|
|
14
|
+
extern unordered_map<VALUE, FrameData> cached_frames;
|
|
15
|
+
|
|
16
|
+
static VALUE test_frames[BUF_SIZE];
|
|
17
|
+
static int test_lines[BUF_SIZE];
|
|
18
|
+
int test_num;
|
|
19
|
+
|
|
20
|
+
static int ruby_version;
|
|
21
|
+
|
|
22
|
+
VALUE RubyCallsFrames::c_get_frames() {
|
|
23
|
+
test_num = rb_profile_frames(1, sizeof(test_frames) / sizeof(VALUE), test_frames, test_lines);
|
|
24
|
+
return Qnil;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
void Init_RubyCallsFrames() {
|
|
28
|
+
static VALUE cTest = rb_define_module("RubyCalls");
|
|
29
|
+
rb_define_singleton_method(cTest, "get_frames", reinterpret_cast<VALUE (*)(...)>(RubyCallsFrames::c_get_frames), 0);
|
|
30
|
+
|
|
31
|
+
VALUE result;
|
|
32
|
+
result = rb_eval_string("RUBY_VERSION[0].to_i");
|
|
33
|
+
ruby_version = NUM2INT(result);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
TEST(Frames, reserve_cached_frames) {
|
|
37
|
+
// it should only reserve once used during init
|
|
38
|
+
// unordered_map grows automatically
|
|
39
|
+
cached_frames.clear();
|
|
40
|
+
|
|
41
|
+
Frames::reserve_cached_frames();
|
|
42
|
+
int bucket_count = cached_frames.bucket_count();
|
|
43
|
+
|
|
44
|
+
Frames::reserve_cached_frames();
|
|
45
|
+
EXPECT_EQ(bucket_count, cached_frames.bucket_count());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
TEST(Frames, collect_frame_data) {
|
|
49
|
+
rb_eval_string("TestMe::Snapshot::all_kinds");
|
|
50
|
+
|
|
51
|
+
int num = Frames::remove_garbage(test_frames, test_num);
|
|
52
|
+
|
|
53
|
+
vector<FrameData> data;
|
|
54
|
+
// Ruby 3 reports a <cfunc>, before the "take_snapshot" method
|
|
55
|
+
// we have to adjust the index of the trace we are checking
|
|
56
|
+
int i = ruby_version == 2 ? 0 : 1;
|
|
57
|
+
Frames::collect_frame_data(test_frames, i + 1, data);
|
|
58
|
+
|
|
59
|
+
EXPECT_EQ("take_snapshot", data[i].method) << "method name incorrect";
|
|
60
|
+
EXPECT_EQ("TestMe::Snapshot", data[i].klass) << "klass name incorrect";
|
|
61
|
+
std::size_t found = data[i].file.find("ext/oboe_metal/test/ruby_test_helper.rb");
|
|
62
|
+
EXPECT_EQ(data[i].file.length() - 39, found)
|
|
63
|
+
<< "filename incorrect " << found << " " << data[i].file.length();
|
|
64
|
+
EXPECT_EQ(7, data[i].lineno) << "line number incorrect";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
TEST(Frames, remove_garbage) {
|
|
68
|
+
// run some Ruby code and get a snapshot
|
|
69
|
+
rb_eval_string("TestMe::Snapshot::all_kinds");
|
|
70
|
+
|
|
71
|
+
int num = Frames::remove_garbage(test_frames, test_num);
|
|
72
|
+
|
|
73
|
+
int expected = (ruby_version == 2) ? 7 : 9;
|
|
74
|
+
EXPECT_EQ(expected, num)
|
|
75
|
+
<< "wrong number of expected frames after remove_garbage";
|
|
76
|
+
// check no lineno 0 frame at top
|
|
77
|
+
VALUE val;
|
|
78
|
+
int i = (ruby_version == 2) ? 0 : 1;
|
|
79
|
+
val = rb_profile_frame_first_lineno(test_frames[i]); // returns line number
|
|
80
|
+
if (RB_TYPE_P(val, T_FIXNUM)) {
|
|
81
|
+
EXPECT_NE(0, NUM2INT(val))
|
|
82
|
+
<< "the frame with linenumber 0 was not removed";
|
|
83
|
+
} else {
|
|
84
|
+
EXPECT_TRUE(false) << " ************ line number not an int **********";
|
|
85
|
+
}
|
|
86
|
+
// check no repeated frames
|
|
87
|
+
for (i = 0; i < num; i++)
|
|
88
|
+
for (int j = i + 1; j < num; j++)
|
|
89
|
+
EXPECT_NE(test_frames[i], test_frames[j])
|
|
90
|
+
<< "not all repeated frames were removed";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
TEST(Frames, num_matching) {
|
|
94
|
+
VALUE a[BUF_SIZE];
|
|
95
|
+
VALUE b[BUF_SIZE];
|
|
96
|
+
|
|
97
|
+
int a_num = 0;
|
|
98
|
+
int b_num = 0;
|
|
99
|
+
EXPECT_EQ(0, Frames::num_matching(a, a_num, b, b_num))
|
|
100
|
+
<< "* empty frames array should have 0 matches";
|
|
101
|
+
|
|
102
|
+
a[0] = (VALUE)11;
|
|
103
|
+
a[1] = (VALUE)12;
|
|
104
|
+
a[2] = (VALUE)13;
|
|
105
|
+
b[0] = (VALUE)11;
|
|
106
|
+
b[1] = (VALUE)12;
|
|
107
|
+
b[2] = (VALUE)13;
|
|
108
|
+
a_num = 3;
|
|
109
|
+
b_num = 3;
|
|
110
|
+
EXPECT_EQ(3, Frames::num_matching(a, a_num, b, b_num))
|
|
111
|
+
<< "* equal frames array should have matched";
|
|
112
|
+
|
|
113
|
+
b[1] = (VALUE)222;
|
|
114
|
+
EXPECT_EQ(1, Frames::num_matching(a, a_num, b, b_num))
|
|
115
|
+
<< "* only one should match for same length but different content";
|
|
116
|
+
|
|
117
|
+
b[1] = (VALUE)12;
|
|
118
|
+
a[3] = 14;
|
|
119
|
+
a_num = 4;
|
|
120
|
+
EXPECT_EQ(0, Frames::num_matching(a, a_num, b, b_num))
|
|
121
|
+
<< "* different length, frames NOT matching from the end";
|
|
122
|
+
|
|
123
|
+
a[0] = 10;
|
|
124
|
+
a[1] = 11;
|
|
125
|
+
a[2] = 12;
|
|
126
|
+
a[3] = 13;
|
|
127
|
+
EXPECT_EQ(3, Frames::num_matching(a, a_num, b, b_num))
|
|
128
|
+
<< "* different length, frames matching from the end";
|
|
129
|
+
|
|
130
|
+
b[0] = (VALUE)18;
|
|
131
|
+
b[1] = (VALUE)19;
|
|
132
|
+
b[2] = (VALUE)11;
|
|
133
|
+
b[3] = (VALUE)12;
|
|
134
|
+
b[4] = (VALUE)13;
|
|
135
|
+
b_num = 5;
|
|
136
|
+
|
|
137
|
+
EXPECT_EQ(3, Frames::num_matching(a, a_num, b, b_num))
|
|
138
|
+
<< "* different length, frames matching from the end";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
TEST(Frames, cached_frames) {
|
|
142
|
+
cached_frames.clear();
|
|
143
|
+
// run some Ruby code and get a snapshot
|
|
144
|
+
rb_eval_string("TestMe::Snapshot::all_kinds");
|
|
145
|
+
|
|
146
|
+
Frames::remove_garbage(test_frames, test_num);
|
|
147
|
+
|
|
148
|
+
// Check the expected size
|
|
149
|
+
int expected = (ruby_version == 2) ? 8 : 10;
|
|
150
|
+
EXPECT_EQ(expected, cached_frames.size());
|
|
151
|
+
|
|
152
|
+
// check that each frame is cached
|
|
153
|
+
for (int i = 0; i < test_num; i++)
|
|
154
|
+
EXPECT_EQ(1, cached_frames.count(test_frames[i]));
|
|
155
|
+
|
|
156
|
+
// repeat
|
|
157
|
+
rb_eval_string("TestMe::Snapshot::all_kinds");
|
|
158
|
+
Frames::remove_garbage(test_frames, test_num);
|
|
159
|
+
|
|
160
|
+
expected = (ruby_version == 2) ? 9 : 11;
|
|
161
|
+
EXPECT_EQ(expected, cached_frames.size()); // +1 for an extra main frame
|
|
162
|
+
for (int i = 0; i < test_num; i++)
|
|
163
|
+
EXPECT_EQ(1, cached_frames.count(test_frames[i]));
|
|
164
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
|
|
2
|
+
#include "../src/frames.h"
|
|
3
|
+
|
|
4
|
+
#include <string.h>
|
|
5
|
+
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <thread>
|
|
8
|
+
#include <array>
|
|
9
|
+
|
|
10
|
+
#include "../src/profiling.h"
|
|
11
|
+
#include "gtest/gtest.h"
|
|
12
|
+
#include "ruby/debug.h"
|
|
13
|
+
#include "ruby/ruby.h"
|
|
14
|
+
#include "test.h"
|
|
15
|
+
|
|
16
|
+
extern atomic_bool profiling_shut_down;
|
|
17
|
+
// extern oboe_reporter_t *cur_reporter;
|
|
18
|
+
|
|
19
|
+
// FIXME how can I access profiling_shut_down ?
|
|
20
|
+
TEST(Profiling, try_catch_shutdown) {
|
|
21
|
+
EXPECT_FALSE(profiling_shut_down);
|
|
22
|
+
|
|
23
|
+
int result;
|
|
24
|
+
result = Profiling::try_catch_shutdown([] {
|
|
25
|
+
// provoke exception
|
|
26
|
+
std::string ().replace (100, 1, 1, 'c');
|
|
27
|
+
return 0;
|
|
28
|
+
}, "Profiling::try_catch()");
|
|
29
|
+
|
|
30
|
+
EXPECT_NE(0, result);
|
|
31
|
+
EXPECT_TRUE(profiling_shut_down);
|
|
32
|
+
|
|
33
|
+
// reset global var
|
|
34
|
+
profiling_shut_down = false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
TEST(Profiling, oboe_0_profiling) {
|
|
38
|
+
atomic_bool atomic_a1{true};
|
|
39
|
+
atomic_bool atomic_a2{false};
|
|
40
|
+
|
|
41
|
+
atomic_bool running;
|
|
42
|
+
|
|
43
|
+
cout << running << endl;
|
|
44
|
+
cout << running.exchange(true) << endl;
|
|
45
|
+
cout << running.exchange(true) << endl;
|
|
46
|
+
|
|
47
|
+
// cout << "prev val " << atomic_a2.exchange(false) << endl;
|
|
48
|
+
// cout << atomic_a2 << endl;
|
|
49
|
+
// cout << "prev val " << atomic_a2.exchange(true) << endl;
|
|
50
|
+
// cout << atomic_a2 << endl;
|
|
51
|
+
// cout << "prev val " << atomic_a2.exchange(true) << endl;
|
|
52
|
+
// cout << atomic_a2 << endl;
|
|
53
|
+
// cout << "prev val " << atomic_a2.exchange(false) << endl;
|
|
54
|
+
// cout << atomic_a2 << endl;
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
// static bool b1{true};
|
|
59
|
+
// static bool b2{false};
|
|
60
|
+
|
|
61
|
+
// array<thread, 4> threads;
|
|
62
|
+
|
|
63
|
+
// for (auto& t : threads) {
|
|
64
|
+
// t = thread([] { Profiling::profiler_signal_handler(0, NULL, NULL); });
|
|
65
|
+
// }
|
|
66
|
+
|
|
67
|
+
// cout << "waiting..." << endl;
|
|
68
|
+
|
|
69
|
+
// for (auto& t : threads) {
|
|
70
|
+
// t.join();
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
// cout << "Done." << endl;
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// cout << atomic_a1 << ", " << b1 << endl;
|
|
77
|
+
// cout << atomic_a1 << ", " << b1 << ", " << atomic_a1.compare_exchange_weak(b1, false) << endl;
|
|
78
|
+
// cout << atomic_a1 << ", " << b1 << endl;
|
|
79
|
+
// cout << atomic_a2 << ", " << b2 << endl;
|
|
80
|
+
// cout << atomic_a2 << ", " << b2 << ", " << atomic_a2.compare_exchange_weak(b2, true) << endl;
|
|
81
|
+
// cout << atomic_a2 << ", " << b2 << endl;
|
|
82
|
+
// cout << endl;
|
|
83
|
+
|
|
84
|
+
// cout << atomic_a1 << ", " << b1 << endl;
|
|
85
|
+
// cout << atomic_a1 << ", " << b1 << ", " << atomic_a1.compare_exchange_weak(b1, false) << endl;
|
|
86
|
+
// cout << atomic_a1 << ", " << b1 << endl;
|
|
87
|
+
// cout << atomic_a2 << ", " << b2 << endl;
|
|
88
|
+
// cout << atomic_a2 << ", " << b2 << ", " << atomic_a2.compare_exchange_weak(b2, true) << endl;
|
|
89
|
+
// cout << atomic_a2 << ", " << b2 << endl;
|
|
90
|
+
// cout << endl;
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
class TestMe
|
|
2
|
+
class Snapshot
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
# !!! do not shift the definition of take_snapshot from line 7 !!!
|
|
6
|
+
# the line number is used to verify a test in frames_test.cc
|
|
7
|
+
def take_snapshot
|
|
8
|
+
# puts "getting frames ...."
|
|
9
|
+
begin
|
|
10
|
+
::RubyCalls::get_frames
|
|
11
|
+
rescue => e
|
|
12
|
+
puts "oops, getting frames didn't work"
|
|
13
|
+
puts e
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def all_kinds
|
|
18
|
+
begin
|
|
19
|
+
Teddy.new.sing do
|
|
20
|
+
take_snapshot
|
|
21
|
+
end
|
|
22
|
+
rescue => e
|
|
23
|
+
puts "Ruby call did not work"
|
|
24
|
+
puts e
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class Teddy
|
|
31
|
+
|
|
32
|
+
attr_accessor :name
|
|
33
|
+
|
|
34
|
+
def sing
|
|
35
|
+
3.times do
|
|
36
|
+
yodel do
|
|
37
|
+
html_wrap("title", "Hello") { |_html| yield }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def yodel
|
|
45
|
+
a_proc = -> (x) { x * x; yield }
|
|
46
|
+
in_block(&a_proc)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def in_block(&block)
|
|
50
|
+
begin
|
|
51
|
+
yield 7
|
|
52
|
+
# puts "block called!"
|
|
53
|
+
rescue => e
|
|
54
|
+
puts "no, this should never happen"
|
|
55
|
+
puts e
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def html_wrap(tag, text)
|
|
60
|
+
html = "<#{tag}>#{text}</#{tag}>"
|
|
61
|
+
yield html
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
@@ -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
|
data/init.rb
ADDED
data/lib/oboe.rb
ADDED
data/lib/oboe_metal.rb
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'thread'
|
|
5
|
+
|
|
6
|
+
# Disable docs and Camelcase warns since we're implementing
|
|
7
|
+
# an interface here. See OboeBase for details.
|
|
8
|
+
# rubocop:disable Style/Documentation, Naming/MethodName
|
|
9
|
+
module SolarWindsAPM
|
|
10
|
+
extend SolarWindsAPMBase
|
|
11
|
+
include Oboe_metal
|
|
12
|
+
|
|
13
|
+
class Reporter
|
|
14
|
+
class << self
|
|
15
|
+
##
|
|
16
|
+
# start
|
|
17
|
+
#
|
|
18
|
+
# Start the SolarWindsAPM Reporter
|
|
19
|
+
#
|
|
20
|
+
def start
|
|
21
|
+
SolarWindsAPM.loaded = false unless SolarWindsAPM::OboeInitOptions.instance.service_key_ok?
|
|
22
|
+
return unless SolarWindsAPM.loaded
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
options = SolarWindsAPM::OboeInitOptions.instance.array_for_oboe # creates an array with the options in the right order
|
|
26
|
+
|
|
27
|
+
SolarWindsAPM.reporter = Oboe_metal::Reporter.new(*options)
|
|
28
|
+
|
|
29
|
+
# Only report __Init from here if we are not instrumenting a framework.
|
|
30
|
+
# Otherwise, frameworks will handle reporting __Init after full initialization
|
|
31
|
+
unless defined?(::Rails) || defined?(::Sinatra) || defined?(::Padrino) || defined?(::Grape)
|
|
32
|
+
SolarWindsAPM::API.report_init
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
rescue => e
|
|
36
|
+
$stderr.puts e.message
|
|
37
|
+
raise
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
alias :restart :start
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# sendReport
|
|
44
|
+
#
|
|
45
|
+
# Send the report for the given event
|
|
46
|
+
#
|
|
47
|
+
def sendReport(evt)
|
|
48
|
+
SolarWindsAPM.reporter.sendReport(evt)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# sendStatus
|
|
53
|
+
#
|
|
54
|
+
# Send the report for the given event
|
|
55
|
+
#
|
|
56
|
+
def sendStatus(evt, context = nil)
|
|
57
|
+
SolarWindsAPM.reporter.sendStatus(evt, context)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# clear_all_traces
|
|
62
|
+
#
|
|
63
|
+
# Truncates the trace output file to zero
|
|
64
|
+
#
|
|
65
|
+
def clear_all_traces
|
|
66
|
+
File.truncate(SolarWindsAPM::OboeInitOptions.instance.host, 0)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# get_all_traces
|
|
71
|
+
#
|
|
72
|
+
# Retrieves all traces written to the trace file
|
|
73
|
+
#
|
|
74
|
+
def get_all_traces
|
|
75
|
+
io = File.open(SolarWindsAPM::OboeInitOptions.instance.host, 'r')
|
|
76
|
+
contents = io.readlines(nil)
|
|
77
|
+
io.close
|
|
78
|
+
|
|
79
|
+
return contents if contents.empty?
|
|
80
|
+
|
|
81
|
+
traces = []
|
|
82
|
+
|
|
83
|
+
# We use Gem.loaded_spec because older versions of the bson
|
|
84
|
+
# gem didn't even have a version embedded in the gem. If the
|
|
85
|
+
# gem isn't in the bundle, it should rightfully error out
|
|
86
|
+
# anyways.
|
|
87
|
+
#
|
|
88
|
+
if Gem.loaded_specs['bson'] && Gem.loaded_specs['bson'].version.to_s < '4.0'
|
|
89
|
+
s = StringIO.new(contents[0])
|
|
90
|
+
|
|
91
|
+
until s.eof?
|
|
92
|
+
traces << if ::BSON.respond_to? :read_bson_document
|
|
93
|
+
BSON.read_bson_document(s)
|
|
94
|
+
else
|
|
95
|
+
BSON::Document.from_bson(s)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
bbb = ::BSON::ByteBuffer.new(contents[0])
|
|
100
|
+
until bbb.length == 0
|
|
101
|
+
traces << Hash.from_bson(bbb)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
traces
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
module EventUtil
|
|
111
|
+
def self.metadataString(evt)
|
|
112
|
+
evt.metadataString
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class << self
|
|
117
|
+
# def sample?(opts = {})
|
|
118
|
+
# # Return false if no-op mode
|
|
119
|
+
# return false unless SolarWindsAPM.loaded
|
|
120
|
+
#
|
|
121
|
+
# # Assure defaults since SWIG enforces Strings
|
|
122
|
+
# xtrace = opts[:xtrace] ? opts[:xtrace].to_s.strip : SW_APM_STR_BLANK
|
|
123
|
+
#
|
|
124
|
+
# # the first arg has changed to be the service name, blank means to use the default (from the service key)
|
|
125
|
+
# rv = SolarWindsAPM::Context.sampleRequest(SW_APM_STR_BLANK, xtrace)
|
|
126
|
+
#
|
|
127
|
+
# if rv == 0
|
|
128
|
+
# SolarWindsAPM.sample_rate = -1
|
|
129
|
+
# SolarWindsAPM.sample_source = -1
|
|
130
|
+
# false
|
|
131
|
+
# else
|
|
132
|
+
# # liboboe version > 1.3.1 returning a bit masked integer with SampleRate and
|
|
133
|
+
# # source embedded
|
|
134
|
+
# SolarWindsAPM.sample_rate = (rv & SAMPLE_RATE_MASK)
|
|
135
|
+
# SolarWindsAPM.sample_source = (rv & SAMPLE_SOURCE_MASK) >> 24
|
|
136
|
+
# true
|
|
137
|
+
# end
|
|
138
|
+
# rescue StandardError => e
|
|
139
|
+
# SolarWindsAPM.logger.debug "[oboe/error] sample? error: #{e.inspect}"
|
|
140
|
+
# false
|
|
141
|
+
# end
|
|
142
|
+
|
|
143
|
+
# def set_tracing_mode(mode)
|
|
144
|
+
# return unless SolarWindsAPM.loaded
|
|
145
|
+
#
|
|
146
|
+
# value = mode.to_sym
|
|
147
|
+
#
|
|
148
|
+
# case value
|
|
149
|
+
# when :disabled, :never
|
|
150
|
+
# SolarWindsAPM::Context.setTracingMode(SW_APM_TRACE_DISABLED)
|
|
151
|
+
#
|
|
152
|
+
# when :enabled, :always
|
|
153
|
+
# SolarWindsAPM::Context.setTracingMode(SW_APM_TRACE_ENABLED)
|
|
154
|
+
#
|
|
155
|
+
# else
|
|
156
|
+
# SolarWindsAPM.logger.fatal "[oboe/error] Invalid tracing mode set: #{mode}"
|
|
157
|
+
# SolarWindsAPM::Context.setTracingMode(SW_APM_TRACE_DISABLED)
|
|
158
|
+
# end
|
|
159
|
+
# end
|
|
160
|
+
|
|
161
|
+
def set_sample_rate(rate)
|
|
162
|
+
return unless SolarWindsAPM.loaded
|
|
163
|
+
|
|
164
|
+
# Update liboboe with the new SampleRate value
|
|
165
|
+
SolarWindsAPM::Context.setDefaultSampleRate(rate.to_i)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
# rubocop:enable Style/Documentation
|
|
170
|
+
|
|
171
|
+
SolarWindsAPM.loaded = true
|
|
172
|
+
SolarWindsAPM.config_lock = Mutex.new
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module SolarWindsAPM
|
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
6
|
+
source_root File.join(File.dirname(__FILE__), 'templates')
|
|
7
|
+
desc "Copies a SolarWindsAPM gem initializer file to your application."
|
|
8
|
+
|
|
9
|
+
@namespace = "solarwinds_apm:install"
|
|
10
|
+
|
|
11
|
+
def copy_initializer
|
|
12
|
+
# Set defaults
|
|
13
|
+
@verbose = 'false'
|
|
14
|
+
|
|
15
|
+
print_header
|
|
16
|
+
print_footer
|
|
17
|
+
|
|
18
|
+
template "solarwinds_apm_initializer.rb", "config/initializers/solarwinds_apm.rb"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# rubocop:disable Metrics/MethodLength
|
|
24
|
+
def print_header
|
|
25
|
+
say ""
|
|
26
|
+
say shell.set_color "Welcome to the SolarWindsAPM Ruby instrumentation setup.", :green, :bold
|
|
27
|
+
say ""
|
|
28
|
+
say shell.set_color "Documentation Links", :magenta
|
|
29
|
+
say "-------------------"
|
|
30
|
+
say ""
|
|
31
|
+
say "SolarWindsAPM Installation Overview:"
|
|
32
|
+
say "https://documentation.solarwinds.com/en/success_center/swaas/"
|
|
33
|
+
say ""
|
|
34
|
+
say "More information on instrumenting Ruby applications can be found here:"
|
|
35
|
+
say "https://documentation.solarwinds.com/en/success_center/swaas/default.htm#cshid=app-add-ruby-agent"
|
|
36
|
+
end
|
|
37
|
+
# rubocop:enable Metrics/MethodLength
|
|
38
|
+
|
|
39
|
+
def print_footer
|
|
40
|
+
say ""
|
|
41
|
+
say "You can change configuration values in the future by modifying config/initializers/solarwinds_apm.rb"
|
|
42
|
+
say ""
|
|
43
|
+
say "Thanks! Creating the SolarWindsAPM initializer..."
|
|
44
|
+
say ""
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|