datadog 2.12.2 → 2.15.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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -2
  3. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -14
  4. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +3 -0
  5. data/ext/datadog_profiling_native_extension/encoded_profile.c +69 -0
  6. data/ext/datadog_profiling_native_extension/encoded_profile.h +7 -0
  7. data/ext/datadog_profiling_native_extension/http_transport.c +25 -32
  8. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  9. data/ext/datadog_profiling_native_extension/stack_recorder.c +22 -21
  10. data/ext/libdatadog_api/datadog_ruby_common.h +3 -0
  11. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  12. data/lib/datadog/appsec/actions_handler.rb +22 -1
  13. data/lib/datadog/appsec/anonymizer.rb +16 -0
  14. data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
  15. data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
  16. data/lib/datadog/appsec/assets/waf_rules/recommended.json +0 -1344
  17. data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
  18. data/lib/datadog/appsec/assets/waf_rules/strict.json +0 -1344
  19. data/lib/datadog/appsec/component.rb +19 -17
  20. data/lib/datadog/appsec/compressed_json.rb +40 -0
  21. data/lib/datadog/appsec/configuration/settings.rb +62 -10
  22. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  23. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  24. data/lib/datadog/appsec/contrib/devise/configuration.rb +7 -31
  25. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +79 -0
  26. data/lib/datadog/appsec/contrib/devise/ext.rb +21 -0
  27. data/lib/datadog/appsec/contrib/devise/integration.rb +0 -1
  28. data/lib/datadog/appsec/contrib/devise/patcher.rb +36 -23
  29. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  30. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  31. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +2 -2
  32. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +93 -0
  33. data/lib/datadog/appsec/contrib/rack/ext.rb +14 -0
  34. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +10 -3
  35. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +0 -2
  36. data/lib/datadog/appsec/event.rb +22 -51
  37. data/lib/datadog/appsec/ext.rb +4 -2
  38. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +4 -2
  39. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -3
  40. data/lib/datadog/appsec/remote.rb +4 -0
  41. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  42. data/lib/datadog/appsec/utils.rb +0 -2
  43. data/lib/datadog/core/configuration/components.rb +2 -1
  44. data/lib/datadog/core/configuration/ext.rb +4 -0
  45. data/lib/datadog/core/configuration/options.rb +2 -2
  46. data/lib/datadog/core/configuration/settings.rb +53 -30
  47. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  48. data/lib/datadog/core/environment/agent_info.rb +4 -3
  49. data/lib/datadog/core/metrics/client.rb +1 -1
  50. data/lib/datadog/core/remote/client.rb +1 -1
  51. data/lib/datadog/core/remote/component.rb +3 -6
  52. data/lib/datadog/core/remote/configuration/repository.rb +2 -1
  53. data/lib/datadog/core/remote/negotiation.rb +9 -9
  54. data/lib/datadog/core/remote/transport/config.rb +4 -3
  55. data/lib/datadog/core/remote/transport/http/client.rb +4 -3
  56. data/lib/datadog/core/remote/transport/http/config.rb +6 -32
  57. data/lib/datadog/core/remote/transport/http/negotiation.rb +6 -32
  58. data/lib/datadog/core/remote/transport/http.rb +22 -57
  59. data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
  60. data/lib/datadog/core/runtime/metrics.rb +8 -1
  61. data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
  62. data/lib/datadog/core/telemetry/metric.rb +5 -5
  63. data/lib/datadog/core/telemetry/request.rb +1 -1
  64. data/lib/datadog/core/transport/http/api/instance.rb +17 -0
  65. data/lib/datadog/core/transport/http/api/spec.rb +17 -0
  66. data/lib/datadog/core/transport/http/builder.rb +5 -3
  67. data/lib/datadog/core/transport/http.rb +39 -2
  68. data/lib/datadog/di/component.rb +0 -2
  69. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  70. data/lib/datadog/di/probe_notifier_worker.rb +16 -16
  71. data/lib/datadog/di/transport/diagnostics.rb +4 -3
  72. data/lib/datadog/di/transport/http/api.rb +2 -12
  73. data/lib/datadog/di/transport/http/client.rb +4 -3
  74. data/lib/datadog/di/transport/http/diagnostics.rb +7 -34
  75. data/lib/datadog/di/transport/http/input.rb +7 -34
  76. data/lib/datadog/di/transport/http.rb +14 -62
  77. data/lib/datadog/di/transport/input.rb +4 -3
  78. data/lib/datadog/di/utils.rb +5 -0
  79. data/lib/datadog/kit/appsec/events.rb +12 -0
  80. data/lib/datadog/kit/identity.rb +5 -1
  81. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  82. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  83. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  84. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  85. data/lib/datadog/opentelemetry.rb +2 -1
  86. data/lib/datadog/profiling/collectors/info.rb +3 -0
  87. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  88. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  89. data/lib/datadog/profiling/exporter.rb +2 -3
  90. data/lib/datadog/profiling/ext.rb +0 -1
  91. data/lib/datadog/profiling/flush.rb +4 -7
  92. data/lib/datadog/profiling/http_transport.rb +10 -59
  93. data/lib/datadog/profiling/stack_recorder.rb +4 -4
  94. data/lib/datadog/profiling.rb +6 -2
  95. data/lib/datadog/tracing/component.rb +15 -12
  96. data/lib/datadog/tracing/configuration/ext.rb +7 -1
  97. data/lib/datadog/tracing/configuration/settings.rb +18 -2
  98. data/lib/datadog/tracing/context_provider.rb +1 -1
  99. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  100. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  101. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  102. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  103. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  104. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  105. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  106. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  107. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  108. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  109. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -5
  110. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -11
  111. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +6 -10
  112. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  113. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +46 -0
  114. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  115. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  116. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  117. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  118. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  119. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  120. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  121. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  122. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  123. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  124. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  125. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  126. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
  127. data/lib/datadog/tracing/contrib.rb +1 -0
  128. data/lib/datadog/tracing/correlation.rb +9 -2
  129. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  130. data/lib/datadog/tracing/distributed/datadog.rb +2 -0
  131. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  132. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  133. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  134. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  135. data/lib/datadog/tracing/span_event.rb +1 -1
  136. data/lib/datadog/tracing/span_operation.rb +2 -1
  137. data/lib/datadog/tracing/sync_writer.rb +1 -2
  138. data/lib/datadog/tracing/trace_digest.rb +9 -2
  139. data/lib/datadog/tracing/trace_operation.rb +29 -17
  140. data/lib/datadog/tracing/trace_segment.rb +6 -4
  141. data/lib/datadog/tracing/tracer.rb +38 -2
  142. data/lib/datadog/tracing/transport/http/api.rb +2 -10
  143. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  144. data/lib/datadog/tracing/transport/http/traces.rb +13 -41
  145. data/lib/datadog/tracing/transport/http.rb +11 -44
  146. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  147. data/lib/datadog/tracing/transport/traces.rb +26 -9
  148. data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
  149. data/lib/datadog/tracing/writer.rb +2 -6
  150. data/lib/datadog/tracing.rb +16 -3
  151. data/lib/datadog/version.rb +2 -2
  152. data/lib/datadog.rb +1 -1
  153. metadata +28 -13
  154. data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
  155. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
  156. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
  157. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  158. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  159. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a27bb8e1291ee014e342297fc3d53aca8a895017281201b1b0a29cd376ba905
