datadog 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +87 -2
  3. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
  4. data/ext/datadog_profiling_loader/extconf.rb +14 -26
  5. data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
  6. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
  7. data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
  8. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +257 -69
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +53 -28
  10. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
  11. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
  12. data/ext/datadog_profiling_native_extension/collectors_stack.c +136 -81
  13. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +661 -48
  15. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -1
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +83 -0
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +53 -0
  18. data/ext/datadog_profiling_native_extension/extconf.rb +91 -69
  19. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
  20. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
  21. data/ext/datadog_profiling_native_extension/heap_recorder.c +54 -12
  22. data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
  23. data/ext/datadog_profiling_native_extension/helpers.h +6 -17
  24. data/ext/datadog_profiling_native_extension/http_transport.c +41 -9
  25. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
  27. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -172
  28. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +116 -139
  29. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +20 -11
  30. data/ext/datadog_profiling_native_extension/profiling.c +1 -3
  31. data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
  32. data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
  33. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
  34. data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
  35. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
  36. data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
  37. data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
  38. data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +37 -22
  39. data/ext/libdatadog_api/datadog_ruby_common.c +83 -0
  40. data/ext/libdatadog_api/datadog_ruby_common.h +53 -0
  41. data/ext/libdatadog_api/extconf.rb +108 -0
  42. data/ext/libdatadog_api/macos_development.md +26 -0
  43. data/ext/libdatadog_extconf_helpers.rb +130 -0
  44. data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
  45. data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
  46. data/lib/datadog/appsec/component.rb +29 -8
  47. data/lib/datadog/appsec/configuration/settings.rb +2 -2
  48. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
  49. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
  50. data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
  51. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +35 -0
  52. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
  53. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +71 -0
  54. data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -0
  55. data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
  56. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
  57. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +3 -6
  58. data/lib/datadog/appsec/event.rb +1 -1
  59. data/lib/datadog/appsec/processor/actions.rb +1 -1
  60. data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
  61. data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
  62. data/lib/datadog/appsec/processor.rb +36 -37
  63. data/lib/datadog/appsec/rate_limiter.rb +25 -40
  64. data/lib/datadog/appsec/remote.rb +7 -3
  65. data/lib/datadog/appsec/response.rb +15 -1
  66. data/lib/datadog/appsec.rb +3 -2
  67. data/lib/datadog/core/configuration/components.rb +18 -15
  68. data/lib/datadog/core/configuration/settings.rb +135 -9
  69. data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
  70. data/lib/datadog/core/crashtracking/component.rb +111 -0
  71. data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
  72. data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
  73. data/lib/datadog/core/environment/execution.rb +5 -5
  74. data/lib/datadog/core/metrics/client.rb +7 -0
  75. data/lib/datadog/core/rate_limiter.rb +183 -0
  76. data/lib/datadog/core/remote/client/capabilities.rb +4 -3
  77. data/lib/datadog/core/remote/component.rb +4 -2
  78. data/lib/datadog/core/remote/negotiation.rb +4 -4
  79. data/lib/datadog/core/remote/tie.rb +2 -0
  80. data/lib/datadog/core/runtime/metrics.rb +1 -1
  81. data/lib/datadog/core/telemetry/component.rb +51 -2
  82. data/lib/datadog/core/telemetry/emitter.rb +9 -11
  83. data/lib/datadog/core/telemetry/event.rb +37 -1
  84. data/lib/datadog/core/telemetry/ext.rb +1 -0
  85. data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
  86. data/lib/datadog/core/telemetry/http/ext.rb +3 -0
  87. data/lib/datadog/core/telemetry/http/transport.rb +38 -9
  88. data/lib/datadog/core/telemetry/logger.rb +51 -0
  89. data/lib/datadog/core/telemetry/logging.rb +71 -0
  90. data/lib/datadog/core/telemetry/request.rb +13 -1
  91. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
  92. data/lib/datadog/core/utils/time.rb +12 -0
  93. data/lib/datadog/di/code_tracker.rb +168 -0
  94. data/lib/datadog/di/configuration/settings.rb +163 -0
  95. data/lib/datadog/di/configuration.rb +11 -0
  96. data/lib/datadog/di/error.rb +31 -0
  97. data/lib/datadog/di/extensions.rb +16 -0
  98. data/lib/datadog/di/probe.rb +133 -0
  99. data/lib/datadog/di/probe_builder.rb +41 -0
  100. data/lib/datadog/di/redactor.rb +188 -0
  101. data/lib/datadog/di/serializer.rb +193 -0
  102. data/lib/datadog/di.rb +14 -0
  103. data/lib/datadog/kit/appsec/events.rb +2 -4
  104. data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
  105. data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
  106. data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
  107. data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
  108. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +28 -26
  109. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
  110. data/lib/datadog/profiling/collectors/info.rb +15 -6
  111. data/lib/datadog/profiling/collectors/thread_context.rb +30 -2
  112. data/lib/datadog/profiling/component.rb +89 -95
  113. data/lib/datadog/profiling/exporter.rb +3 -3
  114. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
  115. data/lib/datadog/profiling/ext.rb +21 -21
  116. data/lib/datadog/profiling/flush.rb +1 -1
  117. data/lib/datadog/profiling/http_transport.rb +14 -7
  118. data/lib/datadog/profiling/load_native_extension.rb +5 -5
  119. data/lib/datadog/profiling/preload.rb +1 -1
  120. data/lib/datadog/profiling/profiler.rb +5 -8
  121. data/lib/datadog/profiling/scheduler.rb +33 -25
  122. data/lib/datadog/profiling/stack_recorder.rb +3 -0
  123. data/lib/datadog/profiling/tag_builder.rb +2 -2
  124. data/lib/datadog/profiling/tasks/exec.rb +5 -5
  125. data/lib/datadog/profiling/tasks/setup.rb +16 -35
  126. data/lib/datadog/profiling.rb +4 -5
  127. data/lib/datadog/single_step_instrument.rb +12 -0
  128. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
  129. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
  130. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
  131. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
  132. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
  133. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
  134. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
  135. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +4 -1
  136. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
  137. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
  138. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  139. data/lib/datadog/tracing/contrib/ext.rb +14 -0
  140. data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
  141. data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
  142. data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
  143. data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
  144. data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
  145. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +14 -10
  146. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +10 -4
  147. data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
  148. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
  149. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
  150. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
  151. data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
  152. data/lib/datadog/tracing/contrib/lograge/patcher.rb +15 -0
  153. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  154. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  155. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
  156. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
  157. data/lib/datadog/tracing/contrib/patcher.rb +2 -1
  158. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
  159. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
  160. data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
  161. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
  162. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
  163. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
  164. data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
  165. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
  166. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
  167. data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
  168. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
  169. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
  170. data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
  171. data/lib/datadog/tracing/distributed/propagation.rb +7 -0
  172. data/lib/datadog/tracing/metadata/errors.rb +9 -1
  173. data/lib/datadog/tracing/metadata/ext.rb +6 -0
  174. data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
  175. data/lib/datadog/tracing/remote.rb +5 -2
  176. data/lib/datadog/tracing/sampling/matcher.rb +6 -1
  177. data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
  178. data/lib/datadog/tracing/sampling/rule.rb +2 -0
  179. data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
  180. data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
  181. data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
  182. data/lib/datadog/tracing/span.rb +9 -2
  183. data/lib/datadog/tracing/span_event.rb +41 -0
  184. data/lib/datadog/tracing/span_operation.rb +6 -2
  185. data/lib/datadog/tracing/trace_operation.rb +26 -2
  186. data/lib/datadog/tracing/tracer.rb +14 -12
  187. data/lib/datadog/tracing/transport/http/client.rb +1 -0
  188. data/lib/datadog/tracing/transport/io/client.rb +1 -0
  189. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
  190. data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
  191. data/lib/datadog/tracing/workers.rb +1 -1
  192. data/lib/datadog/version.rb +1 -1
  193. metadata +46 -11
  194. data/lib/datadog/profiling/crashtracker.rb +0 -91
  195. data/lib/datadog/profiling/ext/forking.rb +0 -98
  196. data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -166,6 +166,12 @@ struct heap_recorder {
166
166
  size_t objects_frozen;
167
167
  } stats_last_update;
