ddtrace 1.18.0 → 1.23.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +228 -2
  3. data/LICENSE-3rdparty.csv +1 -1
  4. data/bin/ddprofrb +15 -0
  5. data/bin/ddtracerb +3 -1
  6. data/ext/{ddtrace_profiling_loader/ddtrace_profiling_loader.c → datadog_profiling_loader/datadog_profiling_loader.c} +2 -2
  7. data/ext/{ddtrace_profiling_loader → datadog_profiling_loader}/extconf.rb +3 -3
  8. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_cpu_and_wall_time_worker.c +312 -117
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +422 -0
  10. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +101 -0
  11. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.c +22 -14
  12. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.h +4 -0
  13. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
  14. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
  15. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.c +43 -102
  16. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.h +10 -3
  17. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.c +272 -136
  18. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.h +2 -1
  19. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/extconf.rb +28 -7
  20. data/ext/datadog_profiling_native_extension/heap_recorder.c +1047 -0
  21. data/ext/datadog_profiling_native_extension/heap_recorder.h +166 -0
  22. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/helpers.h +6 -0
  23. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/http_transport.c +15 -19
  24. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.c +20 -0
  25. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.h +11 -0
  26. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/native_extension_helpers.rb +50 -4
  27. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.c +19 -0
  28. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.h +4 -0
  29. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/profiling.c +18 -1
  30. data/ext/datadog_profiling_native_extension/ruby_helpers.c +267 -0
  31. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.h +33 -0
  32. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.c +476 -58
  33. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.h +3 -0
  34. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.h +2 -0
  35. data/lib/datadog/appsec/contrib/devise/tracking.rb +8 -0
  36. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +45 -14
  37. data/lib/datadog/appsec/event.rb +1 -1
  38. data/lib/datadog/auto_instrument.rb +3 -0
  39. data/lib/datadog/core/configuration/components.rb +7 -6
  40. data/lib/datadog/core/configuration/option.rb +8 -6
  41. data/lib/datadog/core/configuration/settings.rb +259 -60
  42. data/lib/datadog/core/configuration.rb +20 -4
  43. data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
  44. data/lib/datadog/core/environment/class_count.rb +6 -6
  45. data/lib/datadog/core/environment/git.rb +25 -0
  46. data/lib/datadog/core/environment/identity.rb +18 -48
  47. data/lib/datadog/core/environment/platform.rb +7 -1
  48. data/lib/datadog/core/git/ext.rb +2 -23
  49. data/lib/datadog/core/remote/client/capabilities.rb +1 -1
  50. data/lib/datadog/core/remote/component.rb +25 -12
  51. data/lib/datadog/core/remote/ext.rb +1 -0
  52. data/lib/datadog/core/remote/negotiation.rb +2 -2
  53. data/lib/datadog/core/remote/tie/tracing.rb +39 -0
  54. data/lib/datadog/core/remote/tie.rb +27 -0
  55. data/lib/datadog/core/remote/transport/http/config.rb +1 -1
  56. data/lib/datadog/core/remote/worker.rb +7 -4
  57. data/lib/datadog/core/telemetry/client.rb +18 -10
  58. data/lib/datadog/core/telemetry/emitter.rb +9 -13
  59. data/lib/datadog/core/telemetry/event.rb +247 -56
  60. data/lib/datadog/core/telemetry/ext.rb +4 -0
  61. data/lib/datadog/core/telemetry/heartbeat.rb +1 -3
  62. data/lib/datadog/core/telemetry/http/ext.rb +4 -1
  63. data/lib/datadog/core/telemetry/http/response.rb +4 -0
  64. data/lib/datadog/core/telemetry/http/transport.rb +9 -4
  65. data/lib/datadog/core/telemetry/request.rb +59 -0
  66. data/lib/datadog/core/transport/ext.rb +2 -0
  67. data/lib/datadog/core/utils/url.rb +25 -0
  68. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -2
  69. data/lib/datadog/opentelemetry.rb +3 -0
  70. data/lib/datadog/profiling/collectors/code_provenance.rb +10 -4
  71. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +36 -12
  72. data/lib/datadog/profiling/collectors/info.rb +101 -0
  73. data/lib/datadog/profiling/component.rb +210 -34
  74. data/lib/datadog/profiling/exporter.rb +23 -6
  75. data/lib/datadog/profiling/ext.rb +2 -0
  76. data/lib/datadog/profiling/flush.rb +6 -3
  77. data/lib/datadog/profiling/http_transport.rb +5 -1
  78. data/lib/datadog/profiling/load_native_extension.rb +19 -6
  79. data/lib/datadog/profiling/native_extension.rb +1 -1
  80. data/lib/datadog/profiling/scheduler.rb +4 -6
  81. data/lib/datadog/profiling/stack_recorder.rb +19 -4
  82. data/lib/datadog/profiling/tag_builder.rb +5 -0
  83. data/lib/datadog/profiling/tasks/exec.rb +3 -3
  84. data/lib/datadog/profiling/tasks/help.rb +3 -3
  85. data/lib/datadog/profiling.rb +13 -2
  86. data/lib/datadog/tracing/configuration/ext.rb +0 -1
  87. data/lib/datadog/tracing/configuration/settings.rb +2 -1
  88. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +1 -0
  89. data/lib/datadog/tracing/contrib/action_cable/ext.rb +1 -0
  90. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +1 -0
  91. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +1 -1
  92. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +1 -0
  93. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -0
  94. data/lib/datadog/tracing/contrib/action_pack/ext.rb +1 -0
  95. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +1 -0
  96. data/lib/datadog/tracing/contrib/action_view/ext.rb +1 -0
  97. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -0
  98. data/lib/datadog/tracing/contrib/active_job/ext.rb +1 -0
  99. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +1 -0
  100. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +1 -0
  101. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +11 -4
  102. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -0
  103. data/lib/datadog/tracing/contrib/active_record/ext.rb +1 -0
  104. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -0
  105. data/lib/datadog/tracing/contrib/active_support/ext.rb +1 -0
  106. data/lib/datadog/tracing/contrib/analytics.rb +0 -1
  107. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -0
  108. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  109. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
  110. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +11 -1
  111. data/lib/datadog/tracing/contrib/configurable.rb +1 -1
  112. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -0
  113. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  114. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -0
  115. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +1 -0
  116. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -0
  117. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
  118. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -0
  119. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  120. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -0
  121. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  122. data/lib/datadog/tracing/contrib/extensions.rb +6 -2
  123. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -0
  124. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  125. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -1
  126. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +1 -0
  127. data/lib/datadog/tracing/contrib/grape/ext.rb +1 -0
  128. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -0
  129. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  130. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -0
  131. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  132. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -0
  133. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +2 -2
  134. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  135. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -0
  136. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  137. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -0
  138. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  139. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +1 -0
  140. data/lib/datadog/tracing/contrib/kafka/ext.rb +1 -0
  141. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -0
  142. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  143. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  144. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  145. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -1
  146. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -0
  147. data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -0
  148. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -0
  149. data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
  150. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +11 -4
  151. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -0
  152. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  153. data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +1 -0
  154. data/lib/datadog/tracing/contrib/qless/ext.rb +1 -0
  155. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -0
  156. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  157. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -0
  158. data/lib/datadog/tracing/contrib/racecar/ext.rb +1 -0
  159. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -0
  160. data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
  161. data/lib/datadog/tracing/contrib/rack/middlewares.rb +9 -2
  162. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +0 -2
  163. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -0
  164. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  165. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -0
  166. data/lib/datadog/tracing/contrib/rake/ext.rb +1 -0
  167. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -0
  168. data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
  169. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +2 -2
  170. data/lib/datadog/tracing/contrib/redis/patcher.rb +34 -21
  171. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -0
  172. data/lib/datadog/tracing/contrib/resque/ext.rb +1 -0
  173. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -0
  174. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  175. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +1 -0
  176. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  177. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +1 -0
  178. data/lib/datadog/tracing/contrib/sequel/ext.rb +1 -0
  179. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -0
  180. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +1 -0
  181. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
  182. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  183. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -0
  184. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  185. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -0
  186. data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
  187. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +1 -0
  188. data/lib/datadog/tracing/contrib/stripe/ext.rb +1 -0
  189. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +1 -0
  190. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +1 -0
  191. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +58 -0
  192. data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
  193. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +94 -0
  194. data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
  195. data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
  196. data/lib/datadog/tracing/contrib.rb +1 -0
  197. data/lib/datadog/tracing/sampling/matcher.rb +23 -3
  198. data/lib/datadog/tracing/sampling/rule.rb +7 -2
  199. data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
  200. data/lib/datadog/tracing/trace_operation.rb +1 -2
  201. data/lib/datadog/tracing/transport/http.rb +1 -0
  202. data/lib/datadog/tracing/transport/trace_formatter.rb +31 -0
  203. data/lib/datadog/tracing.rb +8 -2
  204. data/lib/ddtrace/version.rb +2 -2
  205. metadata +71 -61
  206. data/ext/ddtrace_profiling_native_extension/pid_controller.c +0 -57
  207. data/ext/ddtrace_profiling_native_extension/pid_controller.h +0 -45
  208. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +0 -110
  209. data/lib/datadog/core/telemetry/collector.rb +0 -240
  210. data/lib/datadog/core/telemetry/v1/app_event.rb +0 -52
  211. data/lib/datadog/core/telemetry/v1/application.rb +0 -92
  212. data/lib/datadog/core/telemetry/v1/configuration.rb +0 -25
  213. data/lib/datadog/core/telemetry/v1/dependency.rb +0 -43
  214. data/lib/datadog/core/telemetry/v1/host.rb +0 -59
  215. data/lib/datadog/core/telemetry/v1/integration.rb +0 -64
  216. data/lib/datadog/core/telemetry/v1/product.rb +0 -36
  217. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +0 -106
  218. data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +0 -41
  219. data/lib/datadog/core/telemetry/v2/request.rb +0 -29
  220. data/lib/datadog/profiling/diagnostics/environment_logger.rb +0 -39
  221. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/NativeExtensionDesign.md +0 -0
  222. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id.h +0 -0
  223. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_from_pthread.c +0 -0
  224. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_noop.c +0 -0
  225. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.c +0 -0
  226. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.h +0 -0
  227. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.c +0 -0
  228. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.h +0 -0
  229. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.c +0 -0
