ddtrace 1.11.1 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +6 -4
  4. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +34 -16
  5. data/ext/ddtrace_profiling_native_extension/extconf.rb +17 -3
  6. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +2 -2
  7. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +38 -4
  8. data/lib/datadog/appsec/assets/waf_rules/recommended.json +489 -133
  9. data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -47
  10. data/lib/datadog/appsec/configuration/settings.rb +2 -10
  11. data/lib/datadog/appsec/configuration.rb +3 -9
  12. data/lib/datadog/appsec/contrib/rack/ext.rb +0 -1
  13. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +12 -0
  14. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  15. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -9
  16. data/lib/datadog/appsec/contrib/rack/integration.rb +0 -5
  17. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +7 -1
  18. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +1 -1
  19. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +33 -25
  20. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -1
  21. data/lib/datadog/appsec/contrib/rails/framework.rb +1 -13
  22. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -3
  23. data/lib/datadog/appsec/contrib/rails/integration.rb +0 -5
  24. data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
  25. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -1
  26. data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -13
  27. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -6
  28. data/lib/datadog/appsec/contrib/sinatra/integration.rb +0 -5
  29. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -4
  30. data/lib/datadog/appsec/event.rb +5 -5
  31. data/lib/datadog/appsec/ext.rb +1 -0
  32. data/lib/datadog/appsec/extensions.rb +2 -6
  33. data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -4
  34. data/lib/datadog/appsec/processor/rule_merger.rb +13 -7
  35. data/lib/datadog/appsec/processor.rb +0 -45
  36. data/lib/datadog/appsec/remote.rb +6 -0
  37. data/lib/datadog/appsec/scope.rb +61 -0
  38. data/lib/datadog/appsec.rb +6 -0
  39. data/lib/datadog/ci/ext/environment.rb +40 -4
  40. data/lib/datadog/core/configuration/settings.rb +66 -14
  41. data/lib/datadog/core/configuration.rb +5 -1
  42. data/lib/datadog/core/remote/client/capabilities.rb +1 -1
  43. data/lib/datadog/core/telemetry/collector.rb +2 -1
  44. data/lib/datadog/core/telemetry/v1/dependency.rb +2 -1
  45. data/lib/datadog/kit/appsec/events.rb +58 -13
  46. data/lib/datadog/kit/identity.rb +29 -10
  47. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +2 -0
  48. data/lib/datadog/profiling/component.rb +54 -29
  49. data/lib/datadog/tracing/buffer.rb +0 -1
  50. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +9 -1
  51. data/lib/datadog/tracing/contrib/aws/ext.rb +11 -1
  52. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +7 -0
  53. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +4 -0
  54. data/lib/datadog/tracing/contrib/aws/service/base.rb +16 -0
  55. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +19 -0
  56. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +19 -0
  57. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +29 -0
  58. data/lib/datadog/tracing/contrib/aws/service/s3.rb +19 -0
  59. data/lib/datadog/tracing/contrib/aws/service/sns.rb +27 -0
  60. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +24 -0
  61. data/lib/datadog/tracing/contrib/aws/service/stepfunctions.rb +37 -0
  62. data/lib/datadog/tracing/contrib/aws/services.rb +10 -0
  63. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +6 -1
  64. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -2
  65. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +6 -1
  66. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -2
  67. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +6 -1
  68. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +5 -2
  69. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -1
  70. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +5 -2
  71. data/lib/datadog/tracing/contrib/patcher.rb +0 -1
  72. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -1
  73. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -2
  74. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +6 -1
  75. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -2
  76. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +10 -2
  77. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +9 -1
  78. data/lib/datadog/tracing/contrib/racecar/event.rb +3 -1
  79. data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -1
  80. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +6 -1
  81. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -1
  82. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +6 -1
  83. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  84. data/lib/datadog/tracing/contrib/roda/patcher.rb +1 -1
  85. data/lib/datadog/tracing/contrib/sequel/database.rb +4 -1
  86. data/lib/datadog/tracing/contrib/sequel/dataset.rb +4 -1
  87. data/lib/datadog/tracing/contrib/sequel/utils.rb +4 -1
  88. data/lib/datadog/tracing/contrib/status_code_matcher.rb +0 -1
  89. data/lib/datadog/tracing/correlation.rb +0 -1
  90. data/lib/datadog/tracing/distributed/headers/ext.rb +1 -1
  91. data/lib/datadog/tracing/event.rb +0 -2
  92. data/lib/datadog/tracing/pipeline.rb +0 -2
  93. data/lib/datadog/tracing/runtime/metrics.rb +0 -2
  94. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +0 -1
  95. data/lib/datadog/tracing/sampling/rate_sampler.rb +0 -2
  96. data/lib/datadog/tracing/sampling/rule.rb +0 -2
  97. data/lib/datadog/tracing/sampling/rule_sampler.rb +0 -2
  98. data/lib/datadog/tracing/span_operation.rb +0 -1
  99. data/lib/datadog/tracing/sync_writer.rb +0 -2
  100. data/lib/datadog/tracing/trace_operation.rb +0 -1
  101. data/lib/datadog/tracing/tracer.rb +0 -1
  102. data/lib/datadog/tracing/workers/trace_writer.rb +0 -1
  103. data/lib/datadog/tracing/workers.rb +0 -2
  104. data/lib/datadog/tracing/writer.rb +0 -2
  105. data/lib/ddtrace/version.rb +2 -2
  106. metadata +18 -19
  107. data/lib/datadog/appsec/contrib/configuration/settings.rb +0 -20
  108. data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +0 -22
  109. data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +0 -22
  110. data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fab36ba8f93f2c9b067c2fcb4916d6aff5ef906d6608671f035490f3b287c6c9
