datadog 2.42.0 → 2.44.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +67 -2
- data/README.md +3 -0
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +46 -5
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +6 -7
- data/ext/datadog_profiling_native_extension/collectors_stack.c +6 -7
- data/ext/datadog_profiling_native_extension/collectors_stack.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +80 -36
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +3 -2
- data/ext/datadog_profiling_native_extension/extconf.rb +4 -2
- data/ext/datadog_profiling_native_extension/heap_recorder.c +13 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +34 -2
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +1 -0
- data/ext/datadog_profiling_native_extension/profiling.c +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +17 -4
- data/ext/datadog_profiling_native_extension/time_helpers.h +5 -4
- data/ext/libdatadog_api/di.c +8 -3
- data/ext/libdatadog_api/extconf.rb +1 -1
- data/ext/libdatadog_api/feature_flags.c +8 -0
- data/ext/libdatadog_api/init.c +3 -1
- data/ext/libdatadog_api/otel_thread_context.c +51 -15
- data/ext/libdatadog_api/trace_exporter.c +642 -22
- data/ext/libdatadog_extconf_helpers.rb +14 -9
- data/lib/datadog/ai_guard/component.rb +17 -8
- data/lib/datadog/ai_guard/configuration/ext.rb +2 -0
- data/lib/datadog/ai_guard/configuration.rb +13 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +48 -55
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +1 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +135 -0
- data/lib/datadog/ai_guard/evaluation/client.rb +50 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +12 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -7
- data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +6 -6
- data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +4 -60
- data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +11 -18
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +15 -2
- data/lib/datadog/ai_guard/evaluation.rb +25 -11
- data/lib/datadog/ai_guard/ext.rb +1 -0
- data/lib/datadog/ai_guard/{api_client.rb → http_client.rb} +6 -4
- data/lib/datadog/ai_guard/metrics/telemetry.rb +43 -0
- data/lib/datadog/ai_guard/redaction/replacements.rb +97 -0
- data/lib/datadog/ai_guard/redaction/result.rb +29 -0
- data/lib/datadog/ai_guard/redaction.rb +80 -0
- data/lib/datadog/ai_guard.rb +58 -57
- data/lib/datadog/core/configuration/components.rb +9 -1
- data/lib/datadog/core/configuration/settings.rb +5 -2
- data/lib/datadog/core/configuration/supported_configurations.rb +8 -0
- data/lib/datadog/core/remote/client/capabilities.rb +10 -4
- data/lib/datadog/core/remote/component.rb +9 -2
- data/lib/datadog/core/remote/worker.rb +8 -0
- data/lib/datadog/di/instrumenter.rb +1 -1
- data/lib/datadog/di/probe_manager.rb +10 -5
- data/lib/datadog/di/proc_responder.rb +1 -1
- data/lib/datadog/open_feature/agentless/configuration_source.rb +246 -0
- data/lib/datadog/open_feature/agentless/parser.rb +43 -0
- data/lib/datadog/open_feature/agentless/response.rb +19 -0
- data/lib/datadog/open_feature/agentless/transport.rb +103 -0
- data/lib/datadog/open_feature/component.rb +57 -1
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +90 -0
- data/lib/datadog/open_feature/configuration/source/resolution.rb +22 -0
- data/lib/datadog/open_feature/configuration/source.rb +43 -0
- data/lib/datadog/open_feature/configuration.rb +118 -0
- data/lib/datadog/open_feature/native_evaluator.rb +1 -14
- data/lib/datadog/open_feature/remote.rb +5 -5
- data/lib/datadog/open_feature/transport.rb +5 -0
- data/lib/datadog/opentelemetry/signal_configuration.rb +13 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +2 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +5 -7
- data/lib/datadog/profiling/collectors/info.rb +2 -6
- data/lib/datadog/symbol_database/extractor.rb +84 -102
- data/lib/datadog/tracing/component.rb +2 -0
- data/lib/datadog/tracing/configuration/ext.rb +1 -0
- data/lib/datadog/tracing/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/context.rb +24 -2
- data/lib/datadog/tracing/context_provider.rb +9 -5
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +32 -5
- data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
- data/lib/datadog/tracing/contrib/sequel/utils.rb +49 -62
- data/lib/datadog/tracing/metadata/ext.rb +3 -0
- data/lib/datadog/tracing/otel_thread_context.rb +78 -9
- data/lib/datadog/tracing/tracer.rb +15 -2
- data/lib/datadog/tracing/transport/native.rb +18 -26
- data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +13 -3
- data/lib/datadog/tracing/transport/traces.rb +3 -23
- data/lib/datadog/version.rb +1 -1
- metadata +25 -7
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c60f4ef57b9508827fac3387bd07b4233666ed9d22684c0d063187d05dcfc449
|
|
4
|
+
data.tar.gz: 6e795bd6f5fc8b5f59d040a4da62e636a15d12024ff4e6b5c2b10d0989c047ec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 27f955e40d920907b2af84f36f8671f4e306235dce525be84da5221e2c66b852183974095afbbcc4acff4148e9202f585067e676d897b20da08c41e535846e9c
|
|
7
|
+
data.tar.gz: 29f4f51331feb1e0a6e70437490b8067b9e4a6f561b55c7f1b5fff58ae326964d92cf8e2dcf16c31466b5f654b851a25e8b683322795573e5ee3742fb395f519
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.44.0] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* AI Guard: Add sensitive-data redaction to evaluated messages, enabled by default; configure it with `ai_guard.redaction_enabled` or `DD_AI_GUARD_REDACTION_ENABLED`. ([#6394][])
|
|
10
|
+
* Open Feature: Add agentless Feature Flags configuration delivery and settings for selecting agentless, Remote Configuration, or offline delivery. ([#6291][])
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
* AI Guard: Require `ruby_llm` 2.0 or later for the `RubyLLM` integration. ([#6394][])
|
|
15
|
+
* Dynamic Instrumentation: Condition evaluation error snapshots are now subject to the process-wide Dynamic Instrumentation snapshot rate limit in addition to the per-probe limit. ([#6250][])
|
|
16
|
+
* OpenTelemetry: Emit `deployment.environment.name` instead of `deployment.environment` for Logs and Metrics resources, and accept it as the Datadog environment while retaining `deployment.environment` as a fallback. ([#6261][])
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
* Core: Fix native extension build failures when installing gems in a directory whose path contains spaces. ([#6371][])
|
|
21
|
+
* Core: Fix Remote Configuration polling remaining stopped in forked web workers when application warmup started it before the fork. ([#6427][])
|
|
22
|
+
* Tracing: Fix the `grape` integration creating no `grape.endpoint_run` span on Grape 4, which moved the API class, HTTP verb and route path off `Grape::Endpoint#options`. ([#6354][]) ([@dduugg][])
|
|
23
|
+
* Tracing: Fix an empty `http.route` tag on spans for 405 responses when running `grape` versions 2.3 through 3.0. ([#6358][])
|
|
24
|
+
* Profiling: Fix the profiler stopping with `BUG: Unexpected CPU time going backwards between samples`. ([#6364][])
|
|
25
|
+
* Profiling: Fix a sampling race condition during profiler shutdown. ([#6375][])
|
|
26
|
+
* Profiling: Fix a potential crash during garbage collection compaction when profiling is enabled. ([#6395][])
|
|
27
|
+
* Profiling: Stop profiling if `thread_name_for`/`rb_thread_t` changes. ([#6398][])
|
|
28
|
+
* Profiling: Fix native extension build breaking when trying to log %. ([#6407][])
|
|
29
|
+
* Dynamic Instrumentation: Fix methods disappearing from code search and source lookup when method logpoints are already installed. ([#6339][])
|
|
30
|
+
* Dynamic Instrumentation: Fix missing condition evaluation error snapshots for method probes with a `when` condition; errors raised while evaluating the condition are now reported to the backend. ([#6250][])
|
|
31
|
+
|
|
32
|
+
## [2.43.0] - 2026-09-22
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
* Core: Add an experimental `libdatadog`-backed native trace transport with full feature parity. Opt in with `DD_EXPERIMENTAL_NATIVE_TRANSPORT_ENABLED=true`. ([#5971][])
|
|
37
|
+
* SSI: Support `force_ruby_platform` during Ruby dependency resolution. ([#6316][])
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
* SSI: Respect transitive application dependencies during Ruby injection. ([#6316][])
|
|
42
|
+
* SSI: Preserve checksums in injected Ruby lockfiles. ([#6320][])
|
|
43
|
+
* SSI: Preserve Bundler selection and `RUBYOPT` options during injection. ([#6316][])
|
|
44
|
+
* SSI: Support versioned and symlinked Bundler launchers. ([#6316][])
|
|
45
|
+
* SSI: Restore Ruby injection for deployment and vendored bundles. ([#6316][])
|
|
46
|
+
* Profiling: Fix a potential sampling race when Ruby is idle. ([#6286][])
|
|
47
|
+
* Profiling: Fix profiler not starting on Ruby 4 due to `undefined symbol: rb_current_box`. ([#6350][])
|
|
48
|
+
|
|
5
49
|
## [2.42.0] - 2026-08-31
|
|
6
50
|
|
|
7
51
|
### Added
|
|
@@ -3776,7 +3820,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3776
3820
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3777
3821
|
|
|
3778
3822
|
|
|
3779
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3823
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.44.0...master
|
|
3824
|
+
[2.44.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.43.0...v2.44.0
|
|
3825
|
+
[2.43.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.42.0...v2.43.0
|
|
3780
3826
|
[2.42.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.41.0...v2.42.0
|
|
3781
3827
|
[2.41.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.40.0...v2.41.0
|
|
3782
3828
|
[2.40.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.39.0...v2.40.0
|
|
@@ -5610,6 +5656,24 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5610
5656
|
[#6232]: https://github.com/DataDog/dd-trace-rb/issues/6232
|
|
5611
5657
|
[#6234]: https://github.com/DataDog/dd-trace-rb/issues/6234
|
|
5612
5658
|
[#6242]: https://github.com/DataDog/dd-trace-rb/issues/6242
|
|
5659
|
+
[#6250]: https://github.com/DataDog/dd-trace-rb/issues/6250
|
|
5660
|
+
[#6261]: https://github.com/DataDog/dd-trace-rb/issues/6261
|
|
5661
|
+
[#6286]: https://github.com/DataDog/dd-trace-rb/issues/6286
|
|
5662
|
+
[#6291]: https://github.com/DataDog/dd-trace-rb/issues/6291
|
|
5663
|
+
[#6316]: https://github.com/DataDog/dd-trace-rb/issues/6316
|
|
5664
|
+
[#6320]: https://github.com/DataDog/dd-trace-rb/issues/6320
|
|
5665
|
+
[#6339]: https://github.com/DataDog/dd-trace-rb/issues/6339
|
|
5666
|
+
[#6350]: https://github.com/DataDog/dd-trace-rb/issues/6350
|
|
5667
|
+
[#6354]: https://github.com/DataDog/dd-trace-rb/issues/6354
|
|
5668
|
+
[#6358]: https://github.com/DataDog/dd-trace-rb/issues/6358
|
|
5669
|
+
[#6364]: https://github.com/DataDog/dd-trace-rb/issues/6364
|
|
5670
|
+
[#6371]: https://github.com/DataDog/dd-trace-rb/issues/6371
|
|
5671
|
+
[#6375]: https://github.com/DataDog/dd-trace-rb/issues/6375
|
|
5672
|
+
[#6394]: https://github.com/DataDog/dd-trace-rb/issues/6394
|
|
5673
|
+
[#6395]: https://github.com/DataDog/dd-trace-rb/issues/6395
|
|
5674
|
+
[#6398]: https://github.com/DataDog/dd-trace-rb/issues/6398
|
|
5675
|
+
[#6407]: https://github.com/DataDog/dd-trace-rb/issues/6407
|
|
5676
|
+
[#6427]: https://github.com/DataDog/dd-trace-rb/issues/6427
|
|
5613
5677
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5614
5678
|
[@Azure7111]: https://github.com/Azure7111
|
|
5615
5679
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -5662,6 +5726,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5662
5726
|
[@cwoodcox]: https://github.com/cwoodcox
|
|
5663
5727
|
[@danhodge]: https://github.com/danhodge
|
|
5664
5728
|
[@dasch]: https://github.com/dasch
|
|
5729
|
+
[@dduugg]: https://github.com/dduugg
|
|
5665
5730
|
[@dim]: https://github.com/dim
|
|
5666
5731
|
[@dirk]: https://github.com/dirk
|
|
5667
5732
|
[@djmb]: https://github.com/djmb
|
|
@@ -5765,4 +5830,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5765
5830
|
[@y-yagi]: https://github.com/y-yagi
|
|
5766
5831
|
[@yujideveloper]: https://github.com/yujideveloper
|
|
5767
5832
|
[@yukimurasawa]: https://github.com/yukimurasawa
|
|
5768
|
-
[@zachmccormick]: https://github.com/zachmccormick
|
|
5833
|
+
[@zachmccormick]: https://github.com/zachmccormick
|
data/README.md
CHANGED
|
@@ -17,8 +17,11 @@ For descriptions of terminology used in APM, take a look at the [APM Terms and C
|
|
|
17
17
|
|
|
18
18
|
For contributing, checkout the [contribution guidelines][contribution docs] and [development guide][development docs].
|
|
19
19
|
|
|
20
|
+
To check that a downloaded gem file was published by this repository, see [how to verify gem provenance][provenance docs].
|
|
21
|
+
|
|
20
22
|
[public docs]: https://docs.datadoghq.com/tracing/setup/ruby/
|
|
21
23
|
[api docs]: https://datadog.github.io/dd-trace-rb/
|
|
22
24
|
[APM glossary]: https://docs.datadoghq.com/tracing/glossary/
|
|
23
25
|
[contribution docs]: https://github.com/DataDog/dd-trace-rb/blob/master/CONTRIBUTING.md
|
|
24
26
|
[development docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/DevelopmentGuide.md
|
|
27
|
+
[provenance docs]: https://github.com/DataDog/dd-trace-rb/blob/master/docs/Provenance.md
|
|
@@ -228,6 +228,7 @@ static VALUE _native_new(VALUE klass);
|
|
|
228
228
|
static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
|
229
229
|
static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
|
|
230
230
|
static VALUE _native_sampling_loop(VALUE self, VALUE instance);
|
|
231
|
+
static VALUE _native_profiler_internal_thread_done(VALUE self_instance);
|
|
231
232
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread);
|
|
232
233
|
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation);
|
|
233
234
|
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception, const char *optional_operation_name);
|
|
@@ -289,6 +290,7 @@ static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instan
|
|
|
289
290
|
static VALUE handle_sampling_failure_rescued_commit_heap_recordings(VALUE self_instance, VALUE exception);
|
|
290
291
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state);
|
|
291
292
|
static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
293
|
+
static VALUE during_sample_exit_rescue(VALUE state_ptr);
|
|
292
294
|
static void commit_heap_recordings_from_postponed_job_may_lose_gvl(DDTRACE_UNUSED void *_unused);
|
|
293
295
|
|
|
294
296
|
// We're using `on_newobj_event` function with `rb_add_event_hook2`, which requires in its public signature a function
|
|
@@ -380,6 +382,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
380
382
|
|
|
381
383
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_initialize", _native_initialize, -1);
|
|
382
384
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_sampling_loop", _native_sampling_loop, 1);
|
|
385
|
+
rb_define_method(collectors_cpu_and_wall_time_worker_class, "_native_profiler_internal_thread_done", _native_profiler_internal_thread_done, 0);
|
|
383
386
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stop", _native_stop, 2);
|
|
384
387
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
|
|
385
388
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stats", _native_stats, 1);
|
|
@@ -650,6 +653,17 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
650
653
|
return Qnil;
|
|
651
654
|
}
|
|
652
655
|
|
|
656
|
+
static VALUE _native_profiler_internal_thread_done(VALUE self_instance) {
|
|
657
|
+
cpu_and_wall_time_worker_state *state;
|
|
658
|
+
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
659
|
+
|
|
660
|
+
during_sample_enter(state);
|
|
661
|
+
return rb_ensure(
|
|
662
|
+
thread_context_collector_profiler_internal_thread_done, state->thread_context_collector_instance,
|
|
663
|
+
during_sample_exit_rescue, (VALUE) state
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
|
|
653
667
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread) {
|
|
654
668
|
cpu_and_wall_time_worker_state *state;
|
|
655
669
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
@@ -740,6 +754,8 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
740
754
|
// a) we get triggered using SIGPROF, and the docs state a second SIGPROF will not interrupt an existing one (see sigaction docs on sa_mask)
|
|
741
755
|
// b) we validate we are in the thread that has the global VM lock; if a different thread gets a signal, it will return early
|
|
742
756
|
// because it will not have the global VM lock
|
|
757
|
+
// c) `simulate_sampling_signal_delivery` calls us directly instead of via a real SIGPROF, and blocks SIGPROF delivery on its
|
|
758
|
+
// thread for the duration of that call, so it can't be nested into by a real SIGPROF either
|
|
743
759
|
|
|
744
760
|
state->stats.signal_handler_enqueued_sample++;
|
|
745
761
|
|
|
@@ -749,11 +765,20 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
749
765
|
!state->during_sample;
|
|
750
766
|
|
|
751
767
|
if (sample_from_signal_handler) {
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
768
|
+
if (rb_during_gc()) {
|
|
769
|
+
// During GC Ruby might be marking our buffer or compacting (moving) where iseqs live so we skip preparing the
|
|
770
|
+
// sample immediately, and instead ask on_gc_finish to do the job when GC is at its end.
|
|
771
|
+
//
|
|
772
|
+
// When GC profiling is disabled, we just fall back to sampling the stack after GC finishes, e.g. it's the
|
|
773
|
+
// equivalent of disabling `sample_from_signal_handler` for samples that happen during GC.
|
|
774
|
+
thread_context_collector_request_prepare_on_gc_finish();
|
|
775
|
+
} else {
|
|
776
|
+
// Buffer current stack trace. Note that this will not actually record the sample, for that we still need to wait
|
|
777
|
+
// until the postponed job below gets run.
|
|
778
|
+
bool prepared = thread_context_collector_prepare_sample_inside_signal_handler();
|
|
755
779
|
|
|
756
|
-
|
|
780
|
+
if (prepared) state->stats.signal_handler_prepared_sample++;
|
|
781
|
+
}
|
|
757
782
|
}
|
|
758
783
|
|
|
759
784
|
#ifndef NO_POSTPONED_TRIGGER // Ruby 3.3+
|
|
@@ -1094,7 +1119,10 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
|
|
|
1094
1119
|
if (event == RUBY_INTERNAL_EVENT_GC_ENTER) {
|
|
1095
1120
|
thread_context_collector_on_gc_start(state->thread_context_collector_instance);
|
|
1096
1121
|
} else if (event == RUBY_INTERNAL_EVENT_GC_EXIT) {
|
|
1097
|
-
bool
|
|
1122
|
+
bool allow_prepare_sample = !state->during_sample;
|
|
1123
|
+
if (allow_prepare_sample) during_sample_enter(state);
|
|
1124
|
+
bool should_flush = thread_context_collector_on_gc_finish(state->thread_context_collector_instance, allow_prepare_sample);
|
|
1125
|
+
if (allow_prepare_sample) during_sample_exit(state);
|
|
1098
1126
|
|
|
1099
1127
|
// We use rb_postponed_job_register_one to ask Ruby to run thread_context_collector_sample_after_gc when the
|
|
1100
1128
|
// thread collector flags it's time to flush.
|
|
@@ -1279,11 +1307,19 @@ void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
|
|
|
1279
1307
|
// This can potentially happen if the CpuAndWallTimeWorker was stopped while the IdleSamplingHelper was trying to execute this action
|
|
1280
1308
|
if (state == NULL) return NULL;
|
|
1281
1309
|
|
|
1310
|
+
// Since this is not a real signal firing, we need to block SIGPROF delivery on this thread to avoid an actual SIGPROF
|
|
1311
|
+
// signal coming in nested and interrupting us on this thread. Thus we respect the invariant of "no nesting" for `handle_sampling_signal`.
|
|
1312
|
+
//
|
|
1313
|
+
// Not needed when `no_signals_workaround_enabled` is set: no SIGPROFs are ever sent in that mode, so there's nothing to mask.
|
|
1314
|
+
if (!state->no_signals_workaround_enabled) block_sigprof_signal_handler_from_running_in_current_thread();
|
|
1315
|
+
|
|
1282
1316
|
state->stats.simulated_signal_delivery++;
|
|
1283
1317
|
|
|
1284
1318
|
// `handle_sampling_signal` does a few things extra on top of `sample_from_postponed_job` so that's why we don't shortcut here
|
|
1285
1319
|
handle_sampling_signal(0, NULL, NULL);
|
|
1286
1320
|
|
|
1321
|
+
if (!state->no_signals_workaround_enabled) unblock_sigprof_signal_handler_from_running_in_current_thread();
|
|
1322
|
+
|
|
1287
1323
|
return NULL; // Unused
|
|
1288
1324
|
}
|
|
1289
1325
|
|
|
@@ -1765,3 +1801,8 @@ static inline void during_sample_exit(cpu_and_wall_time_worker_state* state) {
|
|
|
1765
1801
|
atomic_signal_fence(memory_order_seq_cst);
|
|
1766
1802
|
state->during_sample = false;
|
|
1767
1803
|
}
|
|
1804
|
+
|
|
1805
|
+
static VALUE during_sample_exit_rescue(VALUE state_ptr) {
|
|
1806
|
+
during_sample_exit((cpu_and_wall_time_worker_state *) state_ptr);
|
|
1807
|
+
return Qnil;
|
|
1808
|
+
}
|
|
@@ -31,9 +31,9 @@ typedef struct {
|
|
|
31
31
|
|
|
32
32
|
static VALUE _native_new(VALUE klass);
|
|
33
33
|
static void reset_state(idle_sampling_loop_state *state);
|
|
34
|
-
static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance, VALUE
|
|
34
|
+
static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance, VALUE cpu_and_wall_time_worker_instance);
|
|
35
35
|
static VALUE idle_sampling_loop_body(VALUE self_instance);
|
|
36
|
-
static VALUE idle_sampling_loop_ensure(VALUE
|
|
36
|
+
static VALUE idle_sampling_loop_ensure(VALUE cpu_and_wall_time_worker_instance);
|
|
37
37
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance);
|
|
38
38
|
static void *run_idle_sampling_loop(void *state_ptr);
|
|
39
39
|
static void interrupt_idle_sampling_loop(void *state_ptr);
|
|
@@ -112,8 +112,8 @@ static VALUE _native_reset(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
|
|
|
112
112
|
return Qtrue;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance, VALUE
|
|
116
|
-
return rb_ensure(idle_sampling_loop_body, self_instance, idle_sampling_loop_ensure,
|
|
115
|
+
static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance, VALUE cpu_and_wall_time_worker_instance) {
|
|
116
|
+
return rb_ensure(idle_sampling_loop_body, self_instance, idle_sampling_loop_ensure, cpu_and_wall_time_worker_instance);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
static VALUE idle_sampling_loop_body(VALUE self_instance) {
|
|
@@ -128,9 +128,8 @@ static VALUE idle_sampling_loop_body(VALUE self_instance) {
|
|
|
128
128
|
return Qtrue;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
static VALUE idle_sampling_loop_ensure(VALUE
|
|
132
|
-
|
|
133
|
-
return Qnil;
|
|
131
|
+
static VALUE idle_sampling_loop_ensure(VALUE cpu_and_wall_time_worker_instance) {
|
|
132
|
+
return rb_funcall(cpu_and_wall_time_worker_instance, rb_intern("_native_profiler_internal_thread_done"), 0);
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
static void *run_idle_sampling_loop(void *state_ptr) {
|
|
@@ -642,8 +642,8 @@ void record_placeholder_stack(
|
|
|
642
642
|
}
|
|
643
643
|
|
|
644
644
|
bool prepare_sample_thread(VALUE thread, sampling_buffer *buffer) {
|
|
645
|
-
//
|
|
646
|
-
//
|
|
645
|
+
// While the signal handler checks if there's GC going on, it's actually possible for `sampling_buffer_mark` to
|
|
646
|
+
// still run outside of GC (see comments on that function) and thus we guard for it here.
|
|
647
647
|
if (buffer->is_marking) return false;
|
|
648
648
|
|
|
649
649
|
buffer->pending_sample = true;
|
|
@@ -705,12 +705,11 @@ void sampling_buffer_mark(sampling_buffer *buffer) {
|
|
|
705
705
|
}
|
|
706
706
|
|
|
707
707
|
buffer->is_marking = true;
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
//
|
|
711
|
-
// `prepare_sample_thread` to add a new sample to the buffer. This flag is here to prevent that BUT we need to
|
|
712
|
-
// make sure the signal handler actually sees the flag being set.
|
|
708
|
+
// The sampling buffer isn't supposed to be touched during GC. Yet, marking can happen outside of GC -- in particular
|
|
709
|
+
// ObjectSpace.dump/dump_all and reachable_objects_from invoke mark callbacks outside GC to enumerate references.
|
|
710
|
+
// Thus we keep this flag to tell the signal handler "hey you're still not allowed to touch the buffer at this time".
|
|
713
711
|
//
|
|
712
|
+
// The fences ensure the compiler doesn't reorder the flags and a signal handler observes them
|
|
714
713
|
// See https://github.com/ruby/ruby/pull/11036 for a similar change made to the Ruby VM with more context.
|
|
715
714
|
atomic_signal_fence(memory_order_seq_cst);
|
|
716
715
|
|
|
@@ -13,7 +13,7 @@ typedef struct {
|
|
|
13
13
|
uint16_t max_frames;
|
|
14
14
|
frame_info *stack_buffer;
|
|
15
15
|
bool pending_sample;
|
|
16
|
-
bool is_marking; // Used to avoid recording a sample when marking
|
|
16
|
+
bool is_marking; // Used to avoid recording a sample when marking (marking can happen outside of GC as well)
|
|
17
17
|
int pending_sample_result;
|
|
18
18
|
} sampling_buffer;
|
|
19
19
|
|