appoptics_apm-zearn 4.13.1

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 (145) 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/.github/workflows/build_and_release_gem.yml +103 -0
  5. data/.github/workflows/build_for_packagecloud.yml +70 -0
  6. data/.github/workflows/docker-images.yml +47 -0
  7. data/.github/workflows/run_cpluplus_tests.yml +73 -0
  8. data/.github/workflows/run_tests.yml +168 -0
  9. data/.github/workflows/scripts/test_install.rb +23 -0
  10. data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
  11. data/.github/workflows/test_on_4_linux.yml +159 -0
  12. data/.gitignore +36 -0
  13. data/.rubocop.yml +29 -0
  14. data/.travis.yml +130 -0
  15. data/.yardopts +6 -0
  16. data/CHANGELOG.md +769 -0
  17. data/CONFIG.md +33 -0
  18. data/Gemfile +14 -0
  19. data/LICENSE +202 -0
  20. data/README.md +393 -0
  21. data/appoptics_apm.gemspec +70 -0
  22. data/bin/appoptics_apm_config +15 -0
  23. data/examples/prepend.rb +13 -0
  24. data/examples/sdk_examples.rb +158 -0
  25. data/ext/oboe_metal/README.md +69 -0
  26. data/ext/oboe_metal/extconf.rb +151 -0
  27. data/ext/oboe_metal/lib/.keep +0 -0
  28. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
  29. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
  30. data/ext/oboe_metal/noop/noop.c +8 -0
  31. data/ext/oboe_metal/src/README.md +6 -0
  32. data/ext/oboe_metal/src/VERSION +2 -0
  33. data/ext/oboe_metal/src/bson/bson.h +220 -0
  34. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  35. data/ext/oboe_metal/src/frames.cc +246 -0
  36. data/ext/oboe_metal/src/frames.h +40 -0
  37. data/ext/oboe_metal/src/init_appoptics_apm.cc +21 -0
  38. data/ext/oboe_metal/src/logging.cc +95 -0
  39. data/ext/oboe_metal/src/logging.h +35 -0
  40. data/ext/oboe_metal/src/oboe.h +1156 -0
  41. data/ext/oboe_metal/src/oboe_api.cpp +652 -0
  42. data/ext/oboe_metal/src/oboe_api.hpp +431 -0
  43. data/ext/oboe_metal/src/oboe_debug.h +59 -0
  44. data/ext/oboe_metal/src/oboe_swig_wrap.cc +7329 -0
  45. data/ext/oboe_metal/src/profiling.cc +435 -0
  46. data/ext/oboe_metal/src/profiling.h +78 -0
  47. data/ext/oboe_metal/test/CMakeLists.txt +53 -0
  48. data/ext/oboe_metal/test/FindGMock.cmake +43 -0
  49. data/ext/oboe_metal/test/README.md +56 -0
  50. data/ext/oboe_metal/test/frames_test.cc +164 -0
  51. data/ext/oboe_metal/test/profiling_test.cc +93 -0
  52. data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
  53. data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
  54. data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
  55. data/ext/oboe_metal/test/test.h +11 -0
  56. data/ext/oboe_metal/test/test_main.cc +32 -0
  57. data/init.rb +4 -0
  58. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  59. data/lib/appoptics_apm/api/logging.rb +381 -0
  60. data/lib/appoptics_apm/api/memcache.rb +37 -0
  61. data/lib/appoptics_apm/api/metrics.rb +63 -0
  62. data/lib/appoptics_apm/api/tracing.rb +57 -0
  63. data/lib/appoptics_apm/api/util.rb +120 -0
  64. data/lib/appoptics_apm/api.rb +21 -0
  65. data/lib/appoptics_apm/base.rb +231 -0
  66. data/lib/appoptics_apm/config.rb +299 -0
  67. data/lib/appoptics_apm/frameworks/grape.rb +98 -0
  68. data/lib/appoptics_apm/frameworks/padrino.rb +78 -0
  69. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  70. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  71. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  72. data/lib/appoptics_apm/frameworks/rails/inst/action_controller6.rb +50 -0
  73. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  74. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +88 -0
  75. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  76. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  77. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  78. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  79. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  80. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +114 -0
  81. data/lib/appoptics_apm/frameworks/rails/inst/logger_formatters.rb +27 -0
  82. data/lib/appoptics_apm/frameworks/rails.rb +100 -0
  83. data/lib/appoptics_apm/frameworks/sinatra.rb +96 -0
  84. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  85. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  86. data/lib/appoptics_apm/inst/curb.rb +332 -0
  87. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  88. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  89. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  90. data/lib/appoptics_apm/inst/excon.rb +125 -0
  91. data/lib/appoptics_apm/inst/faraday.rb +106 -0
  92. data/lib/appoptics_apm/inst/graphql.rb +240 -0
  93. data/lib/appoptics_apm/inst/grpc_client.rb +159 -0
  94. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  95. data/lib/appoptics_apm/inst/http.rb +81 -0
  96. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  97. data/lib/appoptics_apm/inst/logger_formatter.rb +50 -0
  98. data/lib/appoptics_apm/inst/logging_log_event.rb +28 -0
  99. data/lib/appoptics_apm/inst/lumberjack_formatter.rb +13 -0
  100. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  101. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  102. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  103. data/lib/appoptics_apm/inst/moped.rb +466 -0
  104. data/lib/appoptics_apm/inst/rack.rb +182 -0
  105. data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
  106. data/lib/appoptics_apm/inst/redis.rb +274 -0
  107. data/lib/appoptics_apm/inst/resque.rb +151 -0
  108. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  109. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  110. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  111. data/lib/appoptics_apm/inst/sidekiq-worker.rb +66 -0
  112. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  113. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  114. data/lib/appoptics_apm/instrumentation.rb +22 -0
  115. data/lib/appoptics_apm/loading.rb +65 -0
  116. data/lib/appoptics_apm/logger.rb +14 -0
  117. data/lib/appoptics_apm/noop/README.md +9 -0
  118. data/lib/appoptics_apm/noop/context.rb +27 -0
  119. data/lib/appoptics_apm/noop/metadata.rb +25 -0
  120. data/lib/appoptics_apm/noop/profiling.rb +21 -0
  121. data/lib/appoptics_apm/oboe_init_options.rb +211 -0
  122. data/lib/appoptics_apm/ruby.rb +35 -0
  123. data/lib/appoptics_apm/sdk/current_trace.rb +77 -0
  124. data/lib/appoptics_apm/sdk/custom_metrics.rb +94 -0
  125. data/lib/appoptics_apm/sdk/logging.rb +37 -0
  126. data/lib/appoptics_apm/sdk/tracing.rb +434 -0
  127. data/lib/appoptics_apm/support/profiling.rb +18 -0
  128. data/lib/appoptics_apm/support/transaction_metrics.rb +67 -0
  129. data/lib/appoptics_apm/support/transaction_settings.rb +219 -0
  130. data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
  131. data/lib/appoptics_apm/support_report.rb +119 -0
  132. data/lib/appoptics_apm/test.rb +95 -0
  133. data/lib/appoptics_apm/thread_local.rb +26 -0
  134. data/lib/appoptics_apm/util.rb +326 -0
  135. data/lib/appoptics_apm/version.rb +16 -0
  136. data/lib/appoptics_apm/xtrace.rb +115 -0
  137. data/lib/appoptics_apm.rb +77 -0
  138. data/lib/joboe_metal.rb +212 -0
  139. data/lib/oboe.rb +7 -0
  140. data/lib/oboe_metal.rb +172 -0
  141. data/lib/rails/generators/appoptics_apm/install_generator.rb +47 -0
  142. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +425 -0
  143. data/log/.keep +0 -0
  144. data/yardoc_frontpage.md +26 -0
  145. metadata +231 -0