4
- data.tar.gz: 0f62cd63c95aa669f8981cb79c56e49228351a01920c142a36170a9443b60400
3
+ metadata.gz: 59174b63b257f636df60be99956c8e221fcf046ace610c57eb01192fac6560ad
4
+ data.tar.gz: 647e8de04a54a65b40ad7b20061a015f510966f7643c192df30f3710a8335386
5
5
  SHA512:
6
- metadata.gz: 6a747def8ca5cef1d31d72fff939567669c72db53b8c30a3b7cd14df8b52da21a4f5d18efbeba1a22686196923ed49195194b7a9136840428d73f4f8e985da67
7
- data.tar.gz: 72f36c83fac54b4d503d38f40759a89d400c5d70b24fbcb7ebc8a291d603c0bab07f28ca58082b732afb66960fe9d6e7ab7148147f0e1b727bbaeb4f08a885a6
6
+ metadata.gz: b677b76e9e3b00df5e9c5b33bfe8c6007cd867053366364769391bb1b41457e9e380c5869bb85cc97071969e4e6164fcbe89148aaac11828bdc9de7957cc5d21
7
+ data.tar.gz: 33d66238def0a52a491175d015bfe80e15b84e975abc974710d8b892fb76ffe4ff336a15f23341ecd94b5979d7015d75dc93587d7e227d0bd759c6fdb5c782c4
data/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.12.0] - 2023-06-02
6
+
7
+ ### Added
8
+ * Profiling: Add support for profiling Ruby 3.3.0-preview1 ([#2860][])
9
+ * Appsec: Appsec support nested apps ([#2836][])
10
+ * Appsec: Appsec add support for custom rules ([#2856][])
11
+ * Appsec: Update appsec static rules to 1.7.0 version ([#2869][])
12
+ * Appsec: Tag AppSec on Rack top-level span ([#2858][])
13
+ * Profiling: Implement "no signals" workaround and enable CPU Profiling 2.0 for all customers ([#2873][])
14
+ * Ci: Update CI Visibility spec ([#2874][])
15
+ * Appsec: Added missing waf addresses to request operation ([#2883][])
16
+
17
+ ### Changed
18
+
19
+ * Tracing: Consistent APM Span tags for AWS SDK Requests ([#2730][])
20
+ * Tracing: Change default `service_name` values Part 2 ([#2765][])
21
+ * Profiling: Bump debase-ruby_core_source dependency to 3.2.1 ([#2875][])
22
+
23
+ ### Fixed
24
+ * Telemetry: Disable for non-HTTP agent connection ([#2815][])
25
+ * Tracing: Fix circular requires ([#2826][])
26
+ * Tracing: Update comment about Datadog::Tracing::Distributed::Ext to correct modules ([#2840][])
27
+ * Appsec: Check if `:appsec` setting is present before accessing it in remote component ([#2854][])
28
+ * Telemetry: Do not send Dependency `hash` when `version` is present ([#2855][])
29
+ * Core: Fix symbol configuration for `env` and `service` ([#2864][])
30
+ * Tracing: Fix sql comment propagation `full` mode when tracing is disabled ([#2866][])
31
+ * Appsec: Use relative URI for server.request.uri.raw ([#2890][])
32
+
5
33
  ## [1.11.1] - 2023-05-03
6
34
 
7
35
  ### Fixed
@@ -2410,7 +2438,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
2410
2438
 
2411
2439
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2412
2440
 
2413
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.11.1...master
2441
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.12.0...master
2442
+ [1.12.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.11.1...v1.12.0
2414
2443
  [1.11.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...v1.11.1
2415
2444
  [1.11.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...v1.11.0
2416
2445
  [1.11.0.beta1]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...v1.11.0.beta1
@@ -3445,6 +3474,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3445
3474
  [#2720]: https://github.com/DataDog/dd-trace-rb/issues/2720
3446
3475
  [#2726]: https://github.com/DataDog/dd-trace-rb/issues/2726
3447
3476
  [#2727]: https://github.com/DataDog/dd-trace-rb/issues/2727
3477
+ [#2730]: https://github.com/DataDog/dd-trace-rb/issues/2730
3448
3478
  [#2731]: https://github.com/DataDog/dd-trace-rb/issues/2731
3449
3479
  [#2732]: https://github.com/DataDog/dd-trace-rb/issues/2732
3450
3480
  [#2733]: https://github.com/DataDog/dd-trace-rb/issues/2733
@@ -3455,6 +3485,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3455
3485
  [#2757]: https://github.com/DataDog/dd-trace-rb/issues/2757
3456
3486
  [#2760]: https://github.com/DataDog/dd-trace-rb/issues/2760
3457
3487
  [#2762]: https://github.com/DataDog/dd-trace-rb/issues/2762
3488
+ [#2765]: https://github.com/DataDog/dd-trace-rb/issues/2765
3458
3489
  [#2769]: https://github.com/DataDog/dd-trace-rb/issues/2769
3459
3490
  [#2770]: https://github.com/DataDog/dd-trace-rb/issues/2770
3460
3491
  [#2771]: https://github.com/DataDog/dd-trace-rb/issues/2771
@@ -3466,9 +3497,26 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3466
3497
  [#2805]: https://github.com/DataDog/dd-trace-rb/issues/2805
3467
3498
  [#2806]: https://github.com/DataDog/dd-trace-rb/issues/2806
3468
3499
  [#2810]: https://github.com/DataDog/dd-trace-rb/issues/2810
3500
+ [#2815]: https://github.com/DataDog/dd-trace-rb/issues/2815
3469
3501
  [#2822]: https://github.com/DataDog/dd-trace-rb/issues/2822
3470
3502
  [#2824]: https://github.com/DataDog/dd-trace-rb/issues/2824
3503
+ [#2826]: https://github.com/DataDog/dd-trace-rb/issues/2826
3471
3504
  [#2829]: https://github.com/DataDog/dd-trace-rb/issues/2829
3505
+ [#2836]: https://github.com/DataDog/dd-trace-rb/issues/2836
3506
+ [#2840]: https://github.com/DataDog/dd-trace-rb/issues/2840
3507
+ [#2854]: https://github.com/DataDog/dd-trace-rb/issues/2854
3508
+ [#2855]: https://github.com/DataDog/dd-trace-rb/issues/2855
3509
+ [#2856]: https://github.com/DataDog/dd-trace-rb/issues/2856
3510
+ [#2858]: https://github.com/DataDog/dd-trace-rb/issues/2858
3511
+ [#2860]: https://github.com/DataDog/dd-trace-rb/issues/2860
3512
+ [#2864]: https://github.com/DataDog/dd-trace-rb/issues/2864
3513
+ [#2866]: https://github.com/DataDog/dd-trace-rb/issues/2866
3514
+ [#2869]: https://github.com/DataDog/dd-trace-rb/issues/2869
3515
+ [#2873]: https://github.com/DataDog/dd-trace-rb/issues/2873
3516
+ [#2874]: https://github.com/DataDog/dd-trace-rb/issues/2874
3517
+ [#2875]: https://github.com/DataDog/dd-trace-rb/issues/2875
3518
+ [#2883]: https://github.com/DataDog/dd-trace-rb/issues/2883
3519
+ [#2890]: https://github.com/DataDog/dd-trace-rb/issues/2890
3472
3520
  [@AdrianLC]: https://github.com/AdrianLC
3473
3521
  [@Azure7111]: https://github.com/Azure7111
3474
3522
  [@BabyGroot]: https://github.com/BabyGroot
@@ -68,19 +68,19 @@ internal types, structures and functions).
68
68
 
69
69
  Because these private header files are not included in regular Ruby installations, we have two different workarounds:
70
70
 
71
- 1. for Ruby versions >= 2.6 we make use use the Ruby private MJIT header
72
- 2. for Ruby versions < 2.6 (legacy Rubies) we make use of the `debase-ruby_core_source` gem
71
+ 1. for Ruby versions 2.6 to 3.2 we make use use the Ruby private MJIT header
72
+ 2. for Ruby versions < 2.6 and > 3.2 we make use of the `debase-ruby_core_source` gem
73
73
 
74
74
  Functions which make use of these headers are defined in the <private_vm_api_acccess.c> file.
75
75
 
76
- There is currently no way for disabling usage of the private MJIT header for Ruby 2.6+.
76
+ There is currently no way for disabling usage of the private MJIT header for Ruby 2.6 to 3.2.
77
77
 
78
78
  **Important Note**: Our medium/long-term plan is to stop relying on all private Ruby headers, and instead request and
79
79
  contribute upstream changes so that they become official public VM APIs.
80
80
 
81
81
  ### Approach 1: Using the Ruby private MJIT header
82
82
 
83
- Ruby versions >= 2.6 introduced a JIT compiler called MJIT. This compiler does not directly generate machine code;
83
+ Ruby versions 2.6 to 3.2 shipped a JIT compiler called MJIT. This compiler does not directly generate machine code;
84
84
  instead it generates C code and uses the system C compiler to turn it into machine code.
85
85
 
86
86
  The generated C code `#include`s a private header -- which we reference as "the MJIT header" everywhere.
@@ -90,6 +90,8 @@ and of course the intention is that it is only used by the Ruby MJIT compiler.
90
90
  This header is placed inside the `include/` directory in a Ruby installation, and is named for that specific Ruby
91
91
  version. e.g. `rb_mjit_min_header-2.7.4.h`.
92
92
 
93
+ This header was removed in Ruby 3.3.
94
+
93
95
  ### Approach 2: Using the `debase-ruby_core_source` gem
94
96
 
95
97
  The [`debase-ruby_core_source`](https://github.com/ruby-debug/debase-ruby_core_source) contains almost no code;
@@ -81,6 +81,7 @@ struct cpu_and_wall_time_worker_state {
81
81
 
82
82
  bool gc_profiling_enabled;
83
83
  bool allocation_counting_enabled;
84
+ bool no_signals_workaround_enabled;
84
85
  bool dynamic_sampling_rate_enabled;
85
86
  VALUE self_instance;
86
87
  VALUE thread_context_collector_instance;
@@ -148,6 +149,7 @@ static VALUE _native_initialize(
148
149
  VALUE gc_profiling_enabled,
149
150
  VALUE idle_sampling_helper_instance,
150
151
  VALUE allocation_counting_enabled,
152
+ VALUE no_signals_workaround_enabled,
151
153
  VALUE dynamic_sampling_rate_enabled
152
154
  );
153
155
  static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
@@ -221,7 +223,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
221
223
  // https://bugs.ruby-lang.org/issues/18007 for a discussion around this.
222
224
  rb_define_alloc_func(collectors_cpu_and_wall_time_worker_class, _native_new);
223
225
 
224
- rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_initialize", _native_initialize, 6);
226
+ rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_initialize", _native_initialize, 7);
225
227
  rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_sampling_loop", _native_sampling_loop, 1);
226
228
  rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stop", _native_stop, 2);
227
229
  rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
@@ -257,6 +259,7 @@ static VALUE _native_new(VALUE klass) {
257
259
 
258
260
  state->gc_profiling_enabled = false;
259
261
  state->allocation_counting_enabled = false;
262
+ state->no_signals_workaround_enabled = false;
260
263
  state->dynamic_sampling_rate_enabled = true;
261
264
  state->thread_context_collector_instance = Qnil;
262
265
  state->idle_sampling_helper_instance = Qnil;
@@ -283,10 +286,12 @@ static VALUE _native_initialize(
283
286
  VALUE gc_profiling_enabled,
284
287
  VALUE idle_sampling_helper_instance,
285
288
  VALUE allocation_counting_enabled,
289
+ VALUE no_signals_workaround_enabled,
286
290
  VALUE dynamic_sampling_rate_enabled
287
291
  ) {
288
292
  ENFORCE_BOOLEAN(gc_profiling_enabled);
289
293
  ENFORCE_BOOLEAN(allocation_counting_enabled);
294
+ ENFORCE_BOOLEAN(no_signals_workaround_enabled);
290
295
  ENFORCE_BOOLEAN(dynamic_sampling_rate_enabled);
291
296
 
292
297
  struct cpu_and_wall_time_worker_state *state;
@@ -294,6 +299,7 @@ static VALUE _native_initialize(
294
299
 
295
300
  state->gc_profiling_enabled = (gc_profiling_enabled == Qtrue);
296
301
  state->allocation_counting_enabled = (allocation_counting_enabled == Qtrue);
302
+ state->no_signals_workaround_enabled = (no_signals_workaround_enabled == Qtrue);
297
303
  state->dynamic_sampling_rate_enabled = (dynamic_sampling_rate_enabled == Qtrue);
298
304
  state->thread_context_collector_instance = enforce_thread_context_collector_instance(thread_context_collector_instance);
299
305
  state->idle_sampling_helper_instance = idle_sampling_helper_instance;
@@ -439,7 +445,7 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
439
445
  }
440
446
 
441
447
  // We implicitly assume there can be no concurrent nor nested calls to handle_sampling_signal because
442
- // a) we get triggered using SIGPROF, and the docs state second SIGPROF will not interrupt an existing one
448
+ // a) we get triggered using SIGPROF, and the docs state a second SIGPROF will not interrupt an existing one
443
449
  // b) we validate we are in the thread that has the global VM lock; if a different thread gets a signal, it will return early
444
450
  // because it will not have the global VM lock
445
451
 
@@ -476,22 +482,34 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
476
482
  while (atomic_load(&state->should_run)) {
477
483
  state->stats.trigger_sample_attempts++;
478
484
 
479
- current_gvl_owner owner = gvl_owner();
480
- if (owner.valid) {
481
- // Note that reading the GVL owner and sending them a signal is a race -- the Ruby VM keeps on executing while
482
- // we're doing this, so we may still not signal the correct thread from time to time, but our signal handler
483
- // includes a check to see if it got called in the right thread
484
- pthread_kill(owner.owner, SIGPROF);
485
- } else {
486
- // If no thread owns the Global VM Lock, the application is probably idle at the moment. We still want to sample
487
- // so we "ask a friend" (the IdleSamplingHelper component) to grab the GVL and simulate getting a SIGPROF.
485
+ if (state->no_signals_workaround_enabled) {
486
+ // In the no_signals_workaround_enabled mode, the profiler never sends SIGPROF signals.
487
+ //
488
+ // This is a fallback for a few incompatibilities and limitations -- see the code that decides when to enable
489
+ // `no_signals_workaround_enabled` in `Profiling::Component` for details.
488
490
  //
489
- // In a previous version of the code, we called `grab_gvl_and_sample` directly BUT this was problematic because
490
- // Ruby may concurrently get busy and so the CpuAndWallTimeWorker would be blocked in line to acquire the GVL
491
- // for an uncontrolled amount of time. (This can still happen to the IdleSamplingHelper, but the
492
- // CpuAndWallTimeWorker will still be free to interrupt the Ruby VM and keep sampling for the entire blocking period).
491
+ // Thus, we instead pretty please ask Ruby to let us run. This means profiling data can be biased by when the Ruby
492
+ // scheduler chooses to schedule us.
493
493
  state->stats.trigger_simulated_signal_delivery_attempts++;
494
- idle_sampling_helper_request_action(state->idle_sampling_helper_instance, grab_gvl_and_sample);
494
+ grab_gvl_and_sample(); // Note: Can raise exceptions
495
+ } else {
496
+ current_gvl_owner owner = gvl_owner();
497
+ if (owner.valid) {
498
+ // Note that reading the GVL owner and sending them a signal is a race -- the Ruby VM keeps on executing while
499
+ // we're doing this, so we may still not signal the correct thread from time to time, but our signal handler
500
+ // includes a check to see if it got called in the right thread
501
+ pthread_kill(owner.owner, SIGPROF);
502
+ } else {
503
+ // If no thread owns the Global VM Lock, the application is probably idle at the moment. We still want to sample
504
+ // so we "ask a friend" (the IdleSamplingHelper component) to grab the GVL and simulate getting a SIGPROF.
505
+ //
506
+ // In a previous version of the code, we called `grab_gvl_and_sample` directly BUT this was problematic because
507
+ // Ruby may concurrently get busy and so the CpuAndWallTimeWorker would be blocked in line to acquire the GVL
508
+ // for an uncontrolled amount of time. (This can still happen to the IdleSamplingHelper, but the
509
+ // CpuAndWallTimeWorker will still be free to interrupt the Ruby VM and keep sampling for the entire blocking period).
510
+ state->stats.trigger_simulated_signal_delivery_attempts++;
511
+ idle_sampling_helper_request_action(state->idle_sampling_helper_instance, grab_gvl_and_sample);
512
+ }
495
513
  }
496
514
 
497
515
  sleep_for(minimum_time_between_signals);
@@ -81,7 +81,10 @@ end
81
81
 
82
82
  # Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
83
83
  # But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
84
- add_compiler_flag '-Werror' if ENV['DDTRACE_CI'] == 'true'
84
+ #
85
+ # @ivoanjo TODO: Ruby 3.3.0-preview1 was causing issues in CI because `have_header('vm_core.h')` below triggers warnings;
86
+ # I've chosen to disable `-Werror` for this Ruby version for now, and we can revisit this on a later 3.3 release.
87
+ add_compiler_flag '-Werror' if ENV['DDTRACE_CI'] == 'true' && !RUBY_DESCRIPTION.include?('3.3.0preview1')
85
88
 
86
89
  # Older gcc releases may not default to C99 and we need to ask for this. This is also used:
87
90
  # * by upstream Ruby -- search for gnu99 in the codebase
@@ -128,6 +131,12 @@ if RUBY_PLATFORM.include?('linux')
128
131
  $defs << '-DHAVE_PTHREAD_GETCPUCLOCKID'
129
132
  end
130
133
 
134
+ # On older Rubies, we did not need to include the ractor header (this was built into the MJIT header)
135
+ $defs << '-DNO_RACTOR_HEADER_INCLUDE' if RUBY_VERSION < '3.3'
136
+
137
+ # On older Rubies, some of the Ractor internal APIs were directly accessible
138
+ $defs << '-DUSE_RACTOR_INTERNAL_APIS_DIRECTLY' if RUBY_VERSION < '3.3'
139
+
131
140
  # On older Rubies, there was no struct rb_native_thread. See private_vm_api_acccess.c for details.
132
141
  $defs << '-DNO_RB_NATIVE_THREAD' if RUBY_VERSION < '3.2'
133
142
 
@@ -217,7 +226,8 @@ if Datadog::Profiling::NativeExtensionHelpers::CAN_USE_MJIT_HEADER
217
226
 
218
227
  create_makefile EXTENSION_NAME
219
228
  else
220
- # On older Rubies, we use the debase-ruby_core_source gem to get access to private VM headers.
229
+ # The MJIT header was introduced on 2.6 and removed on 3.3; for other Rubies we rely on
230
+ # the debase-ruby_core_source gem to get access to private VM headers.
221
231
  # This gem ships source code copies of these VM headers for the different Ruby VM versions;
222
232
  # see https://github.com/ruby-debug/debase-ruby_core_source for details
223
233
 
@@ -228,7 +238,11 @@ else
228
238
 
229
239
  Debase::RubyCoreSource
230
240
  .create_makefile_with_core(
231
- proc { have_header('vm_core.h') && have_header('iseq.h') },
241
+ proc do
242
+ have_header('vm_core.h') &&
243
+ have_header('iseq.h') &&
244
+ (RUBY_VERSION < '3.3' || have_header('ractor_core.h'))
245
+ end,
232
246
  EXTENSION_NAME,
233
247
  )
234
248
  end
@@ -12,8 +12,8 @@ module Datadog
12
12
  # Can be set to force rubygems to fail gem installation when profiling extension could not be built
13
13
  ENV_FAIL_INSTALL_IF_MISSING_EXTENSION = 'DD_PROFILING_FAIL_INSTALL_IF_MISSING_EXTENSION'
14
14
 
15
- # Older Rubies don't have the MJIT header, used by the JIT compiler, so we need to use a different approach
16
- CAN_USE_MJIT_HEADER = RUBY_VERSION >= '2.6'
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
+ CAN_USE_MJIT_HEADER = RUBY_VERSION.start_with?('2.6', '2.7', '3.0.', '3.1.', '3.2.')
17
17
 
18
18
  LIBDATADOG_VERSION = '~> 2.0.0.1.0'
19
19
 
@@ -12,7 +12,8 @@
12
12
  // Pick up internal structures from the private Ruby MJIT header file
13
13
  #include RUBY_MJIT_HEADER
14
14
  #else
15
- // On older Rubies, use a copy of the VM internal headers shipped in the debase-ruby_core_source gem
15
+ // The MJIT header was introduced on 2.6 and removed on 3.3; for other Rubies we rely on
16
+ // the debase-ruby_core_source gem to get access to private VM headers.
16
17
 
17
18
  // We can't do anything about warnings in VM headers, so we just use this technique to suppress them.
18
19
  // See https://nelkinda.com/blog/suppress-warnings-in-gcc-and-clang/#d11e364 for details.
@@ -23,7 +24,20 @@
23
24
  #pragma GCC diagnostic ignored "-Wexpansion-to-defined"
24
25
  #include <vm_core.h>
25
26
  #pragma GCC diagnostic pop
26
- #include <iseq.h>
27
+
28
+ #pragma GCC diagnostic push
29
+ #pragma GCC diagnostic ignored "-Wunused-parameter"
30
+ #include <iseq.h>
31
+ #pragma GCC diagnostic pop
32
+
33
+ #include <ruby.h>
34
+
35
+ #ifndef NO_RACTOR_HEADER_INCLUDE
36
+ #pragma GCC diagnostic push
37
+ #pragma GCC diagnostic ignored "-Wunused-parameter"
38
+ #include <ractor_core.h>
39
+ #pragma GCC diagnostic pop
40
+ #endif
27
41
  #endif
28
42
 
29
43
  #define PRIVATE_VM_API_ACCESS_SKIP_RUBY_INCLUDES
@@ -712,8 +726,28 @@ check_method_entry(VALUE obj, int can_be_svar)
712
726
  #ifndef NO_RACTORS
713
727
  // This API and definition are exported as a public symbol by the VM BUT the function header is not defined in any public header, so we
714
728
  // repeat it here to be able to use in our code.
715
- bool rb_ractor_main_p_(void);
716
- extern struct rb_ractor_struct *ruby_single_main_ractor;
729
+ #ifndef USE_RACTOR_INTERNAL_APIS_DIRECTLY
730
+ // Disable fast path for detecting multiple Ractors. Unfortunately this symbol is no longer visible on modern Ruby
731
+ // versions, so we need to do a bit more work.
732
+ struct rb_ractor_struct *ruby_single_main_ractor = NULL;
733
+
734
+ // Taken from upstream ractor.c at commit a1b01e7701f9fc370f8dff777aad6d39a2c5a3e3 (May 2023, Ruby 3.3.0-preview1)
735
+ // to allow us to ensure that we're always operating on the main ractor (if Ruby has ractors)
736
+ // Modifications:
737
+ // * None
738
+ bool rb_ractor_main_p_(void)
739
+ {
740
+ VM_ASSERT(rb_multi_ractor_p());
741
+ rb_execution_context_t *ec = GET_EC();
742
+ return rb_ec_ractor_ptr(ec) == rb_ec_vm_ptr(ec)->ractor.main_ractor;
743
+ }
744
+ #else
745
+ // Directly access Ruby internal fast path for detecting multiple Ractors.
746
+ extern struct rb_ractor_struct *ruby_single_main_ractor;
747
+
748
+ // Ruby 3.0 to 3.2 directly expose this symbol, we just need to tell the compiler it exists.
749
+ bool rb_ractor_main_p_(void);
750
+ #endif
717
751
 
718
752
  // Taken from upstream ractor_core.h at commit d9cf0388599a3234b9f3c06ddd006cd59a58ab8b (November 2022, Ruby 3.2 trunk)
719
753
  // to allow us to ensure that we're always operating on the main ractor (if Ruby has ractors)