datadog 2.10.0 → 2.11.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -1
  3. data/ext/datadog_profiling_native_extension/collectors_stack.c +3 -3
  4. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +44 -1
  5. data/ext/datadog_profiling_native_extension/extconf.rb +4 -0
  6. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  7. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  9. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +56 -0
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +7 -0
  11. data/ext/datadog_profiling_native_extension/profiling.c +7 -0
  12. data/ext/libdatadog_api/crashtracker.c +4 -4
  13. data/ext/libdatadog_extconf_helpers.rb +1 -1
  14. data/lib/datadog/appsec/configuration/settings.rb +64 -11
  15. data/lib/datadog/appsec/contrib/active_record/patcher.rb +0 -3
  16. data/lib/datadog/appsec/contrib/devise/configuration.rb +76 -0
  17. data/lib/datadog/appsec/contrib/devise/event.rb +4 -7
  18. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +16 -21
  19. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +8 -15
  20. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +1 -1
  21. data/lib/datadog/appsec/contrib/devise/patcher.rb +0 -3
  22. data/lib/datadog/appsec/contrib/devise/tracking.rb +1 -1
  23. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  24. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  25. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +43 -0
  26. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  27. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  28. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  29. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  30. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
  31. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +10 -12
  32. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  33. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +65 -73
  34. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  35. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +20 -25
  36. data/lib/datadog/appsec/contrib/rails/patcher.rb +0 -3
  37. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +38 -49
  38. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +0 -3
  39. data/lib/datadog/appsec/monitor/gateway/watcher.rb +19 -25
  40. data/lib/datadog/appsec/remote.rb +4 -0
  41. data/lib/datadog/appsec.rb +2 -0
  42. data/lib/datadog/core/configuration/components.rb +7 -1
  43. data/lib/datadog/core/configuration/ext.rb +1 -1
  44. data/lib/datadog/core/configuration/option_definition.rb +2 -0
  45. data/lib/datadog/core/configuration/settings.rb +22 -6
  46. data/lib/datadog/core/encoding.rb +16 -0
  47. data/lib/datadog/core/environment/agent_info.rb +77 -0
  48. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  49. data/lib/datadog/core/remote/transport/http/config.rb +0 -18
  50. data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -18
  51. data/lib/datadog/core/remote/transport/http.rb +7 -12
  52. data/lib/datadog/core/remote/transport/negotiation.rb +13 -1
  53. data/lib/datadog/core/telemetry/event.rb +5 -0
  54. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  55. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +1 -1
  56. data/lib/datadog/{tracing → core}/transport/http/api/spec.rb +1 -1
  57. data/lib/datadog/{tracing → core}/transport/http/builder.rb +37 -17
  58. data/lib/datadog/core/transport/response.rb +4 -0
  59. data/lib/datadog/di/code_tracker.rb +15 -8
  60. data/lib/datadog/di/component.rb +1 -0
  61. data/lib/datadog/di/configuration/settings.rb +14 -0
  62. data/lib/datadog/di/contrib.rb +2 -0
  63. data/lib/datadog/di/logger.rb +30 -0
  64. data/lib/datadog/di/probe.rb +3 -6
  65. data/lib/datadog/di/probe_manager.rb +5 -2
  66. data/lib/datadog/di/probe_notifier_worker.rb +15 -4
  67. data/lib/datadog/di/remote.rb +3 -3
  68. data/lib/datadog/di/utils.rb +91 -0
  69. data/lib/datadog/di.rb +3 -0
  70. data/lib/datadog/profiling/component.rb +2 -8
  71. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  72. data/lib/datadog/tracing/configuration/ext.rb +1 -0
  73. data/lib/datadog/tracing/contrib/extensions.rb +14 -0
  74. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  75. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  76. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  77. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  78. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  79. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  80. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  81. data/lib/datadog/tracing/transport/http/api.rb +11 -2
  82. data/lib/datadog/tracing/transport/http/traces.rb +0 -3
  83. data/lib/datadog/tracing/transport/http.rb +12 -7
  84. data/lib/datadog/tracing/transport/serializable_trace.rb +8 -4
  85. data/lib/datadog/tracing/transport/traces.rb +25 -8
  86. data/lib/datadog/version.rb +1 -1
  87. metadata +23 -28
  88. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  89. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  90. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  91. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  92. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  93. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  94. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  95. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  96. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  97. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  98. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  99. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  100. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  101. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  102. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  103. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88fca1176a1b0fe35703ec00277925dd64a377c6736c52674f5aeb3195ec4d86
4
- data.tar.gz: 92631bc4c25b6132821d30858e99e8cd8308445f99a258226508ed04f4a696ba
3
+ metadata.gz: ae1f5db840520c849d4a21b02232137e5272619ddd7fb46126f263c71c8a5849
4
+ data.tar.gz: bd1b16b752c9e457722965ee29cf8af770ba1dcf3b42cac412c206f6245dd333
5
5
  SHA512:
6
- metadata.gz: 19a5fd9e66f759a1db3aee5cb1496abaa7393381809eaa956d27b8eb045fb993d7f77ef11c305a97b44bd627294e44fde236836d10c9458fc1543846d58e36e1
7
- data.tar.gz: 42bbfab98df4de69947602daa14f75bbb2cdf170bf8203164fb93f496c16d824aea2f659d93688c67e4f0baf7d5221ea1908a4ab5f714d903a9268916a5387ce
6
+ metadata.gz: 072e88d7ba0698a8ef6b080b6b1ab6a5be18b4a69fdb142b42494bc0afc6184aadbe7c4f52e54e2373a37f40fe439215a8a9a4594653d4d6453ef614142ca8e7
7
+ data.tar.gz: 88cb6087f42bc450a517d53338772b4fb10b00fe40024843fec3df3849bbc14f6efd25defaf1dcadb9224c9513878c75e2ee33fb0d3d24bb063ca1d2dd36dcb6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.11.0] - 2025-02-24
6
+
7
+ ### Added
8
+
9
+ * Tracing: Support `graphql` multiple query errors report via Span Events ([#4177][])
10
+ * Profiling: Enable GVL profiling by default on Ruby 3.2+ ([#4406][])
11
+ * Profiling: Support correlating profiling with OTel API 1.5+ ([#4425][])
12
+ * AppSec: Add detection of Server-Side Request Forgery attacks for `excon` ([#4399][])
13
+ * AppSec: Add detection of Server-Side Request Forgery attacks for `faraday` ([#4391][])
14
+ * AppSec: Deprecate `appsec.track_user_events` configuration setting in favor of `appsec.auto_user_instrumentation` ([#4352][])
15
+ * Dynamic Instrumentation: Add optional trace logging ([#4283][])
16
+
17
+ ### Changed
18
+
19
+ * Increase default timeout for unix domain socket to 30 seconds ([#4411][])
20
+ * Upgrade `libdatadog` to `16.0.1` ([#4353][])
21
+ * Dynamic Instrumentation: Improve path matching with prefixes of probe paths ([#4346][])
22
+ * Dynamic Instrumentation: Improve event reporting with combing status and snapshot events ([#4360][])
23
+
24
+ ### Fixed
25
+
26
+ * Tracing: Fix `rack` to continue trace if only distributed trace is present ([#4398][])
27
+ * AppSec: Fix a memory leak issue for RASP ([#4422][])
28
+ * Dynamic Instrumentation: Fix event submission on forked servers ([#4363][])
29
+
30
+ ### Removed
31
+
32
+ * Tracing: Remove peer services by default ([#3846][])
33
+
5
34
  ## [2.10.0] - 2025-02-04
6
35
 
7
36
  ### Added
@@ -3097,7 +3126,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3097
3126
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3098
3127
 
3099
3128
 
3100
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.10.0...master
3129
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.11.0...master
3130
+ [2.11.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.10.0...v2.11.0
3101
3131
  [2.10.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.9.0...v2.10.0
3102
3132
  [2.9.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.8.0...v2.9.0
3103
3133
  [2.8.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.7.1...v2.8.0
@@ -4525,6 +4555,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4525
4555
  [#3837]: https://github.com/DataDog/dd-trace-rb/issues/3837
4526
4556
  [#3839]: https://github.com/DataDog/dd-trace-rb/issues/3839
4527
4557
  [#3841]: https://github.com/DataDog/dd-trace-rb/issues/3841
4558
+ [#3846]: https://github.com/DataDog/dd-trace-rb/issues/3846
4528
4559
  [#3849]: https://github.com/DataDog/dd-trace-rb/issues/3849
4529
4560
  [#3852]: https://github.com/DataDog/dd-trace-rb/issues/3852
4530
4561
  [#3857]: https://github.com/DataDog/dd-trace-rb/issues/3857
@@ -4558,6 +4589,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4558
4589
  [#4161]: https://github.com/DataDog/dd-trace-rb/issues/4161
4559
4590
  [#4164]: https://github.com/DataDog/dd-trace-rb/issues/4164
4560
4591
  [#4167]: https://github.com/DataDog/dd-trace-rb/issues/4167
4592
+ [#4177]: https://github.com/DataDog/dd-trace-rb/issues/4177
4561
4593
  [#4178]: https://github.com/DataDog/dd-trace-rb/issues/4178
4562
4594
  [#4195]: https://github.com/DataDog/dd-trace-rb/issues/4195
4563
4595
  [#4196]: https://github.com/DataDog/dd-trace-rb/issues/4196
@@ -4572,6 +4604,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4572
4604
  [#4257]: https://github.com/DataDog/dd-trace-rb/issues/4257
4573
4605
  [#4266]: https://github.com/DataDog/dd-trace-rb/issues/4266
4574
4606
  [#4272]: https://github.com/DataDog/dd-trace-rb/issues/4272
4607
+ [#4283]: https://github.com/DataDog/dd-trace-rb/issues/4283
4575
4608
  [#4285]: https://github.com/DataDog/dd-trace-rb/issues/4285
4576
4609
  [#4288]: https://github.com/DataDog/dd-trace-rb/issues/4288
4577
4610
  [#4292]: https://github.com/DataDog/dd-trace-rb/issues/4292
@@ -4580,6 +4613,18 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4580
4613
  [#4311]: https://github.com/DataDog/dd-trace-rb/issues/4311
4581
4614
  [#4321]: https://github.com/DataDog/dd-trace-rb/issues/4321
4582
4615
  [#4323]: https://github.com/DataDog/dd-trace-rb/issues/4323
4616
+ [#4346]: https://github.com/DataDog/dd-trace-rb/issues/4346
4617
+ [#4352]: https://github.com/DataDog/dd-trace-rb/issues/4352
4618
+ [#4353]: https://github.com/DataDog/dd-trace-rb/issues/4353
4619
+ [#4360]: https://github.com/DataDog/dd-trace-rb/issues/4360
4620
+ [#4363]: https://github.com/DataDog/dd-trace-rb/issues/4363
4621
+ [#4391]: https://github.com/DataDog/dd-trace-rb/issues/4391
4622
+ [#4398]: https://github.com/DataDog/dd-trace-rb/issues/4398
4623
+ [#4399]: https://github.com/DataDog/dd-trace-rb/issues/4399
4624
+ [#4406]: https://github.com/DataDog/dd-trace-rb/issues/4406
4625
+ [#4411]: https://github.com/DataDog/dd-trace-rb/issues/4411
4626
+ [#4422]: https://github.com/DataDog/dd-trace-rb/issues/4422
4627
+ [#4425]: https://github.com/DataDog/dd-trace-rb/issues/4425
4583
4628
  [@AdrianLC]: https://github.com/AdrianLC
4584
4629
  [@Azure7111]: https://github.com/Azure7111
4585
4630
  [@BabyGroot]: https://github.com/BabyGroot
@@ -300,7 +300,7 @@ void sample_thread(
300
300
  }
301
301
 
302
302
  buffer->locations[i] = (ddog_prof_Location) {
303
- .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
303
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
304
304
  .function = (ddog_prof_Function) {.name = name_slice, .filename = filename_slice},
305
305
  .line = line,
306
306
  };
@@ -379,7 +379,7 @@ static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer*
379
379
  ddog_CharSlice function_name = DDOG_CHARSLICE_C("");
380
380
  ddog_CharSlice function_filename = {.ptr = frames_omitted_message, .len = strlen(frames_omitted_message)};
381
381
  buffer->locations[buffer->max_frames - 1] = (ddog_prof_Location) {
382
- .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
382
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
383
383
  .function = (ddog_prof_Function) {.name = function_name, .filename = function_filename},
384
384
  .line = 0,
385
385
  };
@@ -426,7 +426,7 @@ void record_placeholder_stack(
426
426
  ddog_CharSlice placeholder_stack
427
427
  ) {
428
428
  ddog_prof_Location placeholder_location = {
429
- .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
429
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
430
430
  .function = {.name = DDOG_CHARSLICE_C(""), .filename = placeholder_stack},
431
431
  .line = 0,
432
432
  };
@@ -1,5 +1,6 @@
1
1
  #include <ruby.h>
2
2
 
3
+ #include "datadog_ruby_common.h"
3
4
  #include "collectors_thread_context.h"
4
5
  #include "clock_id.h"
5
6
  #include "collectors_stack.h"
@@ -102,6 +103,7 @@ static ID at_kind_id; // id of :@kind in Ruby
102
103
  static ID at_name_id; // id of :@name in Ruby
103
104
  static ID server_id; // id of :server in Ruby
104
105
  static ID otel_context_storage_id; // id of :__opentelemetry_context_storage__ in Ruby
106
+ static ID otel_fiber_context_storage_id; // id of :@opentelemetry_context in Ruby
105
107
 
106
108
  // This is used by `thread_context_collector_on_gvl_running`. Because when that method gets called we're not sure if
107
109
  // it's safe to access the state of the thread context collector, we store this setting as a global value. This does
@@ -111,6 +113,7 @@ static ID otel_context_storage_id; // id of :__opentelemetry_context_storage__ i
111
113
  static uint32_t global_waiting_for_gvl_threshold_ns = MILLIS_AS_NS(10);
112
114
 
113
115
  typedef enum { OTEL_CONTEXT_ENABLED_FALSE, OTEL_CONTEXT_ENABLED_ONLY, OTEL_CONTEXT_ENABLED_BOTH } otel_context_enabled;
116
+ typedef enum { OTEL_CONTEXT_SOURCE_UNKNOWN, OTEL_CONTEXT_SOURCE_FIBER_IVAR, OTEL_CONTEXT_SOURCE_FIBER_LOCAL } otel_context_source;
114
117
 
115
118
  // Contains state for a single ThreadContext instance
116
119
  typedef struct {
@@ -140,6 +143,8 @@ typedef struct {
140
143
  bool timeline_enabled;
141
144
  // Used to control context collection
142
145
  otel_context_enabled otel_context_enabled;
146
+ // Used to remember where otel context is being stored after we observe it the first time
147
+ otel_context_source otel_context_source;
143
148
  // Used when calling monotonic_to_system_epoch_ns
144
149
  monotonic_to_system_epoch_state time_converter_state;
145
150
  // Used to identify the main thread, to give it a fallback name
@@ -348,6 +353,7 @@ void collectors_thread_context_init(VALUE profiling_module) {
348
353
  at_name_id = rb_intern_const("@name");
349
354
  server_id = rb_intern_const("server");
350
355
  otel_context_storage_id = rb_intern_const("__opentelemetry_context_storage__");
356
+ otel_fiber_context_storage_id = rb_intern_const("@opentelemetry_context");
351
357
 
352
358
  #ifndef NO_GVL_INSTRUMENTATION
353
359
  // This will raise if Ruby already ran out of thread-local keys
@@ -433,6 +439,7 @@ static VALUE _native_new(VALUE klass) {
433
439
  state->endpoint_collection_enabled = true;
434
440
  state->timeline_enabled = true;
435
441
  state->otel_context_enabled = OTEL_CONTEXT_ENABLED_FALSE;
442
+ state->otel_context_source = OTEL_CONTEXT_SOURCE_UNKNOWN;
436
443
  state->time_converter_state = (monotonic_to_system_epoch_state) MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER;
437
444
  VALUE main_thread = rb_thread_main();
438
445
  state->main_thread = main_thread;
@@ -1682,6 +1689,42 @@ static VALUE _native_sample_skipped_allocation_samples(DDTRACE_UNUSED VALUE self
1682
1689
  return Qtrue;
1683
1690
  }
1684
1691
 
1692
+ #ifndef NO_CURRENT_FIBER_FOR // Ruby 3.1+
1693
+ static VALUE otel_context_storage_for(thread_context_collector_state *state, VALUE thread) {
1694
+ if (state->otel_context_source == OTEL_CONTEXT_SOURCE_FIBER_IVAR) { // otel-api 1.5+
1695
+ VALUE current_fiber = current_fiber_for(thread);
1696
+ return current_fiber == Qnil ? Qnil : rb_ivar_get(current_fiber, otel_fiber_context_storage_id /* @opentelemetry_context */);
1697
+ }
1698
+
1699
+ if (state->otel_context_source == OTEL_CONTEXT_SOURCE_FIBER_LOCAL) { // otel-api < 1.5
1700
+ return rb_thread_local_aref(thread, otel_context_storage_id /* __opentelemetry_context_storage__ */);
1701
+ }
1702
+
1703
+ // If we got here, it means we never observed a context being set. Let's probe which one to use.
1704
+ VALUE current_fiber = current_fiber_for(thread);
1705
+ if (current_fiber != Qnil) {
1706
+ VALUE context_storage = rb_ivar_get(current_fiber, otel_fiber_context_storage_id /* @opentelemetry_context */);
1707
+ if (context_storage != Qnil) {
1708
+ state->otel_context_source = OTEL_CONTEXT_SOURCE_FIBER_IVAR; // Remember for next time
1709
+ return context_storage;
1710
+ }
1711
+ } else {
1712
+ VALUE context_storage = rb_thread_local_aref(thread, otel_context_storage_id /* __opentelemetry_context_storage__ */);
1713
+ if (context_storage != Qnil) {
1714
+ state->otel_context_source = OTEL_CONTEXT_SOURCE_FIBER_LOCAL; // Remember for next time
1715
+ return context_storage;
1716
+ }
1717
+ }
1718
+
1719
+ // There's no context storage attached to the current thread
1720
+ return Qnil;
1721
+ }
1722
+ #else
1723
+ static inline VALUE otel_context_storage_for(DDTRACE_UNUSED thread_context_collector_state *state, VALUE thread) {
1724
+ return rb_thread_local_aref(thread, otel_context_storage_id /* __opentelemetry_context_storage__ */);
1725
+ }
1726
+ #endif
1727
+
1685
1728
  // This method differs from trace_identifiers_for/ddtrace_otel_trace_identifiers_for to support the situation where
1686
1729
  // the opentelemetry ruby library is being used for tracing AND the ddtrace tracing bits are not involved at all.
1687
1730
  //
@@ -1709,7 +1752,7 @@ static void otel_without_ddtrace_trace_identifiers_for(
1709
1752
  trace_identifiers *trace_identifiers_result,
1710
1753
  bool is_safe_to_allocate_objects
1711
1754
  ) {
1712
- VALUE context_storage = rb_thread_local_aref(thread, otel_context_storage_id /* __opentelemetry_context_storage__ */);
1755
+ VALUE context_storage = otel_context_storage_for(state, thread);
1713
1756
 
1714
1757
  // If it exists, context_storage is expected to be an Array[OpenTelemetry::Context]
1715
1758
  if (context_storage == Qnil || !RB_TYPE_P(context_storage, T_ARRAY)) return;
@@ -164,6 +164,10 @@ $defs << "-DNO_INT_FIRST_LINENO" if RUBY_VERSION < "3.2"
164
164
  # On older Rubies, "pop" was not a primitive operation
165
165
  $defs << "-DNO_PRIMITIVE_POP" if RUBY_VERSION < "3.2"
166
166
 
167
+ # We could support this for older Rubies, but since this only gets used by the OTEL context extraction, and that
168
+ # use-case is only for 3.1+, we didn't bother supporting it farther back yet.
169
+ $defs << "-DNO_CURRENT_FIBER_FOR" if RUBY_VERSION < "3.1"
170
+
167
171
  # On older Rubies, there was no tid member in the internal thread structure
168
172
  $defs << "-DNO_THREAD_TID" if RUBY_VERSION < "3.1"
169
173
 
@@ -1,5 +1,7 @@
1
1
  #include <ruby.h>
2
2
  #include <ruby/thread.h>
3
+
4
+ #include "datadog_ruby_common.h"
3
5
  #include "gvl_profiling_helper.h"
4
6
 
5
7
  #if !defined(NO_GVL_INSTRUMENTATION) && !defined(USE_GVL_PROFILING_3_2_WORKAROUNDS) // Ruby 3.3+
@@ -39,14 +39,6 @@
39
39
 
40
40
  static inline void gvl_profiling_init(void) { }
41
41
 
42
- // This header gets included in private_vm_access.c which can't include datadog_ruby_common.h so we replicate this
43
- // helper here
44
- #ifdef __GNUC__
45
- #define DDTRACE_UNUSED __attribute__((unused))
46
- #else
47
- #define DDTRACE_UNUSED
48
- #endif
49
-
50
42
  // NOTE: This is a hack that relies on the knowledge that on Ruby 3.2 the
51
43
  // RUBY_INTERNAL_THREAD_EVENT_READY and RUBY_INTERNAL_THREAD_EVENT_RESUMED events always get called on the thread they
52
44
  // are about. Thus, we can use our thread local storage hack to get this data, even though the event doesn't include it.
@@ -678,7 +678,7 @@ static int st_object_records_iterate(DDTRACE_UNUSED st_data_t key, st_data_t val
678
678
  for (uint16_t i = 0; i < stack->frames_len; i++) {
679
679
  const heap_frame *frame = &stack->frames[i];
680
680
  locations[i] = (ddog_prof_Location) {
681
- .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C("")},
681
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
682
682
  .function = {
683
683
  .name = {.ptr = frame->name, .len = strlen(frame->name)},
684
684
  .filename = {.ptr = frame->filename, .len = strlen(frame->filename)},
@@ -40,6 +40,13 @@
40
40
  #endif
41
41
  #endif
42
42
 
43
+ // This file can't include datadog_ruby_common.h so we replicate this here
44
+ #ifdef __GNUC__
45
+ #define DDTRACE_UNUSED __attribute__((unused))
46
+ #else
47
+ #define DDTRACE_UNUSED
48
+ #endif
49
+
43
50
  #define PRIVATE_VM_API_ACCESS_SKIP_RUBY_INCLUDES
44
51
  #include "private_vm_api_access.h"
45
52
 
@@ -803,3 +810,52 @@ static inline int ddtrace_imemo_type(VALUE imemo) {
803
810
 
804
811
  // Is the VM smack in the middle of raising an exception?
805
812
  bool is_raised_flag_set(VALUE thread) { return thread_struct_from_object(thread)->ec->raised_flag > 0; }
813
+
814
+ #ifndef NO_CURRENT_FIBER_FOR
815
+ // The following three declarations are all
816
+ // taken from upstream cont.c at commit d97884a58be32e829fd03a80cd521f4733d65c79 (February 2025, master branch)
817
+ // (See the Ruby project copyright and license above)
818
+ // to enable building `current_fiber_for`.
819
+ //
820
+ // We needed to copy them because they aren't otherwise exposed in any VM APIs or headers.
821
+ // @ivoanjo: I manually checked the Ruby 3.1, 3.2, 3.3 and 3.4 branches + master, and the parts we care about in these
822
+ // structures have not changed in many years (in fact, last change I spotted was for 2.7).
823
+ enum context_type {
824
+ CONTINUATION_CONTEXT = 0,
825
+ FIBER_CONTEXT = 1
826
+ };
827
+
828
+ typedef struct rb_context_struct { // This declaration is incomplete -- only contains up to `self` which is the part we care about
829
+ enum context_type type;
830
+ int argc;
831
+ int kw_splat;
832
+ VALUE self;
833
+ } rb_context_t;
834
+
835
+ struct rb_fiber_struct { // This declaration is incomplete -- only contains the first entry which is the part we care about
836
+ rb_context_t cont;
837
+ };
838
+
839
+ VALUE current_fiber_for(VALUE thread) {
840
+ VALUE self = thread_struct_from_object(thread)->ec->fiber_ptr->cont.self;
841
+ return self == 0 ? Qnil : self;
842
+ }
843
+
844
+ void self_test_current_fiber_for(void) {
845
+ VALUE expected_current_fiber = current_fiber_for(rb_thread_current());
846
+ VALUE actual_current_fiber = rb_fiber_current();
847
+
848
+ if (expected_current_fiber == Qnil) {
849
+ // On purpose above we tried reading before calling `rb_fiber_current()` so the fiber may have not existed yet.
850
+ // But now it should be there.
851
+ expected_current_fiber = current_fiber_for(rb_thread_current());
852
+ }
853
+
854
+ if (expected_current_fiber != actual_current_fiber) rb_raise(rb_eRuntimeError, "current_fiber_for() self-test failed");
855
+ }
856
+ #else
857
+ NORETURN(VALUE current_fiber_for(DDTRACE_UNUSED VALUE thread));
858
+
859
+ VALUE current_fiber_for(DDTRACE_UNUSED VALUE thread) { rb_raise(rb_eRuntimeError, "Not implemented for Ruby < 3.1"); }
860
+ void self_test_current_fiber_for(void) { } // Nothing to do
861
+ #endif
@@ -44,6 +44,7 @@ bool is_thread_alive(VALUE thread);
44
44
  VALUE thread_name_for(VALUE thread);
45
45
 
46
46
  int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *stack_buffer);
47
+
47
48
  // Returns true if the current thread belongs to the main Ractor or if Ruby has no Ractor support
48
49
  bool ddtrace_rb_ractor_main_p(void);
49
50
 
@@ -70,3 +71,9 @@ const char *imemo_kind(VALUE imemo);
70
71
  { if (RB_UNLIKELY(!rb_typeddata_is_kind_of(value, RTYPEDDATA_TYPE(rb_thread_current())))) raise_unexpected_type(value, ADD_QUOTES(value), "Thread", __FILE__, __LINE__, __func__); }
71
72
 
72
73
  bool is_raised_flag_set(VALUE thread);
74
+
75
+ // Can be nil if `rb_fiber_current()` or similar has not been called (gets allocated lazily)
76
+ // Only implemented for Ruby 3.1+
77
+ VALUE current_fiber_for(VALUE thread);
78
+
79
+ void self_test_current_fiber_for(void);
@@ -41,6 +41,12 @@ static VALUE _native_malloc_stats(DDTRACE_UNUSED VALUE _self);
41
41
  static VALUE _native_safe_object_info(DDTRACE_UNUSED VALUE _self, VALUE obj);
42
42
 
43
43
  void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
44
+ // The profiler still has a lot of limitations around being used in Ractors BUT for now we're choosing to take care of those
45
+ // on our side, rather than asking Ruby to block calling our APIs from Ractors.
46
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
47
+ rb_ext_ractor_safe(true);
48
+ #endif
49
+
44
50
  VALUE datadog_module = rb_define_module("Datadog");
45
51
  VALUE profiling_module = rb_define_module_under(datadog_module, "Profiling");
46
52
  VALUE native_extension_module = rb_define_module_under(profiling_module, "NativeExtension");
@@ -80,6 +86,7 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
80
86
 
81
87
  static VALUE native_working_p(DDTRACE_UNUSED VALUE _self) {
82
88
  self_test_clock_id();
89
+ self_test_current_fiber_for();
83
90
  self_test_mn_enabled();
84
91
 
85
92
  return Qtrue;
@@ -98,7 +98,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
98
98
  .optional_stdout_filename = {},
99
99
  };
100
100
 
101
- ddog_crasht_Result result =
101
+ ddog_VoidResult result =
102
102
  action == start_action ?
103
103
  ddog_crasht_init(config, receiver_config, metadata) :
104
104
  ddog_crasht_update_on_fork(config, receiver_config, metadata);
@@ -108,7 +108,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
108
108
  ddog_endpoint_drop(endpoint);
109
109
  // }} End of exception-free zone to prevent leaks
110
110
 
111
- if (result.tag == DDOG_CRASHT_RESULT_ERR) {
111
+ if (result.tag == DDOG_VOID_RESULT_ERR) {
112
112
  rb_raise(rb_eRuntimeError, "Failed to start/update the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
113
113
  }
114
114
 
@@ -116,9 +116,9 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
116
116
  }
117
117
 
118
118
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
119
- ddog_crasht_Result result = ddog_crasht_shutdown();
119
+ ddog_VoidResult result = ddog_crasht_shutdown();
120
120
 
121
- if (result.tag == DDOG_CRASHT_RESULT_ERR) {
121
+ if (result.tag == DDOG_VOID_RESULT_ERR) {
122
122
  rb_raise(rb_eRuntimeError, "Failed to stop the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
123
123
  }
124
124
 
@@ -8,7 +8,7 @@ module Datadog
8
8
  module LibdatadogExtconfHelpers
9
9
  # Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
10
10
  # may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
11
- LIBDATADOG_VERSION = '~> 14.3.1.1.0'
11
+ LIBDATADOG_VERSION = '~> 16.0.1.1.0'
12
12
 
13
13
  # Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
14
14
  # libdatadog are moved after the extension gets compiled.
@@ -12,14 +12,29 @@ module Datadog
12
12
  DEFAULT_OBFUSCATOR_KEY_REGEX = '(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt'
13
13
  DEFAULT_OBFUSCATOR_VALUE_REGEX = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=[^;]|"\s*:\s*"[^"]+")|bearer\s+[a-z0-9\._\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\w=-]+\.ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}[^\-]+[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*[a-z0-9\/\.+]{100,}'
14
14
  # rubocop:enable Layout/LineLength
15
+
16
+ DISABLED_AUTO_USER_INSTRUMENTATION_MODE = 'disabled'
17
+ ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE = 'anonymization'
18
+ IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE = 'identification'
19
+ AUTO_USER_INSTRUMENTATION_MODES = [
20
+ DISABLED_AUTO_USER_INSTRUMENTATION_MODE,
21
+ ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE,
22
+ IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
23
+ ].freeze
24
+ AUTO_USER_INSTRUMENTATION_MODES_ALIASES = {
25
+ 'ident' => IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE,
26
+ 'anon' => ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE,
27
+ }.freeze
28
+
29
+ # NOTE: These two constants are deprecated
30
+ SAFE_TRACK_USER_EVENTS_MODE = 'safe'
31
+ EXTENDED_TRACK_USER_EVENTS_MODE = 'extended'
15
32
  APPSEC_VALID_TRACK_USER_EVENTS_MODE = [
16
- 'safe',
17
- 'extended'
33
+ SAFE_TRACK_USER_EVENTS_MODE, EXTENDED_TRACK_USER_EVENTS_MODE
18
34
  ].freeze
19
- APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES = [
20
- '1',
21
- 'true'
22
- ].concat(APPSEC_VALID_TRACK_USER_EVENTS_MODE).freeze
35
+ APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES = ['1', 'true'].concat(
36
+ APPSEC_VALID_TRACK_USER_EVENTS_MODE
37
+ ).freeze
23
38
 
24
39
  def self.extended(base)
25
40
  base = base.singleton_class unless base.is_a?(Class)
@@ -149,6 +164,29 @@ module Datadog
149
164
  end
150
165
  end
151
166
 
167
+ settings :auto_user_instrumentation do
168
+ define_method(:enabled?) { get_option(:mode) != DISABLED_AUTO_USER_INSTRUMENTATION_MODE }
169
+
170
+ option :mode do |o|
171
+ o.type :string
172
+ o.env 'DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE'
173
+ o.default IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
174
+ o.setter do |value|
175
+ mode = AUTO_USER_INSTRUMENTATION_MODES_ALIASES.fetch(value, value)
176
+ next mode if AUTO_USER_INSTRUMENTATION_MODES.include?(mode)
177
+
178
+ Datadog.logger.warn(
179
+ 'The appsec.auto_user_instrumentation.mode value provided is not supported. ' \
180
+ "Supported values are: #{AUTO_USER_INSTRUMENTATION_MODES.join(' | ')}. " \
181
+ "Using default value: #{IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE}."
182
+ )
183
+
184
+ IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
185
+ end
186
+ end
187
+ end
188
+
189
+ # DEV-3.0: Remove `track_user_events.enabled` and `track_user_events.mode` options
152
190
  settings :track_user_events do
153
191
  option :enabled do |o|
154
192
  o.default true
@@ -161,24 +199,39 @@ module Datadog
161
199
  APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES.include?(env_value.strip.downcase)
162
200
  end
163
201
  end
202
+ o.after_set do
203
+ Core.log_deprecation(key: :appsec_track_user_events_enabled) do
204
+ 'The appsec.track_user_events.enabled setting has been deprecated for removal. ' \
205
+ 'Please remove it from your Datadog.configure block and use ' \
206
+ 'appsec.auto_user_instrumentation.mode instead.'
207
+ end
208
+ end
164
209
  end
165
210
 
166
211
  option :mode do |o|
167
212
  o.type :string
168
213
  o.env 'DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING'
169
- o.default 'safe'
214
+ o.default SAFE_TRACK_USER_EVENTS_MODE
170
215
  o.setter do |v|
171
216
  if APPSEC_VALID_TRACK_USER_EVENTS_MODE.include?(v)
172
217
  v
173
218
  elsif v == 'disabled'
174
- 'safe'
219
+ SAFE_TRACK_USER_EVENTS_MODE
175
220
  else
176
221
  Datadog.logger.warn(
177
222
  'The appsec.track_user_events.mode value provided is not supported.' \
178
- 'Supported values are: safe | extended.' \
179
- 'Using default value `safe`'
223
+ "Supported values are: #{APPSEC_VALID_TRACK_USER_EVENTS_MODE.join(' | ')}." \
224
+ "Using default value: #{SAFE_TRACK_USER_EVENTS_MODE}."
180
225
  )
181
- 'safe'
226
+
227
+ SAFE_TRACK_USER_EVENTS_MODE
228
+ end
229
+ end
230
+ o.after_set do
231
+ Core.log_deprecation(key: :appsec_track_user_events_mode) do
232
+ 'The appsec.track_user_events.mode setting has been deprecated for removal. ' \
233
+ 'Please remove it from your Datadog.configure block and use ' \
234
+ 'appsec.auto_user_instrumentation.mode instead.'
182
235
  end
183
236
  end
184
237
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../patcher'
4
3
  require_relative 'instrumentation'
5
4
 
6
5
  module Datadog
@@ -9,8 +8,6 @@ module Datadog
9
8
  module ActiveRecord
10
9
  # AppSec patcher module for ActiveRecord
11
10
  module Patcher
12
- include Datadog::AppSec::Contrib::Patcher
13
-
14
11
  module_function
15
12
 
16
13
  def patched?
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Devise
7
+ # A temporary configuration module to accomodate new RFC changes.
8
+ # NOTE: DEV-3 Remove module
9
+ module Configuration
10
+ MODES_CONVERSION_RULES = {
11
+ track_user_to_auto_instrumentation: {
12
+ AppSec::Configuration::Settings::SAFE_TRACK_USER_EVENTS_MODE =>
13
+ AppSec::Configuration::Settings::ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE,
14
+ AppSec::Configuration::Settings::EXTENDED_TRACK_USER_EVENTS_MODE =>
15
+ AppSec::Configuration::Settings::IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
16
+ }.freeze,
17
+ auto_instrumentation_to_track_user: {
18
+ AppSec::Configuration::Settings::ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE =>
19
+ AppSec::Configuration::Settings::SAFE_TRACK_USER_EVENTS_MODE,
20
+ AppSec::Configuration::Settings::IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE =>
21
+ AppSec::Configuration::Settings::EXTENDED_TRACK_USER_EVENTS_MODE
22
+ }.freeze
23
+ }.freeze
24
+
25
+ module_function
26
+
27
+ # NOTE: DEV-3 Replace method use with `auto_user_instrumentation.enabled?`
28
+ def auto_user_instrumentation_enabled?
29
+ appsec = Datadog.configuration.appsec
30
+ appsec.auto_user_instrumentation.mode
31
+
32
+ unless appsec.auto_user_instrumentation.options[:mode].default_precedence?
33
+ return appsec.auto_user_instrumentation.enabled?
34
+ end
35
+
36
+ appsec.track_user_events.enabled
37
+ end
38
+
39
+ # NOTE: DEV-3 Replace method use with `auto_user_instrumentation.mode`
40
+ def auto_user_instrumentation_mode
41
+ appsec = Datadog.configuration.appsec
42
+
43
+ # NOTE: Reading both to trigger precedence set
44
+ appsec.auto_user_instrumentation.mode
45
+ appsec.track_user_events.mode
46
+
47
+ if !appsec.auto_user_instrumentation.options[:mode].default_precedence? &&
48
+ appsec.track_user_events.options[:mode].default_precedence?
49
+ return appsec.auto_user_instrumentation.mode
50
+ end
51
+
52
+ if appsec.auto_user_instrumentation.options[:mode].default_precedence?
53
+ return MODES_CONVERSION_RULES[:track_user_to_auto_instrumentation].fetch(
54
+ appsec.track_user_events.mode, appsec.auto_user_instrumentation.mode
55
+ )
56
+ end
57
+
58
+ identification_mode = AppSec::Configuration::Settings::IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
59
+ if appsec.auto_user_instrumentation.mode == identification_mode ||
60
+ appsec.track_user_events.mode == AppSec::Configuration::Settings::EXTENDED_TRACK_USER_EVENTS_MODE
61
+ return identification_mode
62
+ end
63
+
64
+ AppSec::Configuration::Settings::ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE
65
+ end
66
+
67
+ # NOTE: Remove in next version of tracking
68
+ def track_user_events_mode
69
+ MODES_CONVERSION_RULES[:auto_instrumentation_to_track_user]
70
+ .fetch(auto_user_instrumentation_mode, Datadog.configuration.appsec.track_user_events.mode)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -8,9 +8,6 @@ module Datadog
8
8
  class Event
9
9
  UUID_REGEX = /^\h{8}-\h{4}-\h{4}-\h{4}-\h{12}$/.freeze
10
10
 
11
- SAFE_MODE = 'safe'
12
- EXTENDED_MODE = 'extended'
13
-
14
11
  attr_reader :user_id
15
12
 
16
13
  def initialize(resource, mode)
@@ -38,15 +35,15 @@ module Datadog
38
35
  @user_id = @resource.id
39
36
 
40
37
  case @mode
41
- when EXTENDED_MODE
38
+ when AppSec::Configuration::Settings::IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
42
39
  @email = @resource.email
43
40
  @username = @resource.username
44
- when SAFE_MODE
41
+ when AppSec::Configuration::Settings::ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE
45
42
  @user_id = nil unless @user_id && @user_id.to_s =~ UUID_REGEX
46
43
  else
47
44
  Datadog.logger.warn(
48
- "Invalid automated user evenst mode: `#{@mode}`. "\
49
- 'Supported modes are: `safe` and `extended`.'
45
+ "Invalid auto_user_instrumentation.mode: `#{@mode}`. " \
46
+ "Supported modes are: #{AppSec::Configuration::Settings::AUTO_USER_INSTRUMENTATION_MODES.join(' | ')}."
50
47
  )
51
48
  end
52
49
  end