@@ -0,0 +1,220 @@
1
+ /* bson.h */
2
+
3
+ /* Copyright 2009, 2010 10gen Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #ifndef _BSON_H_
19
+ #define _BSON_H_
20
+
21
+ #define MONGO_HAVE_STDINT
22
+ #include "platform_hacks.h"
23
+ #include <time.h>
24
+
25
+ MONGO_EXTERN_C_START
26
+
27
+ typedef enum {
28
+ oboe_bson_error=-1,
29
+ oboe_bson_eoo=0,
30
+ oboe_bson_double=1,
31
+ oboe_bson_string=2,
32
+ oboe_bson_object=3,
33
+ oboe_bson_array=4,
34
+ oboe_bson_bindata=5,
35
+ oboe_bson_undefined=6,
36
+ oboe_bson_oid=7,
37
+ oboe_bson_bool=8,
38
+ oboe_bson_date=9,
39
+ oboe_bson_null=10,
40
+ oboe_bson_regex=11,
41
+ oboe_bson_dbref=12, /* deprecated */
42
+ oboe_bson_code=13,
43
+ oboe_bson_symbol=14,
44
+ oboe_bson_codewscope=15,
45
+ oboe_bson_int = 16,
46
+ oboe_bson_timestamp = 17,
47
+ oboe_bson_long = 18
48
+ } oboe_bson_type;
49
+
50
+ typedef int oboe_bson_bool_t;
51
+
52
+ typedef struct {
53
+ char * data;
54
+ oboe_bson_bool_t owned;
55
+ } oboe_bson;
56
+
57
+ typedef struct {
58
+ const char * cur;
59
+ oboe_bson_bool_t first;
60
+ } oboe_bson_iterator;
61
+
62
+ typedef struct {
63
+ char * buf;
64
+ char * cur;
65
+ int bufSize;
66
+ oboe_bson_bool_t finished;
67
+ int stack[32];
68
+ int stackPos;
69
+ } oboe_bson_buffer;
70
+
71
+ #pragma pack(1)
72
+ typedef union{
73
+ char bytes[12]; // Flawfinder: ignore
74
+ int ints[3];
75
+ } oboe_bson_oid_t;
76
+ #pragma pack()
77
+
78
+ typedef int64_t oboe_bson_date_t; /* milliseconds since epoch UTC */
79
+
80
+ /* ----------------------------
81
+ READING
82
+ ------------------------------ */
83
+
84
+
85
+ oboe_bson * oboe_bson_empty(oboe_bson * obj); /* returns pointer to static empty bson object */
86
+ int oboe_bson_copy(oboe_bson* out, const oboe_bson* in); /* puts data in new buffer. NOOP if out==NULL */
87
+ oboe_bson * oboe_bson_from_buffer(oboe_bson * b, oboe_bson_buffer * buf);
88
+ oboe_bson * oboe_bson_init( oboe_bson * b , char * data , oboe_bson_bool_t mine );
89
+ oboe_bson * oboe_bson_init_safe( oboe_bson * b , char * data , oboe_bson_bool_t mine , size_t buflen);
90
+ int oboe_bson_size(const oboe_bson * b );
91
+ void oboe_bson_destroy( oboe_bson * b );
92
+
93
+ void oboe_bson_print( oboe_bson * b );
94
+ void oboe_bson_print_raw( const char * bson , int depth );
95
+
96
+ /* advances iterator to named field */
97
+ /* returns bson_eoo (which is false) if field not found */
98
+ oboe_bson_type oboe_bson_find(oboe_bson_iterator* it, const oboe_bson* obj, const char* name);
99
+
100
+ void oboe_bson_iterator_init( oboe_bson_iterator * i , const char * bson );
101
+
102
+ /* more returns true for eoo. best to loop with bson_iterator_next(&it) */
103
+ oboe_bson_bool_t oboe_bson_iterator_more( const oboe_bson_iterator * i );
104
+ oboe_bson_type oboe_bson_iterator_next( oboe_bson_iterator * i );
105
+
106
+ oboe_bson_type oboe_bson_iterator_type( const oboe_bson_iterator * i );
107
+ const char * oboe_bson_iterator_key( const oboe_bson_iterator * i );
108
+ const char * oboe_bson_iterator_value( const oboe_bson_iterator * i );
109
+
110
+ /* these convert to the right type (return 0 if non-numeric) */
111
+ double oboe_bson_iterator_double( const oboe_bson_iterator * i );
112
+ int oboe_bson_iterator_int( const oboe_bson_iterator * i );
113
+ int64_t oboe_bson_iterator_long( const oboe_bson_iterator * i );
114
+
115
+ /* false: boolean false, 0 in any type, or null */
116
+ /* true: anything else (even empty strings and objects) */
117
+ oboe_bson_bool_t oboe_bson_iterator_bool( const oboe_bson_iterator * i );
118
+
119
+ /* these assume you are using the right type */
120
+ double oboe_bson_iterator_double_raw( const oboe_bson_iterator * i );
121
+ int oboe_bson_iterator_int_raw( const oboe_bson_iterator * i );
122
+ int64_t oboe_bson_iterator_long_raw( const oboe_bson_iterator * i );
123
+ oboe_bson_bool_t oboe_bson_iterator_bool_raw( const oboe_bson_iterator * i );
124
+ oboe_bson_oid_t* oboe_bson_iterator_oid( const oboe_bson_iterator * i );
125
+
126
+ /* these can also be used with bson_code and bson_symbol*/
127
+ const char * oboe_bson_iterator_string( const oboe_bson_iterator * i );
128
+ int oboe_bson_iterator_string_len( const oboe_bson_iterator * i );
129
+
130
+ /* works with bson_code, bson_codewscope, and bson_string */
131
+ /* returns NULL for everything else */
132
+ const char * oboe_bson_iterator_code(const oboe_bson_iterator * i);
133
+
134
+ /* calls bson_empty on scope if not a bson_codewscope */
135
+ void oboe_bson_iterator_code_scope(const oboe_bson_iterator * i, oboe_bson * scope);
136
+
137
+ /* both of these only work with bson_date */
138
+ oboe_bson_date_t oboe_bson_iterator_date(const oboe_bson_iterator * i);
139
+ time_t oboe_bson_iterator_time_t(const oboe_bson_iterator * i);
140
+
141
+ int oboe_bson_iterator_bin_len( const oboe_bson_iterator * i );
142
+ char oboe_bson_iterator_bin_type( const oboe_bson_iterator * i );
143
+ const char * oboe_bson_iterator_bin_data( const oboe_bson_iterator * i );
144
+
145
+ const char * oboe_bson_iterator_regex( const oboe_bson_iterator * i );
146
+ const char * oboe_bson_iterator_regex_opts( const oboe_bson_iterator * i );
147
+
148
+ /* these work with bson_object and bson_array */
149
+ void oboe_bson_iterator_subobject(const oboe_bson_iterator * i, oboe_bson * sub);
150
+ void oboe_bson_iterator_subiterator(const oboe_bson_iterator * i, oboe_bson_iterator * sub);
151
+
152
+ /* str must be at least 24 hex chars + null byte */
153
+ void oboe_bson_oid_from_string(oboe_bson_oid_t* oid, const char* str);
154
+ void oboe_bson_oid_to_string(const oboe_bson_oid_t* oid, char* str);
155
+ void oboe_bson_oid_gen(oboe_bson_oid_t* oid);
156
+
157
+ time_t oboe_bson_oid_generated_time(oboe_bson_oid_t* oid); /* Gives the time the OID was created */
158
+
159
+ /* ----------------------------
160
+ BUILDING
161
+ ------------------------------ */
162
+
163
+ oboe_bson_buffer * oboe_bson_buffer_init( oboe_bson_buffer * b );
164
+ oboe_bson_buffer * oboe_bson_ensure_space( oboe_bson_buffer * b , const int bytesNeeded );
165
+
166
+ /**
167
+ * @return the raw data. you either should free this OR call bson_destroy not both
168
+ */
169
+ char * oboe_bson_buffer_finish( oboe_bson_buffer * b );
170
+ void oboe_bson_buffer_destroy( oboe_bson_buffer * b );
171
+
172
+ oboe_bson_buffer * oboe_bson_append_oid( oboe_bson_buffer * b , const char * name , const oboe_bson_oid_t* oid );
173
+ oboe_bson_buffer * oboe_bson_append_int( oboe_bson_buffer * b , const char * name , const int i );
174
+ oboe_bson_buffer * oboe_bson_append_long( oboe_bson_buffer * b , const char * name , const int64_t i );
175
+ oboe_bson_buffer * oboe_bson_append_double( oboe_bson_buffer * b , const char * name , const double d );
176
+ oboe_bson_buffer * oboe_bson_append_string( oboe_bson_buffer * b , const char * name , const char * str );
177
+ oboe_bson_buffer * oboe_bson_append_symbol( oboe_bson_buffer * b , const char * name , const char * str );
178
+ oboe_bson_buffer * oboe_bson_append_code( oboe_bson_buffer * b , const char * name , const char * str );
179
+ oboe_bson_buffer * oboe_bson_append_code_w_scope( oboe_bson_buffer * b , const char * name , const char * code , const oboe_bson * scope);
180
+ oboe_bson_buffer * oboe_bson_append_binary( oboe_bson_buffer * b, const char * name, char type, const char * str, int len );
181
+ oboe_bson_buffer * oboe_bson_append_bool( oboe_bson_buffer * b , const char * name , const oboe_bson_bool_t v );
182
+ oboe_bson_buffer * oboe_bson_append_null( oboe_bson_buffer * b , const char * name );
183
+ oboe_bson_buffer * oboe_bson_append_undefined( oboe_bson_buffer * b , const char * name );
184
+ oboe_bson_buffer * oboe_bson_append_regex( oboe_bson_buffer * b , const char * name , const char * pattern, const char * opts );
185
+ oboe_bson_buffer * oboe_bson_append_bson( oboe_bson_buffer * b , const char * name , const oboe_bson* bson);
186
+ oboe_bson_buffer * oboe_bson_append_element( oboe_bson_buffer * b, const char * name_or_null, const oboe_bson_iterator* elem);
187
+
188
+ /* these both append a bson_date */
189
+ oboe_bson_buffer * oboe_bson_append_date(oboe_bson_buffer * b, const char * name, oboe_bson_date_t millis);
190
+ oboe_bson_buffer * oboe_bson_append_time_t(oboe_bson_buffer * b, const char * name, time_t secs);
191
+
192
+ oboe_bson_buffer * oboe_bson_append_start_object( oboe_bson_buffer * b , const char * name );
193
+ oboe_bson_buffer * oboe_bson_append_start_array( oboe_bson_buffer * b , const char * name );
194
+ oboe_bson_buffer * oboe_bson_append_finish_object( oboe_bson_buffer * b );
195
+
196
+ void oboe_bson_numstr(char* str, int i);
197
+ void oboe_bson_incnumstr(char* str);
198
+
199
+
200
+ /* ------------------------------
201
+ ERROR HANDLING - also used in mongo code
202
+ ------------------------------ */
203
+
204
+ void * oboe_bson_malloc(int size); /* checks return value */
205
+
206
+ /* bson_err_handlers shouldn't return!!! */
207
+ typedef void(*ob_bson_err_handler)(const char* errmsg);
208
+
209
+ /* returns old handler or NULL */
210
+ /* default handler prints error then exits with failure*/
211
+ ob_bson_err_handler oboe_set_bson_err_handler(ob_bson_err_handler func);
212
+
213
+
214
+
215
+ /* does nothing is ok != 0 */
216
+ void oboe_bson_fatal( int ok );
217
+ int oboe_bson_fatal_msg( int ok, const char* msg );
218
+
219
+ MONGO_EXTERN_C_END
220
+ #endif
@@ -0,0 +1,91 @@
1
+ /* platform_hacks.h */
2
+ /* Copyright 2009, 2010 10gen Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+
18
+ /* all platform-specific ifdefs should go here */
19
+
20
+ #ifndef _PLATFORM_HACKS_H_
21
+ #define _PLATFORM_HACKS_H_
22
+
23
+ #ifdef __GNUC__
24
+ #define MONGO_INLINE static __inline__
25
+ #else
26
+ #define MONGO_INLINE static
27
+ #endif
28
+
29
+ #ifdef __cplusplus
30
+ #define MONGO_EXTERN_C_START extern "C" {
31
+ #define MONGO_EXTERN_C_END }
32
+ #else
33
+ #define MONGO_EXTERN_C_START
34
+ #define MONGO_EXTERN_C_END
35
+ #endif
36
+
37
+
38
+ #if defined(MONGO_HAVE_STDINT) || __STDC_VERSION__ >= 199901L
39
+ #include <stdint.h>
40
+ #elif defined(MONGO_HAVE_UNISTD)
41
+ #include <unistd.h>
42
+ #elif defined(MONGO_USE__INT64)
43
+ typedef __int64 int64_t;
44
+ #elif defined(MONGO_USE_LONG_LONG_INT)
45
+ typedef long long int int64_t;
46
+ #else
47
+ #error must have a 64bit int type
48
+ #endif
49
+
50
+ /* big endian is only used for OID generation. little is used everywhere else */
51
+ #ifdef MONGO_BIG_ENDIAN
52
+ #define oboe_bson_little_endian64(out, in) ( oboe_bson_swap_endian64(out, in) )
53
+ #define oboe_bson_little_endian32(out, in) ( oboe_bson_swap_endian32(out, in) )
54
+ #define oboe_bson_big_endian64(out, in) ( memmove(out, in, 8) )
55
+ #define oboe_bson_big_endian32(out, in) ( memmove(out, in, 4) )
56
+ #else
57
+ #define oboe_bson_little_endian64(out, in) ( memmove(out, in, 8) )
58
+ #define oboe_bson_little_endian32(out, in) ( memmove(out, in, 4) )
59
+ #define oboe_bson_big_endian64(out, in) ( oboe_bson_swap_endian64(out, in) )
60
+ #define oboe_bson_big_endian32(out, in) ( oboe_bson_swap_endian32(out, in) )
61
+ #endif
62
+
63
+ MONGO_EXTERN_C_START
64
+
65
+ MONGO_INLINE void oboe_bson_swap_endian64(void* outp, const void* inp){
66
+ const char *in = (const char*)inp;
67
+ char *out = (char*)outp;
68
+
69
+ out[0] = in[7];
70
+ out[1] = in[6];
71
+ out[2] = in[5];
72
+ out[3] = in[4];
73
+ out[4] = in[3];
74
+ out[5] = in[2];
75
+ out[6] = in[1];
76
+ out[7] = in[0];
77
+
78
+ }
79
+ MONGO_INLINE void oboe_bson_swap_endian32(void* outp, const void* inp){
80
+ const char *in = (const char*)inp;
81
+ char *out = (char*)outp;
82
+
83
+ out[0] = in[3];
84
+ out[1] = in[2];
85
+ out[2] = in[1];
86
+ out[3] = in[0];
87
+ }
88
+
89
+ MONGO_EXTERN_C_END
90
+
91
+ #endif
@@ -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
@@ -0,0 +1,21 @@
1
+ // Copyright (c) 2019 SolarWinds, LLC.
2
+ // All rights reserved.
3
+
4
+ #include <iostream>
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ void Init_oboe_metal(void);
11
+
12
+ void Init_profiling(void);
13
+
14
+ void Init_libappoptics_apm() {
15
+ Init_oboe_metal();
16
+ Init_profiling();
17
+ }
18
+
19
+ #ifdef __cplusplus
20
+ }
21
+ #endif