168
168
  };
169
+
170
+ struct end_heap_allocation_args {
171
+ struct heap_recorder *heap_recorder;
172
+ ddog_prof_Slice_Location locations;
173
+ };
174
+
169
175
  static heap_record* get_or_create_heap_record(heap_recorder*, ddog_prof_Slice_Location);
170
176
  static void cleanup_heap_record_if_unused(heap_recorder*, heap_record*);
171
177
  static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record);
@@ -176,6 +182,7 @@ static int st_object_records_iterate(st_data_t, st_data_t, st_data_t);
176
182
  static int st_object_records_debug(st_data_t key, st_data_t value, st_data_t extra);
177
183
  static int update_object_record_entry(st_data_t*, st_data_t*, st_data_t, int);
178
184
  static void commit_recording(heap_recorder*, heap_record*, recording);
185
+ static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args);
179
186
 
180
187
  // ==========================
181
188
  // Heap Recorder External API
@@ -219,7 +226,7 @@ void heap_recorder_free(heap_recorder *heap_recorder) {
219
226
  st_foreach(heap_recorder->heap_records, st_heap_record_entry_free, 0);
220
227
  st_free_table(heap_recorder->heap_records);
221
228
 
222
- if (heap_recorder->active_recording.object_record != NULL) {
229
+ if (heap_recorder->active_recording.object_record != NULL && heap_recorder->active_recording.object_record != &SKIPPED_RECORD) {
223
230
  // If there's a partial object record, clean it up as well
224
231
  object_record_free(heap_recorder->active_recording.object_record);
225
232
  }
@@ -340,9 +347,28 @@ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj
340
347
  };
341
348
  }