@@ -0,0 +1,267 @@
1
+ #include <ruby.h>
2
+ #include <ruby/thread.h>
3
+
4
+ #include "ruby_helpers.h"
5
+ #include "private_vm_api_access.h"
6
+
7
+ // The following global variables are initialized at startup to save expensive lookups later.
8
+ // They are not expected to be mutated outside of init.
9
+ static VALUE module_object_space = Qnil;
10
+ static ID _id2ref_id = Qnil;
11
+ static ID inspect_id = Qnil;
12
+ static ID to_s_id = Qnil;
13
+
14
+ void ruby_helpers_init(void) {
15
+ rb_global_variable(&module_object_space);
16
+
17
+ module_object_space = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
18
+ _id2ref_id = rb_intern("_id2ref");
19
+ inspect_id = rb_intern("inspect");
20
+ to_s_id = rb_intern("to_s");
21
+ }
22
+
23
+ void raise_unexpected_type(
24
+ VALUE value,
25
+ const char *value_name,
26
+ const char *type_name,
27
+ const char *file,
28
+ int line,
29
+ const char* function_name
30
+ ) {
31
+ rb_exc_raise(
32
+ rb_exc_new_str(
33
+ rb_eTypeError,
34
+ rb_sprintf("wrong argument %"PRIsVALUE" for '%s' (expected a %s) at %s:%d:in `%s'",
35
+ rb_inspect(value),
36
+ value_name,
37
+ type_name,
38
+ file,
39
+ line,
40
+ function_name
41
+ )
42
+ )
43
+ );
44
+ }
45
+
46
+ #define MAX_RAISE_MESSAGE_SIZE 256
47
+
48
+ struct raise_arguments {
49
+ VALUE exception_class;
50
+ char exception_message[MAX_RAISE_MESSAGE_SIZE];
51
+ };
52
+
53
+ static void *trigger_raise(void *raise_arguments) {
54
+ struct raise_arguments *args = (struct raise_arguments *) raise_arguments;
55
+ rb_raise(args->exception_class, "%s", args->exception_message);
56
+ }
57
+
58
+ void grab_gvl_and_raise(VALUE exception_class, const char *format_string, ...) {
59
+ struct raise_arguments args;
60
+
61
+ args.exception_class = exception_class;
62
+
63
+ va_list format_string_arguments;
64
+ va_start(format_string_arguments, format_string);
65
+ vsnprintf(args.exception_message, MAX_RAISE_MESSAGE_SIZE, format_string, format_string_arguments);
66
+
67
+ if (is_current_thread_holding_the_gvl()) {
68
+ rb_raise(
69
+ rb_eRuntimeError,
70
+ "grab_gvl_and_raise called by thread holding the global VM lock. exception_message: '%s'",
71
+ args.exception_message
72
+ );
73
+ }
74
+
75
+ rb_thread_call_with_gvl(trigger_raise, &args);
76
+
77
+ rb_bug("[ddtrace] Unexpected: Reached the end of grab_gvl_and_raise while raising '%s'\n", args.exception_message);
78
+ }
79
+
80
+ struct syserr_raise_arguments {
81
+ int syserr_errno;
82
+ char exception_message[MAX_RAISE_MESSAGE_SIZE];
83
+ };
84
+
85
+ static void *trigger_syserr_raise(void *syserr_raise_arguments) {
86
+ struct syserr_raise_arguments *args = (struct syserr_raise_arguments *) syserr_raise_arguments;
87
+ rb_syserr_fail(args->syserr_errno, args->exception_message);
88
+ }
89
+
90
+ void grab_gvl_and_raise_syserr(int syserr_errno, const char *format_string, ...) {
91
+ struct syserr_raise_arguments args;
92
+
93
+ args.syserr_errno = syserr_errno;
94
+
95
+ va_list format_string_arguments;
96
+ va_start(format_string_arguments, format_string);
97
+ vsnprintf(args.exception_message, MAX_RAISE_MESSAGE_SIZE, format_string, format_string_arguments);
98
+
99
+ if (is_current_thread_holding_the_gvl()) {
100
+ rb_raise(
101
+ rb_eRuntimeError,
102
+ "grab_gvl_and_raise_syserr called by thread holding the global VM lock. syserr_errno: %d, exception_message: '%s'",
103
+ syserr_errno,
104
+ args.exception_message
105
+ );
106
+ }
107
+
108
+ rb_thread_call_with_gvl(trigger_syserr_raise, &args);
109
+
110
+ rb_bug("[ddtrace] Unexpected: Reached the end of grab_gvl_and_raise_syserr while raising '%s'\n", args.exception_message);
111
+ }
112
+
113
+ void raise_syserr(
114
+ int syserr_errno,
115
+ bool have_gvl,
116
+ const char *expression,
117
+ const char *file,
118
+ int line,
119
+ const char *function_name
120
+ ) {
121
+ if (have_gvl) {
122
+ rb_exc_raise(rb_syserr_new_str(syserr_errno, rb_sprintf("Failure returned by '%s' at %s:%d:in `%s'", expression, file, line, function_name)));
123
+ } else {
124
+ grab_gvl_and_raise_syserr(syserr_errno, "Failure returned by '%s' at %s:%d:in `%s'", expression, file, line, function_name);
125
+ }
126
+ }
127
+
128
+ char* ruby_strndup(const char *str, size_t size) {
129
+ char *dup;
130
+
131
+ dup = xmalloc(size + 1);
132
+ memcpy(dup, str, size);
133
+ dup[size] = '\0';
134
+
135
+ return dup;
136
+ }
137
+
138
+ static VALUE _id2ref(VALUE obj_id) {
139
+ // Call ::ObjectSpace._id2ref natively. It will raise if the id is no longer valid
140
+ return rb_funcall(module_object_space, _id2ref_id, 1, obj_id);
141
+ }
142
+
143
+ static VALUE _id2ref_failure(DDTRACE_UNUSED VALUE _unused1, DDTRACE_UNUSED VALUE _unused2) {
144
+ return Qfalse;
145
+ }
146
+
147
+ // Native wrapper to get an object ref from an id. Returns true on success and
148
+ // writes the ref to the value pointer parameter if !NULL. False if id doesn't
149
+ // reference a valid object (in which case value is not changed).
150
+ bool ruby_ref_from_id(VALUE obj_id, VALUE *value) {
151
+ // Call ::ObjectSpace._id2ref natively. It will raise if the id is no longer valid
152
+ // so we need to call it via rb_rescue2
153
+ // TODO: Benchmark rb_rescue2 vs rb_protect here
154
+ VALUE result = rb_rescue2(
155
+ _id2ref,
156
+ obj_id,
157
+ _id2ref_failure,
158
+ Qnil,
159
+ rb_eRangeError, // rb_eRangeError is the error used to flag invalid ids
160
+ 0 // Required by API to be the last argument
161
+ );
162
+
163
+ if (result == Qfalse) {
164
+ return false;
165
+ }
166
+
167
+ if (value != NULL) {
168
+ (*value) = result;
169
+ }
170
+
171
+ return true;
172
+ }
173
+
174
+ // Not part of public headers but is externed from Ruby
175
+ size_t rb_obj_memsize_of(VALUE obj);
176
+
177
+ // Wrapper around rb_obj_memsize_of to avoid hitting crashing paths.
178
+ //
179
+ // The crashing paths are due to calls to rb_bug so should hopefully
180
+ // be situations that can't happen. But given that rb_obj_memsize_of
181
+ // isn't fully public (it's externed but not part of public headers)
182
+ // there is a possibility that it is just assumed that whoever calls
183
+ // it, will do proper checking for those cases. We want to be cautious
184
+ // so we'll assume that's the case and will skip over known crashing
185
+ // paths in this wrapper.
186
+ size_t ruby_obj_memsize_of(VALUE obj) {
187
+ switch (rb_type(obj)) {
188
+ case T_OBJECT:
189
+ case T_MODULE:
190
+ case T_CLASS:
191
+ case T_ICLASS:
192
+ case T_STRING:
193
+ case T_ARRAY:
194
+ case T_HASH:
195
+ case T_REGEXP:
196
+ case T_DATA:
197
+ case T_MATCH:
198
+ case T_FILE:
199
+ case T_RATIONAL:
200
+ case T_COMPLEX:
201
+ case T_IMEMO:
202
+ case T_FLOAT:
203
+ case T_SYMBOL:
204
+ case T_BIGNUM:
205
+ // case T_NODE: -> Crashes the vm in rb_obj_memsize_of
206
+ case T_STRUCT:
207
+ case T_ZOMBIE:
208
+ #ifndef NO_T_MOVED
209
+ case T_MOVED:
210
+ #endif
211
+ return rb_obj_memsize_of(obj);
212
+ default:
213
+ // Unsupported, return 0 instead of erroring like rb_obj_memsize_of likes doing
214
+ return 0;
215
+ }
216
+ }
217
+
218
+ // Inspired by rb_class_of but without actually returning classes or potentially doing assertions
219
+ static bool ruby_is_obj_with_class(VALUE obj) {
220
+ if (!RB_SPECIAL_CONST_P(obj)) {
221
+ return true;
222
+ }
223
+ if (obj == RUBY_Qfalse) {
224
+ return true;
225
+ }
226
+ else if (obj == RUBY_Qnil) {
227
+ return true;
228
+ }
229
+ else if (obj == RUBY_Qtrue) {
230
+ return true;
231
+ }
232
+ else if (RB_FIXNUM_P(obj)) {
233
+ return true;
234
+ }
235
+ else if (RB_STATIC_SYM_P(obj)) {
236
+ return true;
237
+ }
238
+ else if (RB_FLONUM_P(obj)) {
239
+ return true;
240
+ }
241
+
242
+ return false;
243
+ }
244
+
245
+ VALUE ruby_safe_inspect(VALUE obj) {
246
+ if (!ruby_is_obj_with_class(obj)) {
247
+ return rb_str_new_cstr("(Not an object)");
248
+ }
249
+
250
+ if (rb_respond_to(obj, inspect_id)) {
251
+ return rb_sprintf("%+"PRIsVALUE, obj);
252
+ } else if (rb_respond_to(obj, to_s_id)) {
253
+ return rb_sprintf("%"PRIsVALUE, obj);
254
+ } else {
255
+ return rb_str_new_cstr("(Not inspectable)");
256
+ }
257
+ }
258
+
259
+ VALUE ddtrace_version(void) {
260
+ VALUE ddtrace_module = rb_const_get(rb_cObject, rb_intern("DDTrace"));
261
+ ENFORCE_TYPE(ddtrace_module, T_MODULE);
262
+ VALUE version_module = rb_const_get(ddtrace_module, rb_intern("VERSION"));
263
+ ENFORCE_TYPE(version_module, T_MODULE);
264
+ VALUE version_string = rb_const_get(version_module, rb_intern("STRING"));
265
+ ENFORCE_TYPE(version_string, T_STRING);
266
+ return version_string;
267
+ }
@@ -5,6 +5,10 @@
5
5
 
