datadog 2.0.0 → 2.2.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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -2
  3. data/README.md +1 -1
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +19 -1
  5. data/ext/datadog_profiling_native_extension/collectors_stack.c +41 -0
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +1 -1
  7. data/ext/datadog_profiling_native_extension/crashtracker.c +1 -1
  8. data/ext/datadog_profiling_native_extension/extconf.rb +6 -4
  9. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +47 -1
  10. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
  11. data/ext/datadog_profiling_native_extension/stack_recorder.c +13 -6
  12. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
  13. data/lib/datadog/appsec/configuration/settings.rb +5 -0
  14. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +0 -1
  15. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  16. data/lib/datadog/appsec/extensions.rb +1 -0
  17. data/lib/datadog/core/configuration/components.rb +6 -3
  18. data/lib/datadog/core/configuration/ext.rb +1 -0
  19. data/lib/datadog/core/configuration/option.rb +21 -14
  20. data/lib/datadog/core/configuration/options.rb +5 -1
  21. data/lib/datadog/core/configuration/settings.rb +68 -5
  22. data/lib/datadog/core/configuration.rb +3 -17
  23. data/lib/datadog/core/deprecations.rb +58 -0
  24. data/lib/datadog/core/environment/ext.rb +2 -0
  25. data/lib/datadog/core/environment/yjit.rb +5 -0
  26. data/lib/datadog/core/runtime/ext.rb +2 -0
  27. data/lib/datadog/core/runtime/metrics.rb +6 -0
  28. data/lib/datadog/core/telemetry/component.rb +107 -0
  29. data/lib/datadog/core/telemetry/event.rb +124 -31
  30. data/lib/datadog/core/telemetry/ext.rb +2 -0
  31. data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
  32. data/lib/datadog/core/telemetry/metric.rb +167 -0
  33. data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
  34. data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
  35. data/lib/datadog/core/telemetry/request.rb +1 -1
  36. data/lib/datadog/core/telemetry/worker.rb +173 -0
  37. data/lib/datadog/core/utils/only_once_successful.rb +76 -0
  38. data/lib/datadog/core.rb +2 -19
  39. data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
  40. data/lib/datadog/opentelemetry/sdk/span_processor.rb +5 -2
  41. data/lib/datadog/profiling/collectors/code_provenance.rb +18 -5
  42. data/lib/datadog/profiling/component.rb +18 -1
  43. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
  44. data/lib/datadog/profiling.rb +1 -0
  45. data/lib/datadog/tracing/configuration/ext.rb +7 -0
  46. data/lib/datadog/tracing/configuration/settings.rb +52 -3
  47. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  48. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
  49. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
  50. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
  51. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
  52. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
  53. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
  54. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
  55. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  56. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  57. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  58. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  59. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  60. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  61. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  62. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  63. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  64. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  65. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
  66. data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
  67. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
  68. data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
  69. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
  70. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
  71. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
  72. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
  73. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
  74. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
  75. data/lib/datadog/tracing/contrib/analytics.rb +5 -0
  76. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
  77. data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
  78. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
  79. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +25 -0
  80. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
  81. data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
  82. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
  83. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
  84. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
  85. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
  86. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
  87. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
  88. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
  89. data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
  90. data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
  91. data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
  92. data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
  93. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  94. data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
  95. data/lib/datadog/tracing/distributed/datadog.rb +2 -2
  96. data/lib/datadog/tracing/distributed/propagation.rb +39 -4
  97. data/lib/datadog/tracing/distributed/trace_context.rb +5 -3
  98. data/lib/datadog/tracing/metadata/ext.rb +1 -0
  99. data/lib/datadog/tracing/span_operation.rb +3 -2
  100. data/lib/datadog/tracing/trace_operation.rb +7 -3
  101. data/lib/datadog/tracing/trace_segment.rb +4 -1
  102. data/lib/datadog/tracing/tracer.rb +9 -2
  103. data/lib/datadog/tracing.rb +5 -1
  104. data/lib/datadog/version.rb +2 -2
  105. metadata +21 -8
  106. data/lib/datadog/core/telemetry/client.rb +0 -95
  107. data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5008d4cb7f37cf4c4e1ed7956198b1fba9837c52f379b5d892898506ce4b2640
4
- data.tar.gz: 684c2b438ef7230e7f30ebd69b43041b2eea81413bbe2d4aedfe8140af01e955
3
+ metadata.gz: 895fe8f9fdd8391d5c6c86e8d39d0a8e241c85bbce42b35c9744e1f94095853f
4
+ data.tar.gz: d5a6e88ec35816de59a5d080f66896a4c85656216d2853b46bb1268dfa64df35
5
5
  SHA512:
6
- metadata.gz: 1582a1f36cdf990613dc46e6febadb29f45275a363d32f4213237b5c8dc5be145218226639a590cb16e2fe7881a91b05dfb714c018e85fbb99f407376f68d71c
7
- data.tar.gz: e08d4d1645d47bd4fb8e4c6d03f088571bca24df622bc8e9da0d5ca696b33602fe28dc855e34da9f1783c62e4797916e1a0736f5d8fa29850d71d57a5508ec4e
6
+ metadata.gz: fef3c78c7835c47507a1f09d87c2ee84ddcc97303f9b9d7c6b4d601381ac62a47133f3450ddbc888cf54c56353ef4417ff337009a1e60d2ae239fb19093d721b
7
+ data.tar.gz: 061154162ab97a6e1cdc87f53c18d98fd0eea75b6cb7e71fd1e4e5c4a536ff7722c4e1202258760113ce5a7f0ce3838622e700858103fa97dddc33d0322275cc
data/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.2.0] - 2024-07-11
6
+
7
+ ### Added
8
+
9
+ * Tracing: Add `Rails` Runner instrumentation ([#2509][])
10
+ * Tracing: Introduce a new, reworked `GraphQL` tracer to comply with span attributes specification ([#3672][])
11
+ * Tracing: Enhance `ActiveSupport::Cache` instrumentation with `ActiveSupport::Notifications` subscription ([#3772][])
12
+ * Profiling: Track unscaled allocation counts in allocation profiler ([#3770][])
13
+
14
+ ### Changed
15
+
16
+ * Core: Send Telemetry events in batches ([#3749][])
17
+ * Tracing: Populate spans from `ActiveSupport::Notifications` as early as possible ([#3725][])
18
+ * Profiling: Upgrade to `libdatadog` 10 ([#3753][])
19
+ * Profiling: Optimize `CodeProvenance#record_loaded_files` to avoid allocations ([#3757][])
20
+
21
+ ### Fixed
22
+
23
+ * Core: Fix Telemetry events blocking main thread ([#3718][])
24
+ * Core: Fix deadlock from Telemetry threads ([#3743][])
25
+ * Tracing: Fix empty log correlation when tracing is disabled ([#3731][])
26
+ * Tracing: Fix HTTP propagation when missing parent span id ([#3730][])
27
+ * Tracing: Ensure `_dd.p.tid` tag with fixed size ([#3729][])
28
+ * OTel: Fix ids encoding/decoding for propagation ([#3709][])
29
+ * Profiling: Workaround Ruby `Dir` returning incorrect results ([#3720][])
30
+ * Profiling: Fix `Phusion Passenger` detection when missing from `Gemfile`/`gems.rb` ([#3750][])
31
+ * Profiling: Fix `rpath` for linking to libdatadog when loading extension ([#3706][])
32
+ * Profiling: Fix incorrect code provenance due to broken JSON monkey patch ([#3695][])
33
+ * Profiling: Fix aggregation of actionview template classes ([#3759][], [#3774][])
34
+
35
+ ## [2.1.0] - 2024-06-10
36
+
37
+ ### Added
38
+
39
+ * Tracing: Configuration by OpenTelemetry environment variables ([#3657][])
40
+
41
+ ### Fixed
42
+
43
+ * Tracing: Improved compatibility with W3C Trace Context propagation ([#3631][])
44
+
5
45
  ## [2.0.0] - 2024-06-06
6
46
 
7
47
  ### Added
@@ -2894,7 +2934,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
2894
2934
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
2895
2935
 
2896
2936
 
2897
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0...master
2937
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.2.0...master
2938
+ [2.2.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.1.0...v2.2.0
2939
+ [2.1.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0...v2.1.0
2898
2940
  [2.0.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0.rc1...v2.0.0
2899
2941
  [2.0.0.rc1]: https://github.com/DataDog/dd-trace-rb/compare/v2.0.0.beta2...v2.0.0.rc1
2900
2942
  [1.23.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.22.0...v1.23.0
@@ -3890,6 +3932,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3890
3932
  [#2497]: https://github.com/DataDog/dd-trace-rb/issues/2497
3891
3933
  [#2501]: https://github.com/DataDog/dd-trace-rb/issues/2501
3892
3934
  [#2504]: https://github.com/DataDog/dd-trace-rb/issues/2504
3935
+ [#2509]: https://github.com/DataDog/dd-trace-rb/issues/2509
3893
3936
  [#2512]: https://github.com/DataDog/dd-trace-rb/issues/2512
3894
3937
  [#2513]: https://github.com/DataDog/dd-trace-rb/issues/2513
3895
3938
  [#2522]: https://github.com/DataDog/dd-trace-rb/issues/2522
@@ -4267,9 +4310,30 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4267
4310
  [#3624]: https://github.com/DataDog/dd-trace-rb/issues/3624
4268
4311
  [#3627]: https://github.com/DataDog/dd-trace-rb/issues/3627
4269
4312
  [#3630]: https://github.com/DataDog/dd-trace-rb/issues/3630
4313
+ [#3631]: https://github.com/DataDog/dd-trace-rb/issues/3631
4270
4314
  [#3645]: https://github.com/DataDog/dd-trace-rb/issues/3645
4271
4315
  [#3651]: https://github.com/DataDog/dd-trace-rb/issues/3651
4316
+ [#3657]: https://github.com/DataDog/dd-trace-rb/issues/3657
4272
4317
  [#3664]: https://github.com/DataDog/dd-trace-rb/issues/3664
4318
+ [#3672]: https://github.com/DataDog/dd-trace-rb/issues/3672
4319
+ [#3695]: https://github.com/DataDog/dd-trace-rb/issues/3695
4320
+ [#3706]: https://github.com/DataDog/dd-trace-rb/issues/3706
4321
+ [#3709]: https://github.com/DataDog/dd-trace-rb/issues/3709
4322
+ [#3718]: https://github.com/DataDog/dd-trace-rb/issues/3718
4323
+ [#3720]: https://github.com/DataDog/dd-trace-rb/issues/3720
4324
+ [#3725]: https://github.com/DataDog/dd-trace-rb/issues/3725
4325
+ [#3729]: https://github.com/DataDog/dd-trace-rb/issues/3729
4326
+ [#3730]: https://github.com/DataDog/dd-trace-rb/issues/3730
4327
+ [#3731]: https://github.com/DataDog/dd-trace-rb/issues/3731
4328
+ [#3743]: https://github.com/DataDog/dd-trace-rb/issues/3743
4329
+ [#3749]: https://github.com/DataDog/dd-trace-rb/issues/3749
4330
+ [#3750]: https://github.com/DataDog/dd-trace-rb/issues/3750
4331
+ [#3753]: https://github.com/DataDog/dd-trace-rb/issues/3753
4332
+ [#3757]: https://github.com/DataDog/dd-trace-rb/issues/3757
4333
+ [#3759]: https://github.com/DataDog/dd-trace-rb/issues/3759
4334
+ [#3770]: https://github.com/DataDog/dd-trace-rb/issues/3770
4335
+ [#3772]: https://github.com/DataDog/dd-trace-rb/issues/3772
4336
+ [#3774]: https://github.com/DataDog/dd-trace-rb/issues/3774
4273
4337
  [@AdrianLC]: https://github.com/AdrianLC
4274
4338
  [@Azure7111]: https://github.com/Azure7111
4275
4339
  [@BabyGroot]: https://github.com/BabyGroot
@@ -4421,4 +4485,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4421
4485
  [@y-yagi]: https://github.com/y-yagi
4422
4486
  [@yujideveloper]: https://github.com/yujideveloper
4423
4487
  [@yukimurasawa]: https://github.com/yukimurasawa
4424
- [@zachmccormick]: https://github.com/zachmccormick
4488
+ [@zachmccormick]: https://github.com/zachmccormick
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ## Getting started
10
10
 
11
- **If you're upgrading from a 0.x version, check out our [upgrade guide](https://github.com/DataDog/dd-trace-rb/blob/master/docs/UpgradeGuide.md#from-0x-to-10).**
11
+ **If you're upgrading from a 1.x version, check out the [upgrade guide](https://github.com/DataDog/dd-trace-rb/blob/release/docs/UpgradeGuide2.md).**
12
12
 
13
13
  For a product overview, installation, and configuration check out our [documentation][public docs].
14
14
 
@@ -222,6 +222,8 @@ static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
222
222
  static VALUE rescued_sample_allocation(VALUE tracepoint_data);
223
223
  static void delayed_error(struct cpu_and_wall_time_worker_state *state, const char *error);
224
224
  static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
225
+ static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
226
+ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
225
227
 
226
228
  // Note on sampler global state safety:
227
229
  //
@@ -285,7 +287,9 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
285
287
  rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_allocation_count", _native_allocation_count, 0);
286
288
  rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_is_running?", _native_is_running, 1);
287
289
  rb_define_singleton_method(testing_module, "_native_current_sigprof_signal_handler", _native_current_sigprof_signal_handler, 0);
288
- // TODO: Remove `_native_is_running` from `testing_module` once `prof-correctness` has been updated to not need it
290
+ rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_hold_signals", _native_hold_signals, 0);
291
+ rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_resume_signals", _native_resume_signals, 0);
292
+ // TODO: Remove `_native_is_running` from `testing_module` (should be in class) once `prof-correctness` has been updated to not need it
289
293
  rb_define_singleton_method(testing_module, "_native_is_running?", _native_is_running, 1);
290
294
  rb_define_singleton_method(testing_module, "_native_install_testing_signal_handler", _native_install_testing_signal_handler, 0);
291
295
  rb_define_singleton_method(testing_module, "_native_remove_testing_signal_handler", _native_remove_testing_signal_handler, 0);
@@ -1159,3 +1163,17 @@ static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VA
1159
1163
 
1160
1164
  return Qnil;
1161
1165
  }
1166
+
1167
+ // Masks SIGPROF interruptions for the current thread. Please don't use this -- you may end up with incomplete
1168
+ // profiling data.
1169
+ static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self) {
1170
+ block_sigprof_signal_handler_from_running_in_current_thread();
1171
+ return Qtrue;
1172
+ }
1173
+
1174
+ // Unmasks SIGPROF interruptions for the current thread. If there's a pending sample, it'll be triggered inside this
1175
+ // method.
1176
+ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1177
+ unblock_sigprof_signal_handler_from_running_in_current_thread();
1178
+ return Qtrue;
1179
+ }
@@ -34,6 +34,7 @@ static VALUE _native_sample(
34
34
  );
35
35
  static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size);
36
36
  static void record_placeholder_stack_in_native_code(sampling_buffer* buffer, VALUE recorder_instance, sample_values values, sample_labels labels);
37
+ static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_CharSlice *filename_slice);
37
38
 
38
39
  void collectors_stack_init(VALUE profiling_module) {
39
40
  VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
@@ -69,6 +70,7 @@ static VALUE _native_sample(
69
70
  .cpu_or_wall_samples = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("cpu-samples"), zero)),
70
71
  .wall_time_ns = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("wall-time"), zero)),
71
72
  .alloc_samples = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("alloc-samples"), zero)),
73
+ .alloc_samples_unscaled = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("alloc-samples-unscaled"), zero)),
72
74
  .timeline_wall_time_ns = NUM2UINT(rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("timeline"), zero)),
73
75
  };
74
76
 
@@ -199,6 +201,8 @@ void sample_thread(
199
201
  ddog_CharSlice name_slice = char_slice_from_ruby_string(name);
200
202
  ddog_CharSlice filename_slice = char_slice_from_ruby_string(filename);
201
203
 
204
+ maybe_trim_template_random_ids(&name_slice, &filename_slice);
205
+
202
206
  bool top_of_the_stack = i == 0;
203
207
 
204
208
  // When there's only wall-time in a sample, this means that the thread was not active in the sampled period.
@@ -268,6 +272,43 @@ void sample_thread(
268
272
  );
269
273
  }
270
274
 
275
+ // Rails's ActionView likes to dynamically generate method names with suffixed hashes/ids, resulting in methods with
276
+ // names such as:
277
+ // * "_app_views_layouts_explore_html_haml__2304485752546535910_211320" (__number_number suffix -- two underscores)
278
+ // * "_app_views_articles_index_html_erb___2022809201779434309_12900" (___number_number suffix -- three underscores)
279
+ // This makes these stacks not aggregate well, as well as being not-very-useful data.
280
+ // (Reference:
281
+ // https://github.com/rails/rails/blob/4fa56814f18fd3da49c83931fa773caa727d8096/actionview/lib/action_view/template.rb#L389
282
+ // The two vs three underscores happen when @identifier.hash is negative in that method: the "-" gets replaced with
283
+ // the extra "_".)
284
+ //
285
+ // This method trims these suffixes, so that we keep less data + the names correctly aggregate together.
286
+ static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_CharSlice *filename_slice) {
287
+ // Check filename doesn't end with ".rb"; templates are usually along the lines of .html.erb/.html.haml/...
288
+ if (filename_slice->len < 3 || memcmp(filename_slice->ptr + filename_slice->len - 3, ".rb", 3) == 0) return;
289
+
290
+ int pos = name_slice->len - 1;
291
+
292
+ // Let's match on something__number_number:
293
+ // Find start of id suffix from the end...
294
+ if (name_slice->ptr[pos] < '0' || name_slice->ptr[pos] > '9') return;
295
+
296
+ // ...now match a bunch of numbers and interspersed underscores
297
+ for (int underscores = 0; pos >= 0 && underscores < 2; pos--) {
298
+ if (name_slice->ptr[pos] == '_') underscores++;
299
+ else if (name_slice->ptr[pos] < '0' || name_slice->ptr[pos] > '9') return;
300
+ }
301
+
302
+ // Make sure there's something left before the underscores (hence the <= instead of <) + match the last underscore
303
+ if (pos <= 0 || name_slice->ptr[pos] != '_') return;
304
+
305
+ // Does it have the optional third underscore? If so, remove it as well
306
+ if (pos > 1 && name_slice->ptr[pos-1] == '_') pos--;
307
+
308
+ // If we got here, we matched on our pattern. Let's slice the length of the string to exclude it.
309
+ name_slice->len = pos;
310
+ }
311
+
271
312
  static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size) {
272
313
  ptrdiff_t frames_omitted = stack_depth_for(thread) - buffer->max_frames;
273
314
 
@@ -1290,7 +1290,7 @@ void thread_context_collector_sample_allocation(VALUE self_instance, unsigned in
1290
1290
  /* thread: */ current_thread,
1291
1291
  /* stack_from_thread: */ current_thread,
1292
1292
  get_or_create_context_for(current_thread, state),
1293
- (sample_values) {.alloc_samples = sample_weight},
1293
+ (sample_values) {.alloc_samples = sample_weight, .alloc_samples_unscaled = 1},
1294
1294
  INVALID_TIME, // For now we're not collecting timestamps for allocation events, as per profiling team internal discussions
1295
1295
  &ruby_vm_type,
1296
1296
  optional_class_name
@@ -57,7 +57,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
57
57
  // "Process.kill('SEGV', Process.pid)" gets run.
58
58
  .create_alt_stack = false,
59
59
  .endpoint = endpoint,
60
- .resolve_frames = DDOG_PROF_STACKTRACE_COLLECTION_ENABLED,
60
+ .resolve_frames = DDOG_PROF_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER,
61
61
  .timeout_secs = FIX2INT(upload_timeout_seconds),
62
62
  };
63
63
 
@@ -211,12 +211,14 @@ unless have_type('atomic_int', ['stdatomic.h'])
211
211
  skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
212
212
  end
213
213
 
214
- # See comments on the helper method being used for why we need to additionally set this.
214
+ # See comments on the helper methods being used for why we need to additionally set this.
215
215
  # The extremely excessive escaping around ORIGIN below seems to be correct and was determined after a lot of
216
216
  # experimentation. We need to get these special characters across a lot of tools untouched...
217
- $LDFLAGS += \
218
- ' -Wl,-rpath,$$$\\\\{ORIGIN\\}/' \
219
- "#{Datadog::Profiling::NativeExtensionHelpers.libdatadog_folder_relative_to_native_lib_folder}"
217
+ extra_relative_rpaths = [
218
+ Datadog::Profiling::NativeExtensionHelpers.libdatadog_folder_relative_to_native_lib_folder,
219
+ *Datadog::Profiling::NativeExtensionHelpers.libdatadog_folder_relative_to_ruby_extensions_folders,
220
+ ]
221
+ extra_relative_rpaths.each { |folder| $LDFLAGS += " -Wl,-rpath,$$$\\\\{ORIGIN\\}/#{folder.to_str}" }
220
222
  Logging.message("[datadog] After pkg-config $LDFLAGS were set to: #{$LDFLAGS.inspect}\n")
221
223
 
222
224
  # Tag the native extension library with the Ruby version and Ruby platform.
@@ -15,7 +15,7 @@ module Datadog
15
15
  # The MJIT header was introduced on 2.6 and removed on 3.3; for other Rubies we rely on debase-ruby_core_source
16
16
  CAN_USE_MJIT_HEADER = RUBY_VERSION.start_with?('2.6', '2.7', '3.0.', '3.1.', '3.2.')
17
17
 
18
- LIBDATADOG_VERSION = '~> 9.0.0.1.0'
18
+ LIBDATADOG_VERSION = '~> 10.0.0.1.0'
19
19
 
20
20
  def self.fail_install_if_missing_extension?
21
21
  ENV[ENV_FAIL_INSTALL_IF_MISSING_EXTENSION].to_s.strip.downcase == 'true'
@@ -67,6 +67,52 @@ module Datadog
67
67
  Pathname.new(libdatadog_lib_folder).relative_path_from(Pathname.new(profiling_native_lib_folder)).to_s
68
68
  end
69
69
 
70
+ # In https://github.com/DataDog/dd-trace-rb/pull/3582 we got a report of a customer for which the native extension
71
+ # only got installed into the extensions folder.
72
+ #
73
+ # But then this fix was not enough to fully get them moving because then they started to see the issue from
74
+ # https://github.com/DataDog/dd-trace-rb/issues/2067 / https://github.com/DataDog/dd-trace-rb/pull/2125 :
75
+ #
76
+ # > Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling
77
+ # > native extension due to 'RuntimeError Failure to load datadog_profiling_native_extension.3.2.2_x86_64-linux
78
+ # > due to libdatadog_profiling.so: cannot open shared object file: No such file or directory
79
+ #
80
+ # The problem is that when loading the native extension from the extensions directory, the relative rpath we add
81
+ # with the #libdatadog_folder_relative_to_native_lib_folder helper above is not correct, we need to add a relative
82
+ # rpath to the extensions directory.
83
+ #
84
+ # So how do we find the full path where the native extension is placed?
85
+ # * From https://github.com/ruby/ruby/blob/83f02d42e0a3c39661dc99c049ab9a70ff227d5b/lib/bundler/runtime.rb#L166
86
+ # `extension_dirs = Dir["#{Gem.dir}/extensions/*/*/*"] + Dir["#{Gem.dir}/bundler/gems/extensions/*/*/*"]`
87
+ # we get that's in one of two fixed subdirectories of `Gem.dir`
88
+ # * From https://github.com/ruby/ruby/blob/83f02d42e0a3c39661dc99c049ab9a70ff227d5b/lib/rubygems/basic_specification.rb#L111-L115
89
+ # we get the structure of the subdirectory (platform/extension_api_version/gem_and_version)
90
+ #
91
+ # Thus, `Gem.dir` of `/var/app/current/vendor/bundle/ruby/3.2.0` becomes (for instance)
92
+ # `/var/app/current/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/datadog-2.0.0/` or
93
+ # `/var/app/current/vendor/bundle/ruby/3.2.0/bundler/gems/extensions/x86_64-linux/3.2.0/datadog-2.0.0/`
94
+ #
95
+ # We then compute the relative path between these folders and the libdatadog folder, and use that as a relative path.
96
+ def self.libdatadog_folder_relative_to_ruby_extensions_folders(
97
+ gem_dir: Gem.dir,
98
+ libdatadog_pkgconfig_folder: Libdatadog.pkgconfig_folder
99
+ )
100
+ return unless libdatadog_pkgconfig_folder
101
+
102
+ # For the purposes of calculating a folder relative to the other, we don't actually NEED to fill in the
103
+ # platform, extension_api_version and gem version. We're basically just after how many folders it is deep from
104
+ # the Gem.dir.
105
+ expected_ruby_extensions_folders = [
106
+ "#{gem_dir}/extensions/platform/extension_api_version/datadog_version/",
107
+ "#{gem_dir}/bundler/gems/extensions/platform/extension_api_version/datadog_version/",
108
+ ]
109
+ libdatadog_lib_folder = "#{libdatadog_pkgconfig_folder}/../"
110
+
111
+ expected_ruby_extensions_folders.map do |folder|
112
+ Pathname.new(libdatadog_lib_folder).relative_path_from(Pathname.new(folder)).to_s
113
+ end
114
+ end
115
+
70
116
  # Used to check if profiler is supported, including user-visible clear messages explaining why their
71
117
  # system may not be supported.
72
118
  module Supported
@@ -91,7 +91,7 @@ void remove_sigprof_signal_handler(void) {
91
91
  if (sigaction(SIGPROF, &signal_handler_config, NULL) != 0) rb_sys_fail("Failure while removing the signal handler");
92
92
  }
93
93
 
94
- static void toggle_sigprof_signal_handler_for_current_thread(int action) {
94
+ static inline void toggle_sigprof_signal_handler_for_current_thread(int action) {
95
95
  sigset_t signals_to_toggle;
96
96
  sigemptyset(&signals_to_toggle);
97
97
  sigaddset(&signals_to_toggle, SIGPROF);
@@ -151,21 +151,23 @@ static VALUE error_symbol = Qnil; // :error in Ruby
151
151
  #define WALL_TIME_VALUE_ID 2
152
152
  #define ALLOC_SAMPLES_VALUE {.type_ = VALUE_STRING("alloc-samples"), .unit = VALUE_STRING("count")}
153
153
  #define ALLOC_SAMPLES_VALUE_ID 3
154
+ #define ALLOC_SAMPLES_UNSCALED_VALUE {.type_ = VALUE_STRING("alloc-samples-unscaled"), .unit = VALUE_STRING("count")}
155
+ #define ALLOC_SAMPLES_UNSCALED_VALUE_ID 4
154
156
  #define HEAP_SAMPLES_VALUE {.type_ = VALUE_STRING("heap-live-samples"), .unit = VALUE_STRING("count")}
155
- #define HEAP_SAMPLES_VALUE_ID 4
157
+ #define HEAP_SAMPLES_VALUE_ID 5
156
158
  #define HEAP_SIZE_VALUE {.type_ = VALUE_STRING("heap-live-size"), .unit = VALUE_STRING("bytes")}
157
- #define HEAP_SIZE_VALUE_ID 5
159
+ #define HEAP_SIZE_VALUE_ID 6
158
160
  #define TIMELINE_VALUE {.type_ = VALUE_STRING("timeline"), .unit = VALUE_STRING("nanoseconds")}
159
- #define TIMELINE_VALUE_ID 6
161
+ #define TIMELINE_VALUE_ID 7
160
162
 
161
163
  static const ddog_prof_ValueType all_value_types[] =
162
- {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE, ALLOC_SAMPLES_VALUE, HEAP_SAMPLES_VALUE, HEAP_SIZE_VALUE, TIMELINE_VALUE};
164
+ {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE, ALLOC_SAMPLES_VALUE, ALLOC_SAMPLES_UNSCALED_VALUE, HEAP_SAMPLES_VALUE, HEAP_SIZE_VALUE, TIMELINE_VALUE};
163
165
 
164
166
  // This array MUST be kept in sync with all_value_types above and is intended to act as a "hashmap" between VALUE_ID and the position it
165
167
  // occupies on the all_value_types array.
166
168
  // E.g. all_value_types_positions[CPU_TIME_VALUE_ID] => 0, means that CPU_TIME_VALUE was declared at position 0 of all_value_types.
167
169
  static const uint8_t all_value_types_positions[] =
168
- {CPU_TIME_VALUE_ID, CPU_SAMPLES_VALUE_ID, WALL_TIME_VALUE_ID, ALLOC_SAMPLES_VALUE_ID, HEAP_SAMPLES_VALUE_ID, HEAP_SIZE_VALUE_ID, TIMELINE_VALUE_ID};
170
+ {CPU_TIME_VALUE_ID, CPU_SAMPLES_VALUE_ID, WALL_TIME_VALUE_ID, ALLOC_SAMPLES_VALUE_ID, ALLOC_SAMPLES_UNSCALED_VALUE_ID, HEAP_SAMPLES_VALUE_ID, HEAP_SIZE_VALUE_ID, TIMELINE_VALUE_ID};
169
171
 
170
172
  #define ALL_VALUE_TYPES_COUNT (sizeof(all_value_types) / sizeof(ddog_prof_ValueType))
171
173
 
@@ -429,7 +431,7 @@ static VALUE _native_initialize(
429
431
 
430
432
  uint8_t requested_values_count = ALL_VALUE_TYPES_COUNT -
431
433
  (cpu_time_enabled == Qtrue ? 0 : 1) -
432
- (alloc_samples_enabled == Qtrue? 0 : 1) -
434
+ (alloc_samples_enabled == Qtrue? 0 : 2) -
433
435
  (heap_samples_enabled == Qtrue ? 0 : 1) -
434
436
  (heap_size_enabled == Qtrue ? 0 : 1) -
435
437
  (timeline_enabled == Qtrue ? 0 : 1);
@@ -464,8 +466,12 @@ static VALUE _native_initialize(
464
466
  if (alloc_samples_enabled == Qtrue) {
465
467
  enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) ALLOC_SAMPLES_VALUE;
466
468
  state->position_for[ALLOC_SAMPLES_VALUE_ID] = next_enabled_pos++;
469
+
470
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) ALLOC_SAMPLES_UNSCALED_VALUE;
471
+ state->position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID] = next_enabled_pos++;
467
472
  } else {
468
473
  state->position_for[ALLOC_SAMPLES_VALUE_ID] = next_disabled_pos++;
474
+ state->position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID] = next_disabled_pos++;
469
475
  }
470
476
 
471
477
  if (heap_samples_enabled == Qtrue) {
@@ -603,6 +609,7 @@ void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations,
603
609
  metric_values[position_for[CPU_SAMPLES_VALUE_ID]] = values.cpu_or_wall_samples;
604
610
  metric_values[position_for[WALL_TIME_VALUE_ID]] = values.wall_time_ns;
605
611
  metric_values[position_for[ALLOC_SAMPLES_VALUE_ID]] = values.alloc_samples;
612
+ metric_values[position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID]] = values.alloc_samples_unscaled;
606
613
  metric_values[position_for[TIMELINE_VALUE_ID]] = values.timeline_wall_time_ns;
607
614
 
608
615
  if (values.alloc_samples != 0) {
@@ -8,6 +8,7 @@ typedef struct {
8
8
  int64_t wall_time_ns;
9
9
  uint32_t cpu_or_wall_samples;
10
10
  uint32_t alloc_samples;
11
+ uint32_t alloc_samples_unscaled;
11
12
  int64_t timeline_wall_time_ns;
12
13
  } sample_values;
13
14
 
@@ -192,6 +192,11 @@ module Datadog
192
192
  end
193
193
  end
194
194
  end
195
+
196
+ option :sca_enabled do |o|
197
+ o.type :bool, nilable: true
198
+ o.env 'DD_APPSEC_SCA_ENABLED'
199
+ end
195
200
  end
196
201
  end
197
202
  end
@@ -15,7 +15,6 @@ module Datadog
15
15
  module AppSec
16
16
  module Contrib
17
17
  module Rack
18
- # Create an array of lowercased headers
19
18
  WAF_VENDOR_HEADERS_TAGS = %w[
20
19
  X-Amzn-Trace-Id
21
20
  Cloudfront-Viewer-Ja3-Fingerprint
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../../tracing/contrib/rack/middlewares'
3
+ require_relative '../../../tracing/contrib'
4
4
 
5
5
  require_relative '../patcher'
6
6
  require_relative '../../response'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'configuration'
4
+ require_relative '../core/configuration'
4
5
 
5
6
  module Datadog
6
7
  module AppSec
@@ -6,7 +6,7 @@ require_relative '../diagnostics/environment_logger'
6
6
  require_relative '../diagnostics/health'
7
7
  require_relative '../logger'
8
8
  require_relative '../runtime/metrics'
9
- require_relative '../telemetry/client'
9
+ require_relative '../telemetry/component'
10
10
  require_relative '../workers/runtime_metrics'
11
11
 
12
12
  require_relative '../remote/component'
@@ -62,9 +62,11 @@ module Datadog
62
62
  logger.debug { "Telemetry disabled. Agent network adapter not supported: #{agent_settings.adapter}" }
63
63
  end
64
64
 
65
- Telemetry::Client.new(
65
+ Telemetry::Component.new(
66
66
  enabled: enabled,
67
+ metrics_enabled: enabled && settings.telemetry.metrics_enabled,
67
68
  heartbeat_interval_seconds: settings.telemetry.heartbeat_interval_seconds,
69
+ metrics_aggregation_interval_seconds: settings.telemetry.metrics_aggregation_interval_seconds,
68
70
  dependency_collection: settings.telemetry.dependency_collection
69
71
  )
70
72
  end
@@ -169,8 +171,9 @@ module Datadog
169
171
  unused_statsd = (old_statsd - (old_statsd & new_statsd))
170
172
  unused_statsd.each(&:close)
171
173
 
172
- telemetry.stop!
174
+ # enqueue closing event before stopping telemetry so it will be send out on shutdown
173
175
  telemetry.emit_closing! unless replacement
176
+ telemetry.stop!
174
177
  end
175
178
  end
176
179
  end
@@ -9,6 +9,7 @@ module Datadog
9
9
  # @public_api
10
10
  module Diagnostics
11
11
  ENV_DEBUG_ENABLED = 'DD_TRACE_DEBUG'
12
+ ENV_OTEL_LOG_LEVEL = 'OTEL_LOG_LEVEL'
12
13
  ENV_HEALTH_METRICS_ENABLED = 'DD_HEALTH_METRICS_ENABLED'
13
14
  ENV_STARTUP_LOGS_ENABLED = 'DD_TRACE_STARTUP_LOGS'
14
15
  end
@@ -14,7 +14,7 @@ module Datadog
14
14
  # @!attribute [r] precedence_set
15
15
  # When this option was last set, what was the value precedence used?
16
16
  # @return [Precedence::Value]
17
- attr_reader :definition, :precedence_set
17
+ attr_reader :definition, :precedence_set, :resolved_env
18
18
 
19
19
  # Option setting precedence.
20
20
  module Precedence
@@ -50,6 +50,7 @@ module Datadog
50
50
  @context = context
51
51
  @value = nil
52
52
  @is_set = false
53
+ @resolved_env = nil
53
54
 
54
55
  # One value is stored per precedence, to allow unsetting a higher
55
56
  # precedence value and falling back to a lower precedence one.
@@ -65,7 +66,7 @@ module Datadog
65
66
  #
66
67
  # @param value [Object] the new value to be associated with this option
67
68
  # @param precedence [Precedence] from what precedence order this new value comes from
68
- def set(value, precedence: Precedence::PROGRAMMATIC)
69
+ def set(value, precedence: Precedence::PROGRAMMATIC, resolved_env: nil)
69
70
  # Is there a higher precedence value set?
70
71
  if @precedence_set > precedence
71
72
  # This should be uncommon, as higher precedence values tend to
@@ -84,7 +85,7 @@ module Datadog
84
85
  return @value
85
86
  end
86
87
 
87
- internal_set(value, precedence)
88
+ internal_set(value, precedence, resolved_env)
88
89
  end
89
90
 
90
91
  def unset(precedence)
@@ -102,7 +103,7 @@ module Datadog
102
103
  # Look for value that is set.
103
104
  # The hash `@value_per_precedence` has a custom default value of `UNSET`.
104
105
  if (value = @value_per_precedence[p]) != UNSET
105
- internal_set(value, p)
106
+ internal_set(value, p, nil)
106
107
  return nil
107
108
  end
108
109
  end
@@ -260,11 +261,12 @@ module Datadog
260
261
  end
261
262
 
262
263
  # Directly manipulates the current value and currently set precedence.
263
- def internal_set(value, precedence)
264
+ def internal_set(value, precedence, resolved_env)
264
265
  old_value = @value
265
266
  (@value = context_exec(validate_type(value), old_value, &definition.setter)).tap do |v|
266
267
  @is_set = true
267
268
  @precedence_set = precedence
269
+ @resolved_env = resolved_env
268
270
  # Store original value to ensure we can always safely call `#internal_set`
269
271
  # when restoring a value from `@value_per_precedence`, and we are only running `definition.setter`
270
272
  # on the original value, not on a valud that has already been processed by `definition.setter`.
@@ -284,16 +286,21 @@ module Datadog
284
286
  def set_value_from_env_or_default
285
287
  value = nil
286
288
  precedence = nil
287
- effective_env = nil
289
+ resolved_env = nil
288
290
 
289
- if definition.env && ENV[definition.env]
290
- effective_env = definition.env
291
- value = coerce_env_variable(ENV[definition.env])
292
- precedence = Precedence::PROGRAMMATIC
291
+ if definition.env
292
+ Array(definition.env).each do |env|
293
+ next if ENV[env].nil?
294
+
295
+ resolved_env = env
296
+ value = coerce_env_variable(ENV[env])
297
+ precedence = Precedence::PROGRAMMATIC
298
+ break
299
+ end
293
300
  end
294
301
 
295
302
  if value.nil? && definition.deprecated_env && ENV[definition.deprecated_env]
296
- effective_env = definition.deprecated_env
303
+ resolved_env = definition.deprecated_env
297
304
  value = coerce_env_variable(ENV[definition.deprecated_env])
298
305
  precedence = Precedence::PROGRAMMATIC
299
306
 
@@ -304,11 +311,11 @@ module Datadog
304
311
 
305
312
  option_value = value.nil? ? default_value : value
306
313
 
307
- set(option_value, precedence: precedence || Precedence::DEFAULT)
314
+ set(option_value, precedence: precedence || Precedence::DEFAULT, resolved_env: resolved_env)
308
315
  rescue ArgumentError
309
316
  raise ArgumentError,
310
- "Expected environment variable #{effective_env} to be a #{@definition.type}, " \
311
- "but '#{ENV[effective_env]}' was provided"
317
+ "Expected environment variable #{resolved_env} to be a #{@definition.type}, " \
318
+ "but '#{ENV[resolved_env]}' was provided"
312
319
  end
313
320
 
314
321
  # Anchor object that represents a value that is not set.
@@ -68,7 +68,7 @@ module Datadog
68
68
  end
69
69
 
70
70
  def set_option(name, value, precedence: Configuration::Option::Precedence::PROGRAMMATIC)
71
- resolve_option(name).set(value, precedence: precedence)
71
+ resolve_option(name).set(value, precedence: precedence, resolved_env: resolved_env(name))
72
72
  end
73
73
 
74
74
  def unset_option(name, precedence: Configuration::Option::Precedence::PROGRAMMATIC)
@@ -116,6 +116,10 @@ module Datadog
116
116
  options[name] = definition.build(self)
117
117
  end
118
118
 
119
+ def resolved_env(name)
120
+ return options[name].resolved_env if options.key?(name)
121
+ end
122
+
119
123
  def assert_valid_option!(name)
120
124
  raise(InvalidOptionError, "#{self.class.name} doesn't define the option: #{name}") unless option_defined?(name)
121
125
  end