4
- data.tar.gz: e26c326437e4edcbdfac0ad604514a48c23c31500a68dcc4affb53251aed5f8f
3
+ metadata.gz: 7d17c177691be6204c922253f717344b69cbf2ccf0e6cc51b5d2063e484ffcf9
4
+ data.tar.gz: fb55233c5db1aa2d80562d7d2a0f7297f4d13b0b1f1c8a3f3a6feec8f15bb947
5
5
  SHA512:
6
- metadata.gz: e8dab2f6ed8bc48fb95a4c9c3c28fce16b8eaaceb70179ee12b9a009498dabe498d73b08a25180fdb53642fc78da4388b2c80bbf76a61afd25af53449f2e9375
7
- data.tar.gz: 4489a8e084f7873e59b4d2a13d27b9a75f2b95ae0c9b5129edfdb02a58c736890bd5226df765de216010512b9fd0ffad6f82cc373ea8ee995340ef838c721d65
6
+ metadata.gz: ef69c8e13819833ce2b1a0987ec66a674a15ca029bd4ad0a29703a613c7dd263015ca0018433ac366f69e655fa264a74aa949a1d6b12e30753b249fa8b7d62c2
7
+ data.tar.gz: 1d44dca02ab71b49b87e371825bbdda696fbd686bc9d24662d5d90c5091c4ddf82226abda23c56da9da8e8274ab06759a90b73fd3eb44cecc081598fd8cc188a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,55 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.15.0] - 2025-04-17
6
+
7
+ ### Added
8
+
9
+ * AppSec: Add auto-patching for `activerecord` with sql injection detection ([#4581][])
10
+ * Tracing: Add option for `opensearch` to set resource with relative path ([#4509][])
11
+
12
+ ### Changed
13
+
14
+ * AppSec: Update In-App WAF rules, processors, and scanners ([#4568][])
15
+
16
+ ### Fixed
17
+
18
+ * AppSec: Fix blocked requests not marked correctly when using custom redirect blocking action ([#4580][])
19
+ * AppSec: Fix UTF-8 unsafe payloads in InApp-WAF causing runtime exceptions ([#4573][])
20
+
21
+ ## [2.14.0] - 2025-04-04
22
+
23
+ ### Added
24
+
25
+ * Tracing: Add `karafka` instrumentation with 2.3.0 as the minimum supported version. ([#4147][])
26
+
27
+ ### Fixed
28
+
29
+ * Core: Tracing: default logger arguments for compatibility with previous dd-trace-rb versions ([#4558][])
30
+ * AppSec: Fix `Datadog::Kit::AppSec::Events` SDK methods to correctly handle given string key `usr.login`. ([#4552][])
31
+
32
+ ## [2.13.0] - 2025-04-02
33
+
34
+ ### Added
35
+
36
+ * Core: Add `DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED` experimental option to enable runtime ID collection for runtime metrics. ([#4473][])
37
+ * Tracing: Add support for W3C Baggage API along with automatic extraction and injection, and OpenTelemetry support. ([#4493][], [#4505][])
38
+ * Tracing: Add `DD_APM_TRACING_ENABLED` option to disable APM tracing while keeping other products traces. ([#4498][])
39
+ * Tracing: Add `DD_TRACE_NATIVE_SPAN_EVENTS` option to override span events serialization for agent-less environments. ([#4507][])
40
+ * AppSec: Add stack trace reporting for security events. ([#4526][])
41
+ * AppSec: Improve `devise` instrumentation to support latest Account Takeover (ATO) detection. ([#4433][])
42
+
43
+ ### Changed
44
+
45
+ * Core: Improve `DD_TAGS` configuration handling to be more consistent across Datadog libraries and Agent. ([#4530][])
46
+ * Tracing: Enable by default 128-bit trace ID logging so that trace IDs are consistent across logs and the Datadog UI. ([#4528][])
47
+
48
+ ### Fixed
49
+
50
+ * Core: Fix initialization when the library is partially loaded. ([#4498][])
51
+ * Tracing: Fix trace ID propagation by ensuring extraction of 16-character hex values from the `_dd.p.tid` tag in `x-datadog-tags` header. ([#4534][])
52
+ * Tracing: Profiling: Fix warnings printed by `ruby -w`. ([#4547][], [#4549][])
53
+
5
54
  ## [2.12.2] - 2025-03-17
6
55
 
7
56
  ### Fixed
@@ -3145,7 +3194,10 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3145
3194
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3146
3195
 
3147
3196
 
3148
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.2...master
3197
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.15.0...master
3198
+ [2.15.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.14.0...v2.15.0
3199
+ [2.14.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.13.0...v2.14.0
3200
+ [2.13.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.2...v2.13.0
3149
3201
  [2.12.2]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.1...v2.12.2
3150
3202
  [2.12.1]: https://github.com/DataDog/dd-trace-rb/compare/v2.12.0...v2.12.1
3151
3203
  [2.12.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.11.0...v2.12.0
@@ -4607,6 +4659,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4607
4659
  [#4085]: https://github.com/DataDog/dd-trace-rb/issues/4085
4608
4660
  [#4137]: https://github.com/DataDog/dd-trace-rb/issues/4137
4609
4661
  [#4140]: https://github.com/DataDog/dd-trace-rb/issues/4140
4662
+ [#4147]: https://github.com/DataDog/dd-trace-rb/issues/4147
4610
4663
  [#4153]: https://github.com/DataDog/dd-trace-rb/issues/4153
4611
4664
  [#4161]: https://github.com/DataDog/dd-trace-rb/issues/4161
4612
4665
  [#4164]: https://github.com/DataDog/dd-trace-rb/issues/4164
@@ -4649,8 +4702,27 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4649
4702
  [#4424]: https://github.com/DataDog/dd-trace-rb/issues/4424
4650
4703
  [#4425]: https://github.com/DataDog/dd-trace-rb/issues/4425
4651
4704
  [#4426]: https://github.com/DataDog/dd-trace-rb/issues/4426
4705
+ [#4433]: https://github.com/DataDog/dd-trace-rb/issues/4433
4652
4706
  [#4437]: https://github.com/DataDog/dd-trace-rb/issues/4437
4707
+ [#4473]: https://github.com/DataDog/dd-trace-rb/issues/4473
4708
+ [#4493]: https://github.com/DataDog/dd-trace-rb/issues/4493
4653
4709
  [#4497]: https://github.com/DataDog/dd-trace-rb/issues/4497
4710
+ [#4498]: https://github.com/DataDog/dd-trace-rb/issues/4498
4711
+ [#4505]: https://github.com/DataDog/dd-trace-rb/issues/4505
4712
+ [#4507]: https://github.com/DataDog/dd-trace-rb/issues/4507
4713
+ [#4509]: https://github.com/DataDog/dd-trace-rb/issues/4509
4714
+ [#4526]: https://github.com/DataDog/dd-trace-rb/issues/4526
4715
+ [#4528]: https://github.com/DataDog/dd-trace-rb/issues/4528
4716
+ [#4530]: https://github.com/DataDog/dd-trace-rb/issues/4530
4717
+ [#4534]: https://github.com/DataDog/dd-trace-rb/issues/4534
4718
+ [#4547]: https://github.com/DataDog/dd-trace-rb/issues/4547
4719
+ [#4549]: https://github.com/DataDog/dd-trace-rb/issues/4549
4720
+ [#4552]: https://github.com/DataDog/dd-trace-rb/issues/4552
4721
+ [#4558]: https://github.com/DataDog/dd-trace-rb/issues/4558
4722
+ [#4568]: https://github.com/DataDog/dd-trace-rb/issues/4568
4723
+ [#4573]: https://github.com/DataDog/dd-trace-rb/issues/4573
4724
+ [#4580]: https://github.com/DataDog/dd-trace-rb/issues/4580
4725
+ [#4581]: https://github.com/DataDog/dd-trace-rb/issues/4581
4654
4726
  [@AdrianLC]: https://github.com/AdrianLC
4655
4727
  [@Azure7111]: https://github.com/Azure7111
4656
4728
  [@BabyGroot]: https://github.com/BabyGroot
@@ -4802,4 +4874,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4802
4874
  [@y-yagi]: https://github.com/y-yagi
4803
4875
  [@yujideveloper]: https://github.com/yujideveloper
4804
4876
  [@yukimurasawa]: https://github.com/yukimurasawa
4805
- [@zachmccormick]: https://github.com/zachmccormick
4877
+ [@zachmccormick]: https://github.com/zachmccormick
@@ -212,7 +212,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
212
212
  static VALUE _native_sample(VALUE self, VALUE collector_instance, VALUE profiler_overhead_stack_thread, VALUE allow_exception);
213
213
  static VALUE _native_on_gc_start(VALUE self, VALUE collector_instance);
214
214
  static VALUE _native_on_gc_finish(VALUE self, VALUE collector_instance);
215
- static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE reset_monotonic_to_system_state, VALUE allow_exception);
215
+ static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE allow_exception);
216
216
  static void update_metrics_and_sample(
217
217
  thread_context_collector_state *state,
218
218
  VALUE thread_being_sampled,
@@ -297,6 +297,7 @@ static void otel_without_ddtrace_trace_identifiers_for(
297
297
  static otel_span otel_span_from(VALUE otel_context, VALUE otel_current_span_key);
298
298
  static uint64_t otel_span_id_to_uint(VALUE otel_span_id);
299
299
  static VALUE safely_lookup_hash_without_going_into_ruby_code(VALUE hash, VALUE key);
300
+ static VALUE _native_system_epoch_time_now_ns(DDTRACE_UNUSED VALUE self, VALUE collector_instance);
300
301
 
301
302
  void collectors_thread_context_init(VALUE profiling_module) {
302
303
  VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
@@ -321,13 +322,14 @@ void collectors_thread_context_init(VALUE profiling_module) {
321
322
  rb_define_singleton_method(testing_module, "_native_sample_allocation", _native_sample_allocation, 3);
322
323
  rb_define_singleton_method(testing_module, "_native_on_gc_start", _native_on_gc_start, 1);
323
324
  rb_define_singleton_method(testing_module, "_native_on_gc_finish", _native_on_gc_finish, 1);
324
- rb_define_singleton_method(testing_module, "_native_sample_after_gc", _native_sample_after_gc, 3);
325
+ rb_define_singleton_method(testing_module, "_native_sample_after_gc", _native_sample_after_gc, 2);
325
326
  rb_define_singleton_method(testing_module, "_native_thread_list", _native_thread_list, 0);
326
327
  rb_define_singleton_method(testing_module, "_native_per_thread_context", _native_per_thread_context, 1);
327
328
  rb_define_singleton_method(testing_module, "_native_stats", _native_stats, 1);
328
329
  rb_define_singleton_method(testing_module, "_native_gc_tracking", _native_gc_tracking, 1);
329
330
  rb_define_singleton_method(testing_module, "_native_new_empty_thread", _native_new_empty_thread, 0);
330
331
  rb_define_singleton_method(testing_module, "_native_sample_skipped_allocation_samples", _native_sample_skipped_allocation_samples, 2);
332
+ rb_define_singleton_method(testing_module, "_native_system_epoch_time_now_ns", _native_system_epoch_time_now_ns, 1);
331
333
  #ifndef NO_GVL_INSTRUMENTATION
332
334
  rb_define_singleton_method(testing_module, "_native_on_gvl_waiting", _native_on_gvl_waiting, 1);
333
335
  rb_define_singleton_method(testing_module, "_native_gvl_waiting_at_for", _native_gvl_waiting_at_for, 1);
@@ -551,19 +553,9 @@ static VALUE _native_on_gc_finish(DDTRACE_UNUSED VALUE self, VALUE collector_ins
551
553
  return Qtrue;
552
554
  }
553
555
 
554
- // This method exists only to enable testing Datadog::Profiling::Collectors::ThreadContext behavior using RSpec.
555
- // It SHOULD NOT be used for other purposes.
556
- static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE reset_monotonic_to_system_state, VALUE allow_exception) {
557
- ENFORCE_BOOLEAN(reset_monotonic_to_system_state);
556
+ static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE allow_exception) {
558
557
  ENFORCE_BOOLEAN(allow_exception);
559
558
 
560
- thread_context_collector_state *state;
561
- TypedData_Get_Struct(collector_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
562
-
563
- if (reset_monotonic_to_system_state == Qtrue) {
564
- state->time_converter_state = (monotonic_to_system_epoch_state) MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER;
565
- }
566
-
567
559
  if (allow_exception == Qfalse) debug_enter_unsafe_context();
568
560
 
569
561
  thread_context_collector_sample_after_gc(collector_instance);
@@ -1316,7 +1308,7 @@ static long thread_id_for(VALUE thread) {
1316
1308
  }
1317
1309
 
1318
1310
  VALUE enforce_thread_context_collector_instance(VALUE object) {
1319
- Check_TypedStruct(object, &thread_context_collector_typed_data);
1311
+ ENFORCE_TYPED_DATA(object, &thread_context_collector_typed_data);
1320
1312
  return object;
1321
1313
  }
1322
1314
 
@@ -2167,3 +2159,13 @@ static VALUE safely_lookup_hash_without_going_into_ruby_code(VALUE hash, VALUE k
2167
2159
 
2168
2160
  return state.result;
2169
2161
  }
2162
+
2163
+ static VALUE _native_system_epoch_time_now_ns(DDTRACE_UNUSED VALUE self, VALUE collector_instance) {
2164
+ thread_context_collector_state *state;
2165
+ TypedData_Get_Struct(collector_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
2166
+
2167
+ long current_monotonic_wall_time_ns = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
2168
+ long system_epoch_time_ns = monotonic_to_system_epoch_ns(&state->time_converter_state, current_monotonic_wall_time_ns);
2169
+
2170
+ return LONG2NUM(system_epoch_time_ns);
2171
+ }
@@ -27,6 +27,9 @@
27
27
  #define ENFORCE_BOOLEAN(value) \
28
28
  { if (RB_UNLIKELY(value != Qtrue && value != Qfalse)) raise_unexpected_type(value, ADD_QUOTES(value), "true or false", __FILE__, __LINE__, __func__); }
29
29
 
30
+ #define ENFORCE_TYPED_DATA(value, type) \
31
+ { if (RB_UNLIKELY(!rb_typeddata_is_kind_of(value, type))) raise_unexpected_type(value, ADD_QUOTES(value), "TypedData of type " ADD_QUOTES(type), __FILE__, __LINE__, __func__); }
32
+
30
33
  NORETURN(void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name));
31
34
 
32
35
  // Helper to retrieve Datadog::VERSION::STRING
@@ -0,0 +1,69 @@
1
+ #include "encoded_profile.h"
2
+ #include "datadog_ruby_common.h"
3
+ #include "libdatadog_helpers.h"
4
+
5
+ // This class exists to wrap a ddog_prof_EncodedProfile into a Ruby object
6
+ // This file implements the native bits of the Datadog::Profiling::EncodedProfile class
7
+
8
+ static void encoded_profile_typed_data_free(void *state_ptr);
9
+ static VALUE _native_bytes(VALUE self);
10
+
11
+ static VALUE encoded_profile_class = Qnil;
12
+
13
+ void encoded_profile_init(VALUE profiling_module) {
14
+ encoded_profile_class = rb_define_class_under(profiling_module, "EncodedProfile", rb_cObject);
15
+
16
+ rb_undef_alloc_func(encoded_profile_class); // Class cannot be created from Ruby code
17
+ rb_global_variable(&encoded_profile_class);
18
+
19
+ rb_define_method(encoded_profile_class, "_native_bytes", _native_bytes, 0);
20
+ }
21
+
22
+ // This structure is used to define a Ruby object that stores a `ddog_prof_EncodedProfile`
23
+ // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
24
+ static const rb_data_type_t encoded_profile_typed_data = {
25
+ .wrap_struct_name = "Datadog::Profiling::EncodedProfile",
26
+ .function = {
27
+ .dmark = NULL, // We don't store references to Ruby objects so we don't need to mark any of them
28
+ .dfree = encoded_profile_typed_data_free,
29
+ .dsize = NULL, // We don't track memory usage (although it'd be cool if we did!)
30
+ //.dcompact = NULL, // Not needed -- we don't store references to Ruby objects
31
+ },
32
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
33
+ };
34
+
35
+ VALUE from_ddog_prof_EncodedProfile(ddog_prof_EncodedProfile profile) {
36
+ ddog_prof_EncodedProfile *state = ruby_xcalloc(1, sizeof(ddog_prof_EncodedProfile));
37
+ *state = profile;
38
+ return TypedData_Wrap_Struct(encoded_profile_class, &encoded_profile_typed_data, state);
39
+ }
40
+
41
+ static void encoded_profile_typed_data_free(void *state_ptr) {
42
+ ddog_prof_EncodedProfile *state = (ddog_prof_EncodedProfile *) state_ptr;
43
+
44
+ // This drops the profile itself
45
+ ddog_prof_EncodedProfile_drop(state);
46
+
47
+ // This drops the tiny bit of memory we allocated to contain the ` ddog_prof_EncodedProfile` struct
48
+ ruby_xfree(state);
49
+ }
50
+
51
+ static VALUE _native_bytes(VALUE self) {
52
+ ddog_prof_EncodedProfile *state;
53
+ TypedData_Get_Struct(self, ddog_prof_EncodedProfile, &encoded_profile_typed_data, state);
54
+
55
+ return ruby_string_from_vec_u8(state->buffer);
56
+
57
+ // TODO: This will be used for libdatadog 17
58
+ /*ddog_prof_Result_ByteSlice raw_bytes = ddog_prof_EncodedProfile_bytes(state);
59
+ if (raw_bytes.tag == DDOG_PROF_RESULT_BYTE_SLICE_ERR_BYTE_SLICE) {
60
+ rb_raise(rb_eRuntimeError, "Failed to get bytes from profile: %"PRIsVALUE, get_error_details_and_drop(&raw_bytes.err));
61
+ }
62
+
63
+ return rb_str_new((const char *) raw_bytes.ok.ptr, raw_bytes.ok.len);*/
64
+ }
65
+
66
+ VALUE enforce_encoded_profile_instance(VALUE object) {
67
+ ENFORCE_TYPED_DATA(object, &encoded_profile_typed_data);
68
+ return object;
69
+ }
@@ -0,0 +1,7 @@
1
+ #pragma once
2
+
3
+ #include <ruby.h>
4
+ #include <datadog/profiling.h>
5
+
6
+ VALUE from_ddog_prof_EncodedProfile(ddog_prof_EncodedProfile profile);
7
+ VALUE enforce_encoded_profile_instance(VALUE object);
@@ -4,6 +4,7 @@
4
4
  #include "helpers.h"
5
5
  #include "libdatadog_helpers.h"
6
6
  #include "ruby_helpers.h"
7
+ #include "encoded_profile.h"
7
8
 
8
9
  // Used to report profiling data to Datadog.
9
10
  // This file implements the native bits of the Datadog::Profiling::HttpTransport class
@@ -29,17 +30,11 @@ static VALUE _native_do_export(
29
30
  VALUE self,
30
31
  VALUE exporter_configuration,
31
32
  VALUE upload_timeout_milliseconds,
33
+ VALUE flush,
32
34
  VALUE start_timespec_seconds,
33
35
  VALUE start_timespec_nanoseconds,
34
36
  VALUE finish_timespec_seconds,
35
- VALUE finish_timespec_nanoseconds,
36
- VALUE pprof_file_name,
37
- VALUE pprof_data,
38
- VALUE code_provenance_file_name,
39
- VALUE code_provenance_data,
40
- VALUE tags_as_array,
41
- VALUE internal_metadata_json,
42
- VALUE info_json
37
+ VALUE finish_timespec_nanoseconds
43
38
  );
44
39
  static void *call_exporter_without_gvl(void *call_args);
45
40
  static void interrupt_exporter_call(void *cancel_token);
@@ -48,7 +43,7 @@ void http_transport_init(VALUE profiling_module) {
48
43
  VALUE http_transport_class = rb_define_class_under(profiling_module, "HttpTransport", rb_cObject);
49
44
 
50
45
  rb_define_singleton_method(http_transport_class, "_native_validate_exporter", _native_validate_exporter, 1);
51
- rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 13);
46
+ rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 7);
52
47
 
53
48
  ok_symbol = ID2SYM(rb_intern_const("ok"));
54
49
  error_symbol = ID2SYM(rb_intern_const("error"));
@@ -84,22 +79,17 @@ static ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
84
79
  ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
85
80
  ID working_mode = SYM2ID(exporter_working_mode);
86
81
 
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) {
82
+ if (working_mode == rb_intern("agentless")) {
95
83
  VALUE site = rb_ary_entry(exporter_configuration, 1);
96
84
  VALUE api_key = rb_ary_entry(exporter_configuration, 2);
97
85
 
98
86
  return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
99
- } else { // agent_id
87
+ } else if (working_mode == rb_intern("agent")) {
100
88
  VALUE base_url = rb_ary_entry(exporter_configuration, 1);
101
89
 
102
90
  return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
91
+ } else {
92
+ rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
103
93
  }
104
94
  }
105
95
 
@@ -139,7 +129,6 @@ static VALUE perform_export(
139
129
  ddog_Timespec finish,
140
130
  ddog_prof_Exporter_Slice_File files_to_compress_and_export,
141
131
  ddog_prof_Exporter_Slice_File files_to_export_unmodified,
142
- ddog_Vec_Tag *additional_tags,
143
132
  ddog_CharSlice internal_metadata,
144
133
  ddog_CharSlice info
145
134
  ) {
@@ -150,7 +139,7 @@ static VALUE perform_export(
150
139
  finish,
151
140
  files_to_compress_and_export,
152
141
  files_to_export_unmodified,
153
- additional_tags,
142
+ /* optional_additional_tags: */ NULL,
154
143
  endpoints_stats,
155
144
  &internal_metadata,
156
145
  &info
@@ -214,26 +203,27 @@ static VALUE _native_do_export(
214
203
  DDTRACE_UNUSED VALUE _self,
215
204
  VALUE exporter_configuration,
216
205
  VALUE upload_timeout_milliseconds,
206
+ VALUE flush,
217
207
  VALUE start_timespec_seconds,
218
208
  VALUE start_timespec_nanoseconds,
219
209
  VALUE finish_timespec_seconds,
220
- VALUE finish_timespec_nanoseconds,
221
- VALUE pprof_file_name,
222
- VALUE pprof_data,
223
- VALUE code_provenance_file_name,
224
- VALUE code_provenance_data,
225
- VALUE tags_as_array,
226
- VALUE internal_metadata_json,
227
- VALUE info_json
210
+ VALUE finish_timespec_nanoseconds
228
211
  ) {
212
+ VALUE encoded_profile = rb_funcall(flush, rb_intern("encoded_profile"), 0);
213
+ VALUE code_provenance_file_name = rb_funcall(flush, rb_intern("code_provenance_file_name"), 0);
214
+ VALUE code_provenance_data = rb_funcall(flush, rb_intern("code_provenance_data"), 0);
215
+ VALUE tags_as_array = rb_funcall(flush, rb_intern("tags_as_array"), 0);
216
+ VALUE internal_metadata_json = rb_funcall(flush, rb_intern("internal_metadata_json"), 0);
217
+ VALUE info_json = rb_funcall(flush, rb_intern("info_json"), 0);
218
+
229
219
  ENFORCE_TYPE(upload_timeout_milliseconds, T_FIXNUM);
230
220
  ENFORCE_TYPE(start_timespec_seconds, T_FIXNUM);
231
221
  ENFORCE_TYPE(start_timespec_nanoseconds, T_FIXNUM);
232
222
  ENFORCE_TYPE(finish_timespec_seconds, T_FIXNUM);
233
223
  ENFORCE_TYPE(finish_timespec_nanoseconds, T_FIXNUM);
234
- ENFORCE_TYPE(pprof_file_name, T_STRING);
235
- ENFORCE_TYPE(pprof_data, T_STRING);
224
+ enforce_encoded_profile_instance(encoded_profile);
236
225
  ENFORCE_TYPE(code_provenance_file_name, T_STRING);
226
+ ENFORCE_TYPE(tags_as_array, T_ARRAY);
237
227
  ENFORCE_TYPE(internal_metadata_json, T_STRING);
238
228
  ENFORCE_TYPE(info_json, T_STRING);
239
229
 
@@ -256,6 +246,11 @@ static VALUE _native_do_export(
256
246
  ddog_prof_Exporter_Slice_File files_to_compress_and_export = {.ptr = to_compress, .len = to_compress_length};
257
247
  ddog_prof_Exporter_Slice_File files_to_export_unmodified = {.ptr = already_compressed, .len = already_compressed_length};
258
248
 
249
+ // TODO: Hardcoding the file name will go away with libdatadog 17
250
+ VALUE pprof_file_name = rb_str_new_cstr("rubyprofile.pprof");
251
+ VALUE pprof_data = rb_funcall(encoded_profile, rb_intern("_native_bytes"), 0);
252
+ ENFORCE_TYPE(pprof_data, T_STRING);
253
+
259
254
  already_compressed[0] = (ddog_prof_Exporter_File) {
260
255
  .name = char_slice_from_ruby_string(pprof_file_name),
261
256
  .file = byte_slice_from_ruby_string(pprof_data),
@@ -268,7 +263,6 @@ static VALUE _native_do_export(
268
263
  };
269
264
  }
270
265
 
271
- ddog_Vec_Tag *null_additional_tags = NULL;
272
266
  ddog_CharSlice internal_metadata = char_slice_from_ruby_string(internal_metadata_json);
273
267
  ddog_CharSlice info = char_slice_from_ruby_string(info_json);
274
268
 
@@ -293,7 +287,6 @@ static VALUE _native_do_export(
293
287
  finish,
294
288
  files_to_compress_and_export,
295
289
  files_to_export_unmodified,
296
- null_additional_tags,
297
290
  internal_metadata,
298
291
  info
299
292
  );
@@ -20,6 +20,7 @@ void collectors_dynamic_sampling_rate_init(VALUE profiling_module);
20
20
  void collectors_idle_sampling_helper_init(VALUE profiling_module);
21
21
  void collectors_stack_init(VALUE profiling_module);
22
22
  void collectors_thread_context_init(VALUE profiling_module);
23
+ void encoded_profile_init(VALUE profiling_module);
23
24
  void http_transport_init(VALUE profiling_module);
24
25
  void stack_recorder_init(VALUE profiling_module);
25
26
 
@@ -61,6 +62,7 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
61
62
  collectors_idle_sampling_helper_init(profiling_module);
62
63
  collectors_stack_init(profiling_module);
63
64
  collectors_thread_context_init(profiling_module);
65
+ encoded_profile_init(profiling_module);
64
66
  http_transport_init(profiling_module);
65
67
  stack_recorder_init(profiling_module);
66
68
  unsafe_api_calls_check_init();
@@ -8,6 +8,7 @@
8
8
  #include "ruby_helpers.h"
9
9
  #include "time_helpers.h"
10
10
  #include "heap_recorder.h"
11
+ #include "encoded_profile.h"
11
12
 
12
13
  // Used to wrap a ddog_prof_Profile in a Ruby object and expose Ruby-level serialization APIs
13
14
  // This file implements the native bits of the Datadog::Profiling::StackRecorder class
@@ -181,6 +182,7 @@ typedef struct {
181
182
  typedef struct {
182
183
  ddog_prof_Profile profile;
183
184
  stats_slot stats;
185
+ ddog_Timespec start_timestamp;
184
186
  } profile_slot;
185
187
 
186
188
  // Contains native state for each instance
@@ -252,7 +254,7 @@ static ddog_Timespec system_epoch_now_timespec(void);
252
254
  static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);
253
255
  static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time);
254
256
  static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
255
- static void reset_profile_slot(profile_slot *slot, ddog_Timespec *start_time /* Can be null */);
257
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp);
256
258
  static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class);
257
259
  static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations);
258
260
  static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
@@ -358,24 +360,26 @@ static void initialize_slot_concurrency_control(stack_recorder_state *state) {
358
360
  }
359
361
 
360
362
  static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types) {
363
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
364
+
361
365
  ddog_prof_Profile_NewResult slot_one_profile_result =
362
- ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
366
+ ddog_prof_Profile_new(sample_types, NULL /* period is optional */, &start_timestamp);
363
367
 
364
368
  if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
365
369
  rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
366
370
  }
367
371
 
368
- state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok };
372
+ state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
369
373
 
370
374
  ddog_prof_Profile_NewResult slot_two_profile_result =
371
- ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
375
+ ddog_prof_Profile_new(sample_types, NULL /* period is optional */, &start_timestamp);
372
376
 
373
377
  if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
374
378
  // Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
375
379
  rb_raise(rb_eRuntimeError, "Failed to initialize slot two profile: %"PRIsVALUE, get_error_details_and_drop(&slot_two_profile_result.err));
376
380
  }
377
381
 
378
- state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok };
382
+ state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok, .start_timestamp = start_timestamp };
379
383
  }
380
384
 
381
385
  static void stack_recorder_typed_data_free(void *state_ptr) {
@@ -564,18 +568,14 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
564
568
 
565
569
  state->stats_lifetime.serialization_successes++;
566
570
 
567
- VALUE encoded_pprof = ruby_string_from_vec_u8(serialized_profile.ok.buffer);
568
-
569
- ddog_Timespec ddprof_start = serialized_profile.ok.start;
570
- ddog_Timespec ddprof_finish = serialized_profile.ok.end;
571
+ // Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it
572
+ VALUE encoded_profile = from_ddog_prof_EncodedProfile(serialized_profile.ok);
571
573
 
572
- ddog_prof_EncodedProfile_drop(&serialized_profile.ok);
573
-
574
- VALUE start = ruby_time_from(ddprof_start);
575
- VALUE finish = ruby_time_from(ddprof_finish);
574
+ VALUE start = ruby_time_from(args.slot->start_timestamp);
575
+ VALUE finish = ruby_time_from(finish_timestamp);
576
576
  VALUE profile_stats = build_profile_stats(args.slot, serialization_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
577
577
 
578
- return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_pprof, profile_stats));
578
+ return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_profile, profile_stats));
579
579
  }
580
580
 
581
581
  static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
@@ -780,7 +780,7 @@ static void *call_serialize_without_gvl(void *call_args) {
780
780
  }
781
781
 
782
782
  VALUE enforce_recorder_instance(VALUE object) {
783
- Check_TypedStruct(object, &stack_recorder_typed_data);
783
+ ENFORCE_TYPED_DATA(object, &stack_recorder_typed_data);
784
784
  return object;
785
785
  }
786
786
 
@@ -889,9 +889,9 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_
889
889
  // In case the fork happened halfway through `serializer_flip_active_and_inactive_slots` execution and the
890
890
  // resulting state is inconsistent, we make sure to reset it back to the initial state.
891
891
  initialize_slot_concurrency_control(state);
892
-
893
- reset_profile_slot(&state->profile_slot_one, /* start_time: */ NULL);
894
- reset_profile_slot(&state->profile_slot_two, /* start_time: */ NULL);
892
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
893
+ reset_profile_slot(&state->profile_slot_one, start_timestamp);
894
+ reset_profile_slot(&state->profile_slot_two, start_timestamp);
895
895
 
896
896
  heap_recorder_after_fork(state->heap_recorder);
897
897
 
@@ -903,7 +903,7 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_
903
903
  static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time) {
904
904
  // Before making this profile active, we reset it so that it uses the correct start_time for its start
905
905
  profile_slot *next_profile_slot = (state->active_slot == 1) ? &state->profile_slot_two : &state->profile_slot_one;
906
- reset_profile_slot(next_profile_slot, &start_time);
906
+ reset_profile_slot(next_profile_slot, start_time);
907
907
  }
908
908
 
909
909
  static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint) {
@@ -948,11 +948,12 @@ static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locatio
948
948
  return Qnil;
949
949
  }
950
950
 
951
- static void reset_profile_slot(profile_slot *slot, ddog_Timespec *start_time /* Can be null */) {
952
- ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile, start_time);
951
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
952
+ ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile, &start_timestamp);
953
953
  if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
954
954
  rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
955
955
  }
956
+ slot->start_timestamp = start_timestamp;
956
957
  slot->stats = (stats_slot) {};
957
958
  }
958
959
 
@@ -27,6 +27,9 @@
27
27
  #define ENFORCE_BOOLEAN(value) \
28
28
  { if (RB_UNLIKELY(value != Qtrue && value != Qfalse)) raise_unexpected_type(value, ADD_QUOTES(value), "true or false", __FILE__, __LINE__, __func__); }
29
29
 
30
+ #define ENFORCE_TYPED_DATA(value, type) \
31
+ { if (RB_UNLIKELY(!rb_typeddata_is_kind_of(value, type))) raise_unexpected_type(value, ADD_QUOTES(value), "TypedData of type " ADD_QUOTES(type), __FILE__, __LINE__, __func__); }
32
+
30
33
  NORETURN(void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name));
31
34
 
32
35
  // Helper to retrieve Datadog::VERSION::STRING