6
6
  #include "helpers.h"
7
7
 
8
+ // Initialize internal data needed by some ruby helpers. Should be called during start, before any actual
9
+ // usage of ruby helpers.
10
+ void ruby_helpers_init(void);
11
+
8
12
  // Processes any pending interruptions, including exceptions to be raised.
9
13
  // If there's an exception to be raised, it raises it. In that case, this function does not return.
10
14
  static inline VALUE process_pending_interruptions(DDTRACE_UNUSED VALUE _) {
@@ -78,6 +82,9 @@ NORETURN(
78
82
  #define ENFORCE_SUCCESS_HELPER(expression, have_gvl) \
79
83
  { int result_syserr_errno = expression; if (RB_UNLIKELY(result_syserr_errno)) raise_syserr(result_syserr_errno, have_gvl, ADD_QUOTES(expression), __FILE__, __LINE__, __func__); }
80
84
 
85
+ #define RUBY_NUM_OR_NIL(val, condition, conv) ((val condition) ? conv(val) : Qnil)
86
+ #define RUBY_AVG_OR_NIL(total, count) ((count == 0) ? Qnil : DBL2NUM(((double) total) / count))
87
+
81
88
  // Called by ENFORCE_SUCCESS_HELPER; should not be used directly
82
89
  NORETURN(void raise_syserr(
83
90
  int syserr_errno,
@@ -87,3 +94,29 @@ NORETURN(void raise_syserr(
87
94
  int line,
88
95
  const char *function_name
89
96
  ));
97
+
98
+ // Alternative to ruby_strdup that takes a size argument.
99
+ // Similar to C's strndup but slightly less smart as size is expected to
100
+ // be smaller or equal to the real size of str (minus null termination if it
101
+ // exists).
102
+ // A new string will be returned with size+1 bytes and last byte set to '\0'.
103
+ // The returned string must be freed explicitly.
104
+ //
105
+ // WARN: Cannot be used during GC or outside the GVL.
106
+ char* ruby_strndup(const char *str, size_t size);
107
+
108
+ // Native wrapper to get an object ref from an id. Returns true on success and
109
+ // writes the ref to the value pointer parameter if !NULL. False if id doesn't
110
+ // reference a valid object (in which case value is not changed).
111
+ bool ruby_ref_from_id(size_t id, VALUE *value);
112
+
113
+ // Native wrapper to get the approximate/estimated current size of the passed
114
+ // object.
115
+ size_t ruby_obj_memsize_of(VALUE obj);
116
+
117
+ // Safely inspect any ruby object. If the object responds to 'inspect',
118
+ // return a string with the result of that call. Elsif the object responds to
119
+ // 'to_s', return a string with the result of that call. Otherwise, return Qnil.
120
+ VALUE ruby_safe_inspect(VALUE obj);
121
+
122
+ VALUE ddtrace_version(void);