ddtrace 1.19.0 → 1.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +93 -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 +237 -65
  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_thread_context.c +92 -2
  12. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/extconf.rb +5 -2
  13. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/helpers.h +4 -0
  14. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/http_transport.c +10 -14
  15. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/native_extension_helpers.rb +4 -4
  16. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.c +14 -0
  17. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.h +4 -0
  18. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/profiling.c +17 -1
  19. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.c +10 -0
  20. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.h +2 -0
  21. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.h +2 -0
  22. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +2 -1
  23. data/lib/datadog/core/configuration/components.rb +5 -5
  24. data/lib/datadog/core/configuration/option.rb +1 -1
  25. data/lib/datadog/core/configuration/settings.rb +107 -46
  26. data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
  27. data/lib/datadog/core/environment/class_count.rb +6 -6
  28. data/lib/datadog/core/environment/git.rb +25 -0
  29. data/lib/datadog/core/environment/identity.rb +18 -48
  30. data/lib/datadog/core/git/ext.rb +2 -23
  31. data/lib/datadog/core/remote/component.rb +25 -12
  32. data/lib/datadog/core/remote/ext.rb +1 -0
  33. data/lib/datadog/core/remote/negotiation.rb +2 -2
  34. data/lib/datadog/core/remote/tie/tracing.rb +39 -0
  35. data/lib/datadog/core/remote/tie.rb +27 -0
  36. data/lib/datadog/core/remote/worker.rb +7 -4
  37. data/lib/datadog/core/transport/ext.rb +2 -0
  38. data/lib/datadog/core/utils/url.rb +25 -0
  39. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -2
  40. data/lib/datadog/opentelemetry.rb +3 -0
  41. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -2
  42. data/lib/datadog/profiling/collectors/info.rb +101 -0
  43. data/lib/datadog/profiling/component.rb +14 -30
  44. data/lib/datadog/profiling/exporter.rb +19 -5
  45. data/lib/datadog/profiling/ext.rb +2 -0
  46. data/lib/datadog/profiling/flush.rb +6 -3
  47. data/lib/datadog/profiling/http_transport.rb +5 -1
  48. data/lib/datadog/profiling/load_native_extension.rb +5 -5
  49. data/lib/datadog/profiling/native_extension.rb +1 -1
  50. data/lib/datadog/profiling/tag_builder.rb +5 -0
  51. data/lib/datadog/profiling/tasks/exec.rb +3 -3
  52. data/lib/datadog/profiling/tasks/help.rb +3 -3
  53. data/lib/datadog/profiling.rb +2 -2
  54. data/lib/datadog/tracing/configuration/ext.rb +0 -1
  55. data/lib/datadog/tracing/configuration/settings.rb +2 -1
  56. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +1 -0
  57. data/lib/datadog/tracing/contrib/action_cable/ext.rb +1 -0
  58. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +1 -0
  59. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +1 -0
  60. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -0
  61. data/lib/datadog/tracing/contrib/action_pack/ext.rb +1 -0
  62. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +1 -0
  63. data/lib/datadog/tracing/contrib/action_view/ext.rb +1 -0
  64. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -0
  65. data/lib/datadog/tracing/contrib/active_job/ext.rb +1 -0
  66. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +1 -0
  67. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +1 -0
  68. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -0
  69. data/lib/datadog/tracing/contrib/active_record/ext.rb +1 -0
  70. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -0
  71. data/lib/datadog/tracing/contrib/active_support/ext.rb +1 -0
  72. data/lib/datadog/tracing/contrib/analytics.rb +0 -1
  73. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -0
  74. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  75. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
  76. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +11 -1
  77. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -0
  78. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  79. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -0
  80. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +1 -0
  81. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -0
  82. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
  83. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -0
  84. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  85. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -0
  86. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  87. data/lib/datadog/tracing/contrib/extensions.rb +6 -2
  88. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -0
  89. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  90. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -1
  91. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +1 -0
  92. data/lib/datadog/tracing/contrib/grape/endpoint.rb +5 -0
  93. data/lib/datadog/tracing/contrib/grape/ext.rb +1 -0
  94. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -0
  95. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  96. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -0
  97. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  98. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -0
  99. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +2 -2
  100. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  101. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -0
  102. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  103. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -0
  104. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  105. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +1 -0
  106. data/lib/datadog/tracing/contrib/kafka/ext.rb +1 -0
  107. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -0
  108. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  109. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -0
  110. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  111. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -0
  112. data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -0
  113. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -0
  114. data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
  115. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +11 -4
  116. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -0
  117. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  118. data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +1 -0
  119. data/lib/datadog/tracing/contrib/qless/ext.rb +1 -0
  120. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -0
  121. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  122. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -0
  123. data/lib/datadog/tracing/contrib/racecar/ext.rb +1 -0
  124. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -0
  125. data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
  126. data/lib/datadog/tracing/contrib/rack/middlewares.rb +37 -6
  127. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -0
  128. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  129. data/lib/datadog/tracing/contrib/rails/patcher.rb +16 -0
  130. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -0
  131. data/lib/datadog/tracing/contrib/rake/ext.rb +1 -0
  132. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -0
  133. data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
  134. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +2 -2
  135. data/lib/datadog/tracing/contrib/redis/patcher.rb +34 -21
  136. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -0
  137. data/lib/datadog/tracing/contrib/resque/ext.rb +1 -0
  138. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -0
  139. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  140. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +1 -0
  141. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  142. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +1 -0
  143. data/lib/datadog/tracing/contrib/sequel/ext.rb +1 -0
  144. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -0
  145. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +1 -0
  146. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
  147. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  148. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -0
  149. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  150. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +6 -3
  151. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -0
  152. data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
  153. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +1 -0
  154. data/lib/datadog/tracing/contrib/stripe/ext.rb +1 -0
  155. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +1 -0
  156. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +1 -0
  157. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +58 -0
  158. data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
  159. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +94 -0
  160. data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
  161. data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
  162. data/lib/datadog/tracing/contrib.rb +1 -0
  163. data/lib/datadog/tracing/metadata/ext.rb +2 -0
  164. data/lib/datadog/tracing/trace_operation.rb +1 -2
  165. data/lib/datadog/tracing/transport/http.rb +1 -0
  166. data/lib/datadog/tracing/transport/trace_formatter.rb +31 -0
  167. data/lib/datadog/tracing.rb +8 -2
  168. data/lib/ddtrace/version.rb +1 -1
  169. metadata +62 -50
  170. data/ext/ddtrace_profiling_native_extension/pid_controller.c +0 -57
  171. data/ext/ddtrace_profiling_native_extension/pid_controller.h +0 -45
  172. data/lib/datadog/profiling/diagnostics/environment_logger.rb +0 -39
  173. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/NativeExtensionDesign.md +0 -0
  174. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id.h +0 -0
  175. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_from_pthread.c +0 -0
  176. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_noop.c +0 -0
  177. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.c +0 -0
  178. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.h +0 -0
  179. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_gc_profiling_helper.c +0 -0
  180. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_gc_profiling_helper.h +0 -0
  181. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.c +0 -0
  182. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.h +0 -0
  183. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.c +0 -0
  184. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.h +0 -0
  185. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.h +0 -0
  186. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/heap_recorder.c +0 -0
  187. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/heap_recorder.h +0 -0
  188. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.c +0 -0
  189. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.h +0 -0
  190. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.c +0 -0
  191. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.h +0 -0
  192. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.c +0 -0
  193. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.h +0 -0
  194. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.c +0 -0
@@ -82,6 +82,9 @@ static ID at_id_id; // id of :@id in Ruby
82
82
  static ID at_resource_id; // id of :@resource in Ruby
83
83
  static ID at_root_span_id; // id of :@root_span in Ruby
84
84
  static ID at_type_id; // id of :@type in Ruby
85
+ static ID at_otel_values_id; // id of :@otel_values in Ruby
86
+ static ID at_parent_span_id_id; // id of :@parent_span_id in Ruby
87
+ static ID at_datadog_trace_id; // id of :@datadog_trace in Ruby
85
88
 
86
89
  // Contains state for a single ThreadContext instance
87
90
  struct thread_context_collector_state {
@@ -114,6 +117,8 @@ struct thread_context_collector_state {
114
117
  monotonic_to_system_epoch_state time_converter_state;
115
118
  // Used to identify the main thread, to give it a fallback name
116
119
  VALUE main_thread;
120
+ // Used when extracting trace identifiers from otel spans. Lazily initialized.
121
+ VALUE otel_current_span_key;
117
122
 
118
123
  struct stats {
119
124
  // Track how many garbage collection samples we've taken.
@@ -218,6 +223,14 @@ static VALUE thread_list(struct thread_context_collector_state *state);
218
223
  static VALUE _native_sample_allocation(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE sample_weight, VALUE new_object);
219
224
  static VALUE _native_new_empty_thread(VALUE self);
220
225
  static ddog_CharSlice ruby_value_type_to_class_name(enum ruby_value_type type);
226
+ static void ddtrace_otel_trace_identifiers_for(
227
+ struct thread_context_collector_state *state,
228
+ VALUE *active_trace,
229
+ VALUE *root_span,
230
+ VALUE *numeric_span_id,
231
+ VALUE active_span,
232
+ VALUE otel_values
233
+ );
221
234
 
222
235
  void collectors_thread_context_init(VALUE profiling_module) {
223
236
  VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
@@ -255,6 +268,9 @@ void collectors_thread_context_init(VALUE profiling_module) {
255
268
  at_resource_id = rb_intern_const("@resource");
256
269
  at_root_span_id = rb_intern_const("@root_span");
257
270
  at_type_id = rb_intern_const("@type");
271
+ at_otel_values_id = rb_intern_const("@otel_values");
272
+ at_parent_span_id_id = rb_intern_const("@parent_span_id");
273
+ at_datadog_trace_id = rb_intern_const("@datadog_trace");
258
274
 
259
275
  gc_profiling_init();
260
276
  }
@@ -282,6 +298,7 @@ static void thread_context_collector_typed_data_mark(void *state_ptr) {
282
298
  st_foreach(state->hash_map_per_thread_context, hash_map_per_thread_context_mark, 0 /* unused */);
283
299
  rb_gc_mark(state->thread_list_buffer);
284
300
  rb_gc_mark(state->main_thread);
301
+ rb_gc_mark(state->otel_current_span_key);
285
302
  }
286
303
 
287
304
  static void thread_context_collector_typed_data_free(void *state_ptr) {
@@ -334,6 +351,7 @@ static VALUE _native_new(VALUE klass) {
334
351
  state->allocation_type_enabled = true;
335
352
  state->time_converter_state = (monotonic_to_system_epoch_state) MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER;
336
353
  state->main_thread = rb_thread_main();
354
+ state->otel_current_span_key = Qnil;
337
355
  state->gc_tracking.wall_time_at_previous_gc_ns = INVALID_TIME;
338
356
  state->gc_tracking.wall_time_at_last_flushed_gc_event_ns = 0;
339
357
 
@@ -917,6 +935,7 @@ static VALUE _native_inspect(DDTRACE_UNUSED VALUE _self, VALUE collector_instanc
917
935
  ));
918
936
  rb_str_concat(result, rb_sprintf(" main_thread=%"PRIsVALUE, state->main_thread));
919
937
  rb_str_concat(result, rb_sprintf(" gc_tracking=%"PRIsVALUE, gc_tracking_as_ruby_hash(state)));
938
+ rb_str_concat(result, rb_sprintf(" otel_current_span_key=%"PRIsVALUE, state->otel_current_span_key));
920
939
 
921
940
  return result;
922
941
  }
@@ -1104,10 +1123,19 @@ static void trace_identifiers_for(struct thread_context_collector_state *state,
1104
1123
 
1105
1124
  VALUE root_span = rb_ivar_get(active_trace, at_root_span_id /* @root_span */);
1106
1125
  VALUE active_span = rb_ivar_get(active_trace, at_active_span_id /* @active_span */);
1107
- if (root_span == Qnil || active_span == Qnil) return;
1126
+ // Note: On Ruby 3.x `rb_attr_get` is exactly the same as `rb_ivar_get`. For Ruby 2.x, the difference is that
1127
+ // `rb_ivar_get` can trigger "warning: instance variable @otel_values not initialized" if warnings are enabled and
1128
+ // opentelemetry is not in use, whereas `rb_attr_get` does the lookup without generating the warning.
1129
+ VALUE otel_values = rb_attr_get(active_trace, at_otel_values_id /* @otel_values */);
1130
+
1131
+ VALUE numeric_span_id = Qnil;
1132
+
1133
+ if (otel_values != Qnil) ddtrace_otel_trace_identifiers_for(state, &active_trace, &root_span, &numeric_span_id, active_span, otel_values);
1134
+
1135
+ if (root_span == Qnil || (active_span == Qnil && numeric_span_id == Qnil)) return;
1108
1136
 
1109
1137
  VALUE numeric_local_root_span_id = rb_ivar_get(root_span, at_id_id /* @id */);
1110
- VALUE numeric_span_id = rb_ivar_get(active_span, at_id_id /* @id */);
1138
+ if (active_span != Qnil && numeric_span_id == Qnil) numeric_span_id = rb_ivar_get(active_span, at_id_id /* @id */);
1111
1139
  if (numeric_local_root_span_id == Qnil || numeric_span_id == Qnil) return;
1112
1140
 
1113
1141
  trace_identifiers_result->local_root_span_id = NUM2ULL(numeric_local_root_span_id);
@@ -1299,3 +1327,65 @@ static ddog_CharSlice ruby_value_type_to_class_name(enum ruby_value_type type) {
1299
1327
  default: return DDOG_CHARSLICE_C("(VM Internal, Missing class)");
1300
1328
  }
1301
1329
  }
1330
+
1331
+ static VALUE get_otel_current_span_key(struct thread_context_collector_state *state) {
1332
+ if (state->otel_current_span_key == Qnil) {
1333
+ VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
1334
+ VALUE opentelemetry_module = rb_const_get(datadog_module, rb_intern("OpenTelemetry"));
1335
+ VALUE api_module = rb_const_get(opentelemetry_module, rb_intern("API"));
1336
+ VALUE context_module = rb_const_get(api_module, rb_intern_const("Context"));
1337
+ VALUE current_span_key = rb_const_get(context_module, rb_intern_const("CURRENT_SPAN_KEY"));
1338
+
1339
+ if (current_span_key == Qnil) {
1340
+ rb_raise(rb_eRuntimeError, "Unexpected: Missing Datadog::OpenTelemetry::API::Context::CURRENT_SPAN_KEY");
1341
+ }
1342
+
1343
+ state->otel_current_span_key = current_span_key;
1344
+ }
1345
+
1346
+ return state->otel_current_span_key;
1347
+ }
1348
+
1349
+ // This method gets used when ddtrace is being used indirectly via the otel APIs. Information gets stored slightly
1350
+ // differently, and this codepath handles it.
1351
+ static void ddtrace_otel_trace_identifiers_for(
1352
+ struct thread_context_collector_state *state,
1353
+ VALUE *active_trace,
1354
+ VALUE *root_span,
1355
+ VALUE *numeric_span_id,
1356
+ VALUE active_span,
1357
+ VALUE otel_values
1358
+ ) {
1359
+ VALUE resolved_numeric_span_id =
1360
+ active_span == Qnil ?
1361
+ // For traces started from otel spans, the span id will be empty, and the @parent_span_id has the right value
1362
+ rb_ivar_get(*active_trace, at_parent_span_id_id /* @parent_span_id */) :
1363
+ // Regular span created by ddtrace
1364
+ rb_ivar_get(active_span, at_id_id /* @id */);
1365
+
1366
+ if (resolved_numeric_span_id == Qnil) return;
1367
+
1368
+ VALUE otel_current_span_key = get_otel_current_span_key(state);
1369
+ VALUE current_trace = *active_trace;
1370
+
1371
+ // ddtrace uses a different structure when spans are created from otel, where each otel span will have a unique ddtrace
1372
+ // trace and span representing it. Each ddtrace trace is then connected to the previous otel span, forming a linked
1373
+ // list. The local root span is going to be the trace/span we find at the end of this linked list.
1374
+ while (otel_values != Qnil) {
1375
+ VALUE otel_span = rb_hash_lookup(otel_values, otel_current_span_key);
1376
+ if (otel_span == Qnil) break;
1377
+ VALUE next_trace = rb_ivar_get(otel_span, at_datadog_trace_id);
1378
+ if (next_trace == Qnil) break;
1379
+
1380
+ current_trace = next_trace;
1381
+ otel_values = rb_ivar_get(current_trace, at_otel_values_id /* @otel_values */);
1382
+ }
1383
+
1384
+ // We found the last trace in the linked list. This contains the local root span
1385
+ VALUE resolved_root_span = rb_ivar_get(current_trace, at_root_span_id /* @root_span */);
1386
+ if (resolved_root_span == Qnil) return;
1387
+
1388
+ *root_span = resolved_root_span;
1389
+ *active_trace = current_trace;
1390
+ *numeric_span_id = resolved_numeric_span_id;
1391
+ }
@@ -100,7 +100,7 @@ add_compiler_flag '-Wno-declaration-after-statement'
100
100
  add_compiler_flag '-Werror-implicit-function-declaration'
101
101
 
102
102
  # The native extension is not intended to expose any symbols/functions for other native libraries to use;
103
- # the sole exception being `Init_ddtrace_profiling_native_extension` which needs to be visible for Ruby to call it when
103
+ # the sole exception being `Init_datadog_profiling_native_extension` which needs to be visible for Ruby to call it when
104
104
  # it `dlopen`s the library.
105
105
  #
106
106
  # By setting this compiler flag, we tell it to assume that everything is private unless explicitly stated.
@@ -115,6 +115,7 @@ add_compiler_flag '-Wall'
115
115
  add_compiler_flag '-Wextra'
116
116
 
117
117
  if ENV['DDTRACE_DEBUG']
118
+ $defs << '-DDD_DEBUG'
118
119
  CONFIG['optflags'] = '-O0'
119
120
  CONFIG['debugflags'] = '-ggdb3'
120
121
  end
@@ -130,6 +131,8 @@ if RUBY_PLATFORM.include?('linux')
130
131
  $defs << '-DHAVE_PTHREAD_GETCPUCLOCKID'
131
132
  end
132
133
 
134
+ have_func 'malloc_stats'
135
+
133
136
  # On older Rubies, rb_postponed_job_preregister/rb_postponed_job_trigger did not exist
134
137
  $defs << '-DNO_POSTPONED_TRIGGER' if RUBY_VERSION < '3.3'
135
138
 
@@ -234,7 +237,7 @@ Logging.message("[ddtrace] After pkg-config $LDFLAGS were set to: #{$LDFLAGS.ins
234
237
  # This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
235
238
  # the wrong library is never loaded.
236
239
  # When requiring, we need to use the exact same string, including the version and the platform.
237
- EXTENSION_NAME = "ddtrace_profiling_native_extension.#{RUBY_VERSION}_#{RUBY_PLATFORM}".freeze
240
+ EXTENSION_NAME = "datadog_profiling_native_extension.#{RUBY_VERSION}_#{RUBY_PLATFORM}".freeze
238
241
 
239
242
  if Datadog::Profiling::NativeExtensionHelpers::CAN_USE_MJIT_HEADER
240
243
  mjit_header_file_name = "rb_mjit_min_header-#{RUBY_VERSION}.h"
@@ -1,5 +1,7 @@
1
1
  #pragma once
2
2
 
3
+ #include <stdint.h>
4
+
3
5
  // Used to mark symbols to be exported to the outside of the extension.
4
6
  // Consider very carefully before tagging a function with this.
5
7
  #define DDTRACE_EXPORT __attribute__ ((visibility ("default")))
@@ -17,3 +19,5 @@ inline static uint64_t uint64_max_of(uint64_t a, uint64_t b) { return a > b ? a
17
19
  inline static uint64_t uint64_min_of(uint64_t a, uint64_t b) { return a > b ? b : a; }
18
20
  inline static long long_max_of(long a, long b) { return a > b ? a : b; }
19
21
  inline static long long_min_of(long a, long b) { return a > b ? b : a; }
22
+ inline static double double_max_of(double a, double b) { return a > b ? a : b; }
23
+ inline static double double_min_of(double a, double b) { return a > b ? b : a; }
@@ -46,17 +46,17 @@ static VALUE _native_do_export(
46
46
  VALUE code_provenance_file_name,
47
47
  VALUE code_provenance_data,
48
48
  VALUE tags_as_array,
49
- VALUE internal_metadata_json
49
+ VALUE internal_metadata_json,
50
+ VALUE info_json
50
51
  );
51
52
  static void *call_exporter_without_gvl(void *call_args);
52
53
  static void interrupt_exporter_call(void *cancel_token);
53
- static VALUE ddtrace_version(void);
54
54
 
55
55
  void http_transport_init(VALUE profiling_module) {
56
56
  VALUE http_transport_class = rb_define_class_under(profiling_module, "HttpTransport", rb_cObject);
57
57
 
58
58
  rb_define_singleton_method(http_transport_class, "_native_validate_exporter", _native_validate_exporter, 1);
59
- rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 12);
59
+ rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 13);
60
60
 
61
61
  ok_symbol = ID2SYM(rb_intern_const("ok"));
62
62
  error_symbol = ID2SYM(rb_intern_const("error"));
@@ -208,6 +208,7 @@ static VALUE perform_export(
208
208
  ddog_prof_Exporter_Slice_File files_to_export_unmodified,
209
209
  ddog_Vec_Tag *additional_tags,
210
210
  ddog_CharSlice internal_metadata,
211
+ ddog_CharSlice info,
211
212
  uint64_t timeout_milliseconds
212
213
  ) {
213
214
  ddog_prof_ProfiledEndpointsStats *endpoints_stats = NULL; // Not in use yet
@@ -220,6 +221,7 @@ static VALUE perform_export(
220
221
  additional_tags,
221
222
  endpoints_stats,
222
223
  &internal_metadata,
224
+ &info,
223
225
  timeout_milliseconds
224
226
  );
225
227
 
@@ -290,7 +292,8 @@ static VALUE _native_do_export(
290
292
  VALUE code_provenance_file_name,
291
293
  VALUE code_provenance_data,
292
294
  VALUE tags_as_array,
293
- VALUE internal_metadata_json
295
+ VALUE internal_metadata_json,
296
+ VALUE info_json
294
297
  ) {
295
298
  ENFORCE_TYPE(upload_timeout_milliseconds, T_FIXNUM);
296
299
  ENFORCE_TYPE(start_timespec_seconds, T_FIXNUM);
@@ -301,6 +304,7 @@ static VALUE _native_do_export(
301
304
  ENFORCE_TYPE(pprof_data, T_STRING);
302
305
  ENFORCE_TYPE(code_provenance_file_name, T_STRING);
303
306
  ENFORCE_TYPE(internal_metadata_json, T_STRING);
307
+ ENFORCE_TYPE(info_json, T_STRING);
304
308
 
305
309
  // Code provenance can be disabled and in that case will be set to nil
306
310
  bool have_code_provenance = !NIL_P(code_provenance_data);
@@ -335,6 +339,7 @@ static VALUE _native_do_export(
335
339
 
336
340
  ddog_Vec_Tag *null_additional_tags = NULL;
337
341
  ddog_CharSlice internal_metadata = char_slice_from_ruby_string(internal_metadata_json);
342
+ ddog_CharSlice info = char_slice_from_ruby_string(info_json);
338
343
 
339
344
  ddog_prof_Exporter_NewResult exporter_result = create_exporter(exporter_configuration, tags_as_array);
340
345
  // Note: Do not add anything that can raise exceptions after this line, as otherwise the exporter memory will leak
@@ -350,6 +355,7 @@ static VALUE _native_do_export(
350
355
  files_to_export_unmodified,
351
356
  null_additional_tags,
352
357
  internal_metadata,
358
+ info,
353
359
  timeout_milliseconds
354
360
  );
355
361
  }
@@ -367,13 +373,3 @@ static void *call_exporter_without_gvl(void *call_args) {
367
373
  static void interrupt_exporter_call(void *cancel_token) {
368
374
  ddog_CancellationToken_cancel((ddog_CancellationToken *) cancel_token);
369
375
  }
370
-
371
- static VALUE ddtrace_version(void) {
372
- VALUE ddtrace_module = rb_const_get(rb_cObject, rb_intern("DDTrace"));
373
- ENFORCE_TYPE(ddtrace_module, T_MODULE);
374
- VALUE version_module = rb_const_get(ddtrace_module, rb_intern("VERSION"));
375
- ENFORCE_TYPE(version_module, T_MODULE);
376
- VALUE version_string = rb_const_get(version_module, rb_intern("STRING"));
377
- ENFORCE_TYPE(version_string, T_STRING);
378
- return version_string;
379
- }
@@ -15,7 +15,7 @@ module Datadog
15
15
  # The MJIT header was introduced on 2.6 and removed on 3.3; for other Rubies we rely on debase-ruby_core_source
16
16
  CAN_USE_MJIT_HEADER = RUBY_VERSION.start_with?('2.6', '2.7', '3.0.', '3.1.', '3.2.')
17
17
 
18
- LIBDATADOG_VERSION = '~> 5.0.0.1.0'
18
+ LIBDATADOG_VERSION = '~> 6.0.0.2.0'
19
19
 
20
20
  def self.fail_install_if_missing_extension?
21
21
  ENV[ENV_FAIL_INSTALL_IF_MISSING_EXTENSION].to_s.strip.downcase == 'true'
@@ -29,7 +29,7 @@ module Datadog
29
29
  # native extension), we need to add a "runpath" -- a list of folders to search for libdatadog.
30
30
  #
31
31
  # This runpath gets hardcoded at native library linking time. You can look at it using the `readelf` tool in
32
- # Linux: e.g. `readelf -d ddtrace_profiling_native_extension.2.7.3_x86_64-linux.so`.
32
+ # Linux: e.g. `readelf -d datadog_profiling_native_extension.2.7.3_x86_64-linux.so`.
33
33
  #
34
34
  # In older versions of ddtrace, we only set as runpath an absolute path to libdatadog.
35
35
  # (This gets set automatically by the call
@@ -305,8 +305,8 @@ module Datadog
305
305
  no_binaries_for_current_platform = explain_issue(
306
306
  'the `libdatadog` gem installed on your system is missing binaries for your',
307
307
  'platform variant.',
308
- "(Your platform: `#{Gem::Platform.local}`)",
309
- '(Available binaries: ',
308
+ "(Your platform: `#{Libdatadog.current_platform}`)",
309
+ '(Available binaries:',
310
310
  "`#{Libdatadog.available_binaries.join('`, `')}`)",
311
311
  suggested: CONTACT_SUPPORT,
312
312
  )
@@ -876,3 +876,17 @@ static inline int ddtrace_imemo_type(VALUE imemo) {
876
876
  return NULL;
877
877
  }
878
878
  #endif
879
+
880
+ // This is used to workaround a VM bug. See "handle_sampling_signal" in "collectors_cpu_and_wall_time_worker" for details.
881
+ #ifdef NO_POSTPONED_TRIGGER
882
+ void *objspace_ptr_for_gc_finalize_deferred_workaround(void) {
883
+ rb_vm_t *vm =
884
+ #ifndef NO_GET_VM // TODO: Inline GET_VM below once we drop support in dd-trace-rb 2.x for < Ruby 2.5
885
+ GET_VM();
886
+ #else
887
+ thread_struct_from_object(rb_thread_current())->vm;
888
+ #endif
889
+
890
+ return vm->objspace;
891
+ }
892
+ #endif
@@ -55,3 +55,7 @@ void self_test_mn_enabled(void);
55
55
 
56
56
  // Provides more specific information on what kind an imemo is
57
57
  const char *imemo_kind(VALUE imemo);
58
+
59
+ #ifdef NO_POSTPONED_TRIGGER
60
+ void *objspace_ptr_for_gc_finalize_deferred_workaround(void);
61
+ #endif
@@ -1,6 +1,9 @@
1
1
  #include <ruby.h>
2
2
  #include <ruby/thread.h>
3
3
  #include <errno.h>
4
+ #ifdef HAVE_MALLOC_STATS
5
+ #include <malloc.h>
6
+ #endif
4
7
 
5
8
  #include "clock_id.h"
6
9
  #include "helpers.h"
@@ -11,6 +14,7 @@
11
14
 
12
15
  // Each class/module here is implemented in their separate file
13
16
  void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module);
17
+ void collectors_discrete_dynamic_sampler_init(VALUE profiling_module);
14
18
  void collectors_dynamic_sampling_rate_init(VALUE profiling_module);
15
19
  void collectors_idle_sampling_helper_init(VALUE profiling_module);
16
20
  void collectors_stack_init(VALUE profiling_module);
@@ -32,8 +36,9 @@ static void holding_the_gvl_signal_handler(DDTRACE_UNUSED int _signal, DDTRACE_U
32
36
  static VALUE _native_trigger_holding_the_gvl_signal_handler_on(DDTRACE_UNUSED VALUE _self, VALUE background_thread);
33
37
  static VALUE _native_enforce_success(DDTRACE_UNUSED VALUE _self, VALUE syserr_errno, VALUE with_gvl);
34
38
  static void *trigger_enforce_success(void *trigger_args);
39
+ static VALUE _native_malloc_stats(DDTRACE_UNUSED VALUE _self);
35
40
 
36
- void DDTRACE_EXPORT Init_ddtrace_profiling_native_extension(void) {
41
+ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
37
42
  VALUE datadog_module = rb_define_module("Datadog");
38
43
  VALUE profiling_module = rb_define_module_under(datadog_module, "Profiling");
39
44
  VALUE native_extension_module = rb_define_module_under(profiling_module, "NativeExtension");
@@ -43,6 +48,7 @@ void DDTRACE_EXPORT Init_ddtrace_profiling_native_extension(void) {
43
48
 
44
49
  ruby_helpers_init();
45
50
  collectors_cpu_and_wall_time_worker_init(profiling_module);
51
+ collectors_discrete_dynamic_sampler_init(profiling_module);
46
52
  collectors_dynamic_sampling_rate_init(profiling_module);
47
53
  collectors_idle_sampling_helper_init(profiling_module);
48
54
  collectors_stack_init(profiling_module);
@@ -65,6 +71,7 @@ void DDTRACE_EXPORT Init_ddtrace_profiling_native_extension(void) {
65
71
  rb_define_singleton_method(testing_module, "_native_install_holding_the_gvl_signal_handler", _native_install_holding_the_gvl_signal_handler, 0);
66
72
  rb_define_singleton_method(testing_module, "_native_trigger_holding_the_gvl_signal_handler_on", _native_trigger_holding_the_gvl_signal_handler_on, 1);
67
73
  rb_define_singleton_method(testing_module, "_native_enforce_success", _native_enforce_success, 2);
74
+ rb_define_singleton_method(testing_module, "_native_malloc_stats", _native_malloc_stats, 0);
68
75
  }
69
76
 
70
77
  static VALUE native_working_p(DDTRACE_UNUSED VALUE _self) {
@@ -249,3 +256,12 @@ static void *trigger_enforce_success(void *trigger_args) {
249
256
  ENFORCE_SUCCESS_NO_GVL(syserr_errno);
250
257
  return NULL;
251
258
  }
259
+
260
+ static VALUE _native_malloc_stats(DDTRACE_UNUSED VALUE _self) {
261
+ #ifdef HAVE_MALLOC_STATS
262
+ malloc_stats();
263
+ return Qtrue;
264
+ #else
265
+ return Qfalse;
266
+ #endif
267
+ }
@@ -255,3 +255,13 @@ VALUE ruby_safe_inspect(VALUE obj) {
255
255
  return rb_str_new_cstr("(Not inspectable)");
256
256
  }
257
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
+ }
@@ -115,3 +115,5 @@ size_t ruby_obj_memsize_of(VALUE obj);
115
115
  // return a string with the result of that call. Elsif the object responds to
116
116
  // 'to_s', return a string with the result of that call. Otherwise, return Qnil.
117
117
  VALUE ruby_safe_inspect(VALUE obj);
118
+
119
+ VALUE ddtrace_version(void);
@@ -1,5 +1,7 @@
1
1
  #pragma once
2
2
 
3
+ #include <stdbool.h>
4
+
3
5
  #define SECONDS_AS_NS(value) (value * 1000 * 1000 * 1000L)
4
6
  #define MILLIS_AS_NS(value) (value * 1000 * 1000L)
5
7
 
@@ -26,7 +26,8 @@ module Datadog
26
26
  def call(env)
27
27
  return @app.call(env) unless Datadog::AppSec.enabled?
28
28
 
29
- Datadog::Core::Remote.active_remote.barrier(:once) unless Datadog::Core::Remote.active_remote.nil?
29
+ boot = Datadog::Core::Remote::Tie.boot
30
+ Datadog::Core::Remote::Tie::Tracing.tag(boot, active_span)
30
31
 
31
32
  processor = nil
32
33
  ready = false
@@ -81,6 +81,7 @@ module Datadog
81
81
 
82
82
  def initialize(settings)
83
83
  @logger = self.class.build_logger(settings)
84
+ @environment_logger_extra = {}
84
85
 
85
86
  # This agent_settings is intended for use within Core. If you require
86
87
  # agent_settings within a product outside of core you should extend
@@ -90,11 +91,13 @@ module Datadog
90
91
  @remote = Remote::Component.build(settings, agent_settings)
91
92
  @tracer = self.class.build_tracer(settings, logger: @logger)
92
93
 
93
- @profiler = Datadog::Profiling::Component.build_profiler_component(
94
+ @profiler, profiler_logger_extra = Datadog::Profiling::Component.build_profiler_component(
94
95
  settings: settings,
95
96
  agent_settings: agent_settings,
96
97
  optional_tracer: @tracer,
97
98
  )
99
+ @environment_logger_extra.merge!(profiler_logger_extra) if profiler_logger_extra
100
+
98
101
  @runtime_metrics = self.class.build_runtime_metrics_worker(settings)
99
102
  @health_metrics = self.class.build_health_metrics(settings)
100
103
  @telemetry = self.class.build_telemetry(settings, agent_settings, logger)
@@ -105,18 +108,15 @@ module Datadog
105
108
  def startup!(settings)
106
109
  if settings.profiling.enabled
107
110
  if profiler
108
- @logger.debug('Profiling started')
109
111
  profiler.start
110
112
  else
111
113
  # Display a warning for users who expected profiling to be enabled
112
114
  unsupported_reason = Profiling.unsupported_reason
113
115
  logger.warn("Profiling was requested but is not supported, profiling disabled: #{unsupported_reason}")
114
116
  end
115
- else
116
- @logger.debug('Profiling is disabled')
117
117
  end
118
118
 
119
- Core::Diagnostics::EnvironmentLogger.collect_and_log!
119
+ Core::Diagnostics::EnvironmentLogger.collect_and_log!(@environment_logger_extra)
120
120
  end
121
121
 
122
122
  # Shuts down all the components in use.
@@ -264,7 +264,7 @@ module Datadog
264
264
  # when restoring a value from `@value_per_precedence`, and we are only running `definition.setter`
265
265
  # on the original value, not on a valud that has already been processed by `definition.setter`.
266
266
  @value_per_precedence[precedence] = value
267
- context_exec(v, old_value, &definition.after_set) if definition.after_set
267
+ context_exec(v, old_value, precedence, &definition.after_set) if definition.after_set
268
268
  end
269
269
  end
270
270