datadog 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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