342
349
 
343
- void end_heap_allocation_recording(struct heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
350
+ // end_heap_allocation_recording_with_rb_protect gets called while the stack_recorder is holding one of the profile
351
+ // locks. To enable us to correctly unlock the profile on exception, we wrap the call to end_heap_allocation_recording
352
+ // with an rb_protect.
353
+ __attribute__((warn_unused_result))
354
+ int end_heap_allocation_recording_with_rb_protect(struct heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
355
+ int exception_state;
356
+ struct end_heap_allocation_args end_heap_allocation_args = {
357
+ .heap_recorder = heap_recorder,
358
+ .locations = locations,
359
+ };
360
+ rb_protect(end_heap_allocation_recording, (VALUE) &end_heap_allocation_args, &exception_state);
361
+ return exception_state;
362
+ }
363
+
364
+ static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args) {
365
+ struct end_heap_allocation_args *args = (struct end_heap_allocation_args *) end_heap_allocation_args;
366
+
367
+ struct heap_recorder *heap_recorder = args->heap_recorder;
368
+ ddog_prof_Slice_Location locations = args->locations;
369
+
344
370
  if (heap_recorder == NULL) {
345
- return;
371
+ return Qnil;
346
372
  }
347
373
 
348
374
  recording active_recording = heap_recorder->active_recording;
@@ -356,15 +382,16 @@ void end_heap_allocation_recording(struct heap_recorder *heap_recorder, ddog_pro
356
382
  // data required for committing though.
357
383
  heap_recorder->active_recording = (recording) {0};
358
384
 
359
- if (active_recording.object_record == &SKIPPED_RECORD) {
360
- // special marker when we decided to skip due to sampling
361
- return;
385
+ if (active_recording.object_record == &SKIPPED_RECORD) { // special marker when we decided to skip due to sampling
386
+ return Qnil;
362
387
  }
363
388
 
364
389
  heap_record *heap_record = get_or_create_heap_record(heap_recorder, locations);
365
390
 
366
391
  // And then commit the new allocation.
367
392
  commit_recording(heap_recorder, heap_record, active_recording);
393
+
394
+ return Qnil;
368
395
  }
369
396
 
370
397
  void heap_recorder_prepare_iteration(heap_recorder *heap_recorder) {
@@ -605,12 +632,14 @@ static int st_object_records_iterate(DDTRACE_UNUSED st_data_t key, st_data_t val
605
632
  ddog_prof_Location *locations = recorder->reusable_locations;
606
633
  for (uint16_t i = 0; i < stack->frames_len; i++) {
607
634
  const heap_frame *frame = &stack->frames[i];
608
- ddog_prof_Location *location = &locations[i];
609
- location->function.name.ptr = frame->name;
610
- location->function.name.len = strlen(frame->name);
611
- location->function.filename.ptr = frame->filename;
612
- location->function.filename.len = strlen(frame->filename);
613
- location->line = frame->line;
635
+ locations[i] = (ddog_prof_Location) {
636
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
637
+ .function = {
638
+ .name = {.ptr = frame->name, .len = strlen(frame->name)},
639
+ .filename = {.ptr = frame->filename, .len = strlen(frame->filename)},
640
+ },
641
+ .line = frame->line,
642
+ };
614
643
  }
615
644
 
616
645
  heap_recorder_iteration_data iteration_data;
@@ -755,8 +784,20 @@ static void cleanup_heap_record_if_unused(heap_recorder *heap_recorder, heap_rec
755
784
  }
756
785
 
757
786
  static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record) {
787
+ // @ivoanjo: We've seen a segfault crash in the field in this function (October 2024) which we're still trying to investigate.
788
+ // (See PROF-10656 Datadog-internal for details). Just in case, I've sprinkled a bunch of NULL tests in this function for now.
789
+ // Once we figure out the issue we can get rid of them again.
790
+
791
+ if (heap_recorder == NULL) rb_raise(rb_eRuntimeError, "heap_recorder was NULL in on_committed_object_record_cleanup");
792
+ if (heap_recorder->heap_records == NULL) rb_raise(rb_eRuntimeError, "heap_recorder->heap_records was NULL in on_committed_object_record_cleanup");
793
+ if (record == NULL) rb_raise(rb_eRuntimeError, "record was NULL in on_committed_object_record_cleanup");
794
+
758
795
  // Starting with the associated heap record. There will now be one less tracked object pointing to it
759
796
  heap_record *heap_record = record->heap_record;
797
+
798
+ if (heap_record == NULL) rb_raise(rb_eRuntimeError, "heap_record was NULL in on_committed_object_record_cleanup");
799
+ if (heap_record->stack == NULL) rb_raise(rb_eRuntimeError, "heap_record->stack was NULL in on_committed_object_record_cleanup");
800
+
760
801
  heap_record->num_tracked_objects--;
761
802
 
762
803
  // One less object using this heap record, it may have become unused...
@@ -815,6 +856,7 @@ VALUE object_record_inspect(object_record *record) {
815
856
  if (!ruby_ref_from_id(LONG2NUM(record->obj_id), &ref)) {
816
857
  rb_str_catf(inspect, "object=<invalid>");
817
858
  } else {
859
+ rb_str_catf(inspect, "value=%p ", (void *) ref);
818
860
  VALUE ruby_inspect = ruby_safe_inspect(ref);
819
861
  if (ruby_inspect != Qnil) {
820
862
  rb_str_catf(inspect, "object=%"PRIsVALUE, ruby_inspect);
@@ -114,7 +114,9 @@ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj
114
114
  // @param locations The stacktrace representing the location of the allocation.
115
115
  //
116
116
  // WARN: It is illegal to call this without previously having called ::start_heap_allocation_recording.
117
- void end_heap_allocation_recording(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations);
117
+ // WARN: This method rescues exceptions with `rb_protect`, returning the exception state integer for the caller to handle.
118
+ __attribute__((warn_unused_result))
119
+ int end_heap_allocation_recording_with_rb_protect(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations);
118
120
 
119
121
  // Update the heap recorder to reflect the latest state of the VM and prepare internal structures
120
122
  // for efficient iteration.
@@ -2,22 +2,11 @@
2
2
 
3
3
  #include <stdint.h>
4
4
 
5
- // Used to mark symbols to be exported to the outside of the extension.
6
- // Consider very carefully before tagging a function with this.
7
- #define DDTRACE_EXPORT __attribute__ ((visibility ("default")))
8
-
9
- // Used to mark function arguments that are deliberately left unused
10
- #ifdef __GNUC__
11
- #define DDTRACE_UNUSED __attribute__((unused))
12
- #else
13
- #define DDTRACE_UNUSED
14
- #endif
15
-
16
5
  // @ivoanjo: After trying to read through https://stackoverflow.com/questions/3437404/min-and-max-in-c I decided I
17
6
  // don't like C and I just implemented this as a function.
18
- inline static uint64_t uint64_max_of(uint64_t a, uint64_t b) { return a > b ? a : b; }
19
- inline static uint64_t uint64_min_of(uint64_t a, uint64_t b) { return a > b ? b : a; }
20
- inline static long long_max_of(long a, long b) { return a > b ? a : b; }
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; }
7
+ static inline uint64_t uint64_max_of(uint64_t a, uint64_t b) { return a > b ? a : b; }
8
+ static inline uint64_t uint64_min_of(uint64_t a, uint64_t b) { return a > b ? b : a; }
9
+ static inline long long_max_of(long a, long b) { return a > b ? a : b; }
10
+ static inline long long_min_of(long a, long b) { return a > b ? b : a; }
11
+ static inline double double_max_of(double a, double b) { return a > b ? a : b; }
12
+ static inline double double_min_of(double a, double b) { return a > b ? b : a; }
@@ -21,7 +21,7 @@ struct call_exporter_without_gvl_arguments {
21
21
  bool send_ran;
22
22
  };
23
23
 
24
- inline static ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
24
+ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
25
25
  static VALUE _native_validate_exporter(VALUE self, VALUE exporter_configuration);
26
26
  static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration, VALUE tags_as_array);
27
27
  static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_result);
@@ -53,11 +53,11 @@ void http_transport_init(VALUE profiling_module) {
53
53
  ok_symbol = ID2SYM(rb_intern_const("ok"));
54
54
  error_symbol = ID2SYM(rb_intern_const("error"));
55
55
 
56
- library_version_string = ddtrace_version();
56
+ library_version_string = datadog_gem_version();
57
57
  rb_global_variable(&library_version_string);
58
58
  }
59
59
 
60
- inline static ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
60
+ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
61
61
  ENFORCE_TYPE(string, T_STRING);
62
62
  ddog_ByteSlice byte_slice = {.ptr = (uint8_t *) StringValuePtr(string), .len = RSTRING_LEN(string)};
63
63
  return byte_slice;
@@ -77,6 +77,32 @@ static VALUE _native_validate_exporter(DDTRACE_UNUSED VALUE _self, VALUE exporte
77
77
  return rb_ary_new_from_args(2, ok_symbol, Qnil);
78
78
  }
79
79
 
80
+ static ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
81
+ ENFORCE_TYPE(exporter_configuration, T_ARRAY);
82
+
83
+ VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
84
+ ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
85
+ ID working_mode = SYM2ID(exporter_working_mode);
86
+
87
+ ID agentless_id = rb_intern("agentless");
88
+ ID agent_id = rb_intern("agent");
89
+
90
+ if (working_mode != agentless_id && working_mode != agent_id) {
91
+ rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
92
+ }
93
+
94
+ if (working_mode == agentless_id) {
95
+ VALUE site = rb_ary_entry(exporter_configuration, 1);
96
+ VALUE api_key = rb_ary_entry(exporter_configuration, 2);
97
+
98
+ return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
99
+ } else { // agent_id
100
+ VALUE base_url = rb_ary_entry(exporter_configuration, 1);
101
+
102
+ return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
103
+ }
104
+ }
105
+
80
106
  static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration, VALUE tags_as_array) {
81
107
  ENFORCE_TYPE(exporter_configuration, T_ARRAY);
82
108
  ENFORCE_TYPE(tags_as_array, T_ARRAY);
@@ -115,8 +141,7 @@ static VALUE perform_export(
115
141
  ddog_prof_Exporter_Slice_File files_to_export_unmodified,
116
142
  ddog_Vec_Tag *additional_tags,
117
143
  ddog_CharSlice internal_metadata,
118
- ddog_CharSlice info,
119
- uint64_t timeout_milliseconds
144
+ ddog_CharSlice info
120
145
  ) {
121
146
  ddog_prof_ProfiledEndpointsStats *endpoints_stats = NULL; // Not in use yet
122
147
  ddog_prof_Exporter_Request_BuildResult build_result = ddog_prof_Exporter_Request_build(
@@ -128,8 +153,7 @@ static VALUE perform_export(
128
153
  additional_tags,
129
154
  endpoints_stats,
130
155
  &internal_metadata,
131
- &info,
132
- timeout_milliseconds
156
+ &info
133
157
  );
134
158
 
135
159
  if (build_result.tag == DDOG_PROF_EXPORTER_REQUEST_BUILD_RESULT_ERR) {
@@ -254,6 +278,15 @@ static VALUE _native_do_export(
254
278
  VALUE failure_tuple = handle_exporter_failure(exporter_result);
255
279
  if (!NIL_P(failure_tuple)) return failure_tuple;
256
280
 
281
+ ddog_prof_MaybeError timeout_result = ddog_prof_Exporter_set_timeout(exporter_result.ok, timeout_milliseconds);
282
+ if (timeout_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
283
+ // NOTE: Seems a bit harsh to fail the upload if we can't set a timeout. OTOH, this is only expected to fail
284
+ // if the exporter is not well built. Because such a situation should already be caught above I think it's
285
+ // preferable to leave this here as a virtually unreachable exception rather than ignoring it.
286
+ ddog_prof_Exporter_drop(exporter_result.ok);
287
+ return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.some));
288
+ }
289
+
257
290
  return perform_export(
258
291
  exporter_result.ok,
259
292
  start,
@@ -262,8 +295,7 @@ static VALUE _native_do_export(
262
295
  files_to_export_unmodified,
263
296
  null_additional_tags,
264
297
  internal_metadata,
265
- info,
266
- timeout_milliseconds
298
+ info
267
299
  );
268
300
  }
269
301
 
@@ -2,8 +2,6 @@
2
2
 
3
3
  #include <ruby.h>
4
4
 
5
- static VALUE log_failure_to_process_tag(VALUE err_details);
6
-
7
5
  const char *ruby_value_type_to_string(enum ruby_value_type type) {
8
6
  return ruby_value_type_to_char_slice(type).ptr;
9
7
  }
@@ -62,87 +60,3 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
62
60
  ddog_Error_drop(error);
63
61
  return error_msg_size;
64
62
  }
65
-
66
- __attribute__((warn_unused_result))
67
- ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
68
- ENFORCE_TYPE(exporter_configuration, T_ARRAY);
69
-
70
- VALUE exporter_working_mode = rb_ary_entry(exporter_configuration, 0);
71
- ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
72
- ID working_mode = SYM2ID(exporter_working_mode);
73
-
74
- ID agentless_id = rb_intern("agentless");
75
- ID agent_id = rb_intern("agent");
76
-
77
- if (working_mode != agentless_id && working_mode != agent_id) {
78
- rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
79
- }
80
-
81
- if (working_mode == agentless_id) {
82
- VALUE site = rb_ary_entry(exporter_configuration, 1);
83
- VALUE api_key = rb_ary_entry(exporter_configuration, 2);
84
- ENFORCE_TYPE(site, T_STRING);
85
- ENFORCE_TYPE(api_key, T_STRING);
86
-
87
- return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
88
- } else { // agent_id
89
- VALUE base_url = rb_ary_entry(exporter_configuration, 1);
90
- ENFORCE_TYPE(base_url, T_STRING);
91
-
92
- return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
93
- }
94
- }
95
-
96
- __attribute__((warn_unused_result))
97
- ddog_Vec_Tag convert_tags(VALUE tags_as_array) {
98
- ENFORCE_TYPE(tags_as_array, T_ARRAY);
99
-
100
- long tags_count = RARRAY_LEN(tags_as_array);
101
- ddog_Vec_Tag tags = ddog_Vec_Tag_new();
102
-
103
- for (long i = 0; i < tags_count; i++) {
104
- VALUE name_value_pair = rb_ary_entry(tags_as_array, i);
105
-
106
- if (!RB_TYPE_P(name_value_pair, T_ARRAY)) {
107
- ddog_Vec_Tag_drop(tags);
108
- ENFORCE_TYPE(name_value_pair, T_ARRAY);
109
- }
110
-
111
- // Note: We can index the array without checking its size first because rb_ary_entry returns Qnil if out of bounds
112
- VALUE tag_name = rb_ary_entry(name_value_pair, 0);
113
- VALUE tag_value = rb_ary_entry(name_value_pair, 1);
114
-
115
- if (!(RB_TYPE_P(tag_name, T_STRING) && RB_TYPE_P(tag_value, T_STRING))) {
116
- ddog_Vec_Tag_drop(tags);
117
- ENFORCE_TYPE(tag_name, T_STRING);
118
- ENFORCE_TYPE(tag_value, T_STRING);
119
- }
120
-
121
- ddog_Vec_Tag_PushResult push_result =
122
- ddog_Vec_Tag_push(&tags, char_slice_from_ruby_string(tag_name), char_slice_from_ruby_string(tag_value));
123
-
124
- if (push_result.tag == DDOG_VEC_TAG_PUSH_RESULT_ERR) {
125
- // libdatadog validates tags and may catch invalid tags that ddtrace didn't actually catch.
126
- // We warn users about such tags, and then just ignore them.
127
-
128
- int exception_state;
129
- rb_protect(log_failure_to_process_tag, get_error_details_and_drop(&push_result.err), &exception_state);
130
-
131
- // Since we are calling into Ruby code, it may raise an exception. Ensure that dynamically-allocated tags
132
- // get cleaned before propagating the exception.
133
- if (exception_state) {
134
- ddog_Vec_Tag_drop(tags);
135
- rb_jump_tag(exception_state); // "Re-raise" exception
136
- }
137
- }
138
- }
139
-
140
- return tags;
141
- }
142
-
143
- static VALUE log_failure_to_process_tag(VALUE err_details) {
144
- VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
145
- VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
146
-
147
- return rb_funcall(logger, rb_intern("warn"), 1, rb_sprintf("Failed to add tag to profiling request: %"PRIsVALUE, err_details));
148
- }
@@ -3,27 +3,10 @@
3
3
  #include <datadog/profiling.h>
4
4
  #include "ruby_helpers.h"
5
5
 
6
- inline static ddog_CharSlice char_slice_from_ruby_string(VALUE string) {
7
- ENFORCE_TYPE(string, T_STRING);
8
- ddog_CharSlice char_slice = {.ptr = StringValuePtr(string), .len = RSTRING_LEN(string)};
9
- return char_slice;
10
- }
11
-
12
- inline static VALUE ruby_string_from_vec_u8(ddog_Vec_U8 string) {
6
+ static inline VALUE ruby_string_from_vec_u8(ddog_Vec_U8 string) {
13
7
  return rb_str_new((char *) string.ptr, string.len);
14
8
  }
15
9
 
16
- inline static VALUE ruby_string_from_error(const ddog_Error *error) {
17
- ddog_CharSlice char_slice = ddog_Error_message(error);
18
- return rb_str_new(char_slice.ptr, char_slice.len);
19
- }
20
-
21
- inline static VALUE get_error_details_and_drop(ddog_Error *error) {
22
- VALUE result = ruby_string_from_error(error);
23
- ddog_Error_drop(error);
24
- return result;
25
- }
26
-
27
10
  // Utility function to be able to extract an error cstring from a ddog_Error.
28
11
  // Returns the amount of characters written to string (which are necessarily
29
12
  // bounded by capacity - 1 since the string will be null-terminated).
@@ -37,10 +20,6 @@ ddog_CharSlice ruby_value_type_to_char_slice(enum ruby_value_type type);
37
20
 
38
21
  // Returns a dynamically allocated string from the provided char slice.
39
22
  // WARN: The returned string must be explicitly freed with ruby_xfree.
40
- inline static char* string_from_char_slice(ddog_CharSlice slice) {
23
+ static inline char* string_from_char_slice(ddog_CharSlice slice) {
41
24
  return ruby_strndup(slice.ptr, slice.len);
42
25
  }
43
-
44
- ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration);
45
-
46
- ddog_Vec_Tag convert_tags(VALUE tags_as_array);