datadog 2.28.0 → 2.30.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 +87 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +82 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +32 -11
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +3 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +9 -24
- data/ext/datadog_profiling_native_extension/heap_recorder.c +186 -55
- data/ext/datadog_profiling_native_extension/heap_recorder.h +12 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +51 -64
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
- data/ext/datadog_profiling_native_extension/profiling.c +3 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +24 -8
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -3
- data/ext/datadog_profiling_native_extension/stack_recorder.c +63 -48
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -1
- data/ext/libdatadog_api/crashtracker.c +5 -0
- data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
- data/ext/libdatadog_api/extconf.rb +4 -21
- data/ext/libdatadog_extconf_helpers.rb +49 -11
- data/lib/datadog/ai_guard/configuration/settings.rb +3 -0
- data/lib/datadog/appsec/assets/blocked.html +2 -1
- data/lib/datadog/appsec/configuration/settings.rb +14 -0
- data/lib/datadog/appsec/context.rb +44 -9
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +3 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/patcher.rb +2 -0
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +55 -6
- data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +60 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +11 -6
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +6 -10
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +4 -4
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +26 -5
- data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +2 -0
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +2 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +72 -7
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +5 -3
- data/lib/datadog/appsec/counter_sampler.rb +25 -0
- data/lib/datadog/appsec/event.rb +1 -17
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
- data/lib/datadog/appsec/instrumentation/gateway.rb +2 -2
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +18 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/security_engine/engine.rb +23 -2
- data/lib/datadog/appsec/utils/http/body.rb +38 -0
- data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
- data/lib/datadog/appsec/utils/http/media_type.rb +28 -35
- data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
- data/lib/datadog/core/configuration/components.rb +29 -4
- data/lib/datadog/core/configuration/option.rb +2 -1
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +27 -3
- data/lib/datadog/core/configuration/supported_configurations.rb +19 -0
- data/lib/datadog/core/configuration.rb +2 -2
- data/lib/datadog/core/crashtracking/component.rb +71 -19
- data/lib/datadog/core/environment/agent_info.rb +65 -1
- data/lib/datadog/core/logger.rb +1 -1
- data/lib/datadog/core/metrics/logging.rb +1 -1
- data/lib/datadog/core/process_discovery.rb +20 -19
- data/lib/datadog/core/rate_limiter.rb +2 -0
- data/lib/datadog/core/remote/component.rb +16 -5
- data/lib/datadog/core/remote/transport/config.rb +5 -11
- data/lib/datadog/core/runtime/metrics.rb +1 -2
- data/lib/datadog/core/telemetry/component.rb +0 -13
- data/lib/datadog/core/telemetry/transport/telemetry.rb +5 -6
- data/lib/datadog/core/transport/ext.rb +1 -0
- data/lib/datadog/core/transport/http/response.rb +4 -0
- data/lib/datadog/core/transport/parcel.rb +61 -9
- data/lib/datadog/core/utils/base64.rb +1 -1
- data/lib/datadog/core/utils/fnv.rb +26 -0
- data/lib/datadog/core/workers/interval_loop.rb +13 -6
- data/lib/datadog/core/workers/queue.rb +0 -4
- data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
- data/lib/datadog/core.rb +6 -1
- data/lib/datadog/data_streams/processor.rb +35 -33
- data/lib/datadog/data_streams/transport/http/stats.rb +6 -0
- data/lib/datadog/data_streams/transport/http.rb +0 -4
- data/lib/datadog/data_streams/transport/stats.rb +5 -12
- data/lib/datadog/di/boot.rb +1 -0
- data/lib/datadog/di/component.rb +17 -5
- data/lib/datadog/di/configuration/settings.rb +9 -0
- data/lib/datadog/di/context.rb +6 -0
- data/lib/datadog/di/instrumenter.rb +183 -134
- data/lib/datadog/di/probe.rb +10 -1
- data/lib/datadog/di/probe_file_loader.rb +2 -2
- data/lib/datadog/di/probe_manager.rb +86 -64
- data/lib/datadog/di/probe_notification_builder.rb +46 -18
- data/lib/datadog/di/probe_notifier_worker.rb +65 -9
- data/lib/datadog/di/probe_repository.rb +198 -0
- data/lib/datadog/di/proc_responder.rb +4 -0
- data/lib/datadog/di/remote.rb +6 -7
- data/lib/datadog/di/serializer.rb +127 -9
- data/lib/datadog/di/transport/diagnostics.rb +5 -7
- data/lib/datadog/di/transport/http/diagnostics.rb +3 -1
- data/lib/datadog/di/transport/http/input.rb +1 -1
- data/lib/datadog/di/transport/http.rb +12 -3
- data/lib/datadog/di/transport/input.rb +51 -14
- data/lib/datadog/kit/tracing/method_tracer.rb +132 -0
- data/lib/datadog/open_feature/configuration.rb +2 -0
- data/lib/datadog/open_feature/transport.rb +8 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +13 -0
- data/lib/datadog/profiling/component.rb +20 -6
- data/lib/datadog/profiling/http_transport.rb +5 -6
- data/lib/datadog/profiling/profiler.rb +15 -8
- data/lib/datadog/tracing/contrib/dalli/integration.rb +4 -1
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +2 -2
- data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
- data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -1
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +2 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +10 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +24 -0
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +18 -6
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/registerable.rb +11 -0
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +1 -0
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/sync_writer.rb +0 -1
- data/lib/datadog/tracing/transport/io/client.rb +5 -8
- data/lib/datadog/tracing/transport/io/traces.rb +28 -34
- data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
- data/lib/datadog/tracing/transport/traces.rb +4 -10
- data/lib/datadog/tracing/writer.rb +0 -1
- data/lib/datadog/version.rb +1 -1
- metadata +14 -8
- data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
- data/lib/datadog/tracing/workers/trace_writer.rb +0 -204
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2983471f43d0c9b3473b3c65d0ca656514c6cf8cd7a32e35ec26826193fe533
|
|
4
|
+
data.tar.gz: 687d088d90ce4ee0ae5af66d9e604135f058bd7609641f4c7963f1ba32a2bb37
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 96f3744eadab0292666e18beac7deab2a6b7ef61b0da216ab4490e7621b0cec7839d18a519079b5b0563e2a260388b63ef59b5243a65c3d6ba997f3c7981986c
|
|
7
|
+
data.tar.gz: a82f01f50d499f1a08309f23144e5453cb9cf79bdc5b0c7daa9b3c9c373e3a41983babe3f86dc027f2dd2e9f056bc4b7645a49f799531e40eae9455ab7e00a6d
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.30.0] - 2026-03-19
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* Core: Enable `libdatadog`-based features and tests on macOS ([#5351][])
|
|
10
|
+
* Tracing: Add `_dd.p.ksr` propagated tag to transmit Knuth sampling rate for backend resampling ([#5436][])
|
|
11
|
+
* Tracing: Integrations: Add `DD_TRACE_<INTEGRATION>_DISTRIBUTED_TRACING` environment variables to control distributed tracing per integration ([#5396][])
|
|
12
|
+
* Profiling: Add profiler setting `experimental_use_system_dns` to use system DNS resolver (defaults to true) ([#5425][], [#5449][])
|
|
13
|
+
* Profiling: Allow lowering CPU profiling sampling interval with `experimental_cpu_sampling_interval_ms` setting ([#5424][])
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
* Core: Enable process tags by default by setting `DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED`, expanding tag collection for Tracing, Database Monitoring, Data Streams Monitoring, Profiling, Runtime Metrics, Process Discovery, Remote Configuration, Telemetry, Dynamic Instrumentation, and CrashTracking ([#5432][])
|
|
18
|
+
* Core: Upgrade `libdatadog` dependency to version 29.0.0 ([#5274][], [#5461][])
|
|
19
|
+
* Core: Remove dependency on `pkg-config` system tool for native extension builds ([#5469][])
|
|
20
|
+
* Profiling: Improve profiling error message when another profiler is present ([#5375][])
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
* Tracing: Integrations: Fix `endpoint_render.grape` ActiveSupport notification instrumentation for `grape` 3.x ([#5414][])
|
|
25
|
+
* Tracing: Integrations: Fix compatibility with `dalli` version 5.x and later ([#5435][])
|
|
26
|
+
* Dynamic Instrumentation: Fix JSON serialization failures when snapshots contain binary data and invalid UTF-8 strings ([#5434][])
|
|
27
|
+
* Dynamic Instrumentation: Show ERROR probe status when custom serializers produce non-JSON-encodable data instead of silent failures ([#5448][])
|
|
28
|
+
* Data Streams: Fix Data Streams Monitoring to correctly report the configured environment instead of showing `env:none` ([#5427][])
|
|
29
|
+
|
|
30
|
+
## [2.29.0] - 2026-02-20
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
* AppSec: Add analysis for downstream request with redirects ([#5347][])
|
|
36
|
+
* AppSec: Add downstream request body analysis. ([#5320][])
|
|
37
|
+
* SSI: Add support for Bundler vendored mode (`BUNDLE_PATH`) ([#5368][])
|
|
38
|
+
* SSI: Default to local dependency resolution ([#5368][])
|
|
39
|
+
* Dynamic Instrumentation: Added circuit breaker to automatically disable probes consuming excessive CPU time ([#5335][])
|
|
40
|
+
* Crashtracking: Add reporting of unhandled exceptions ([#5321][])
|
|
41
|
+
* Tracing: Add support for the `kicks` gem ([#5305][])
|
|
42
|
+
* Profiling: Add heap profiling for ruby 4.x ([#5201][])
|
|
43
|
+
* Tracing: Add simple method tracing API ([#5294][])
|
|
44
|
+
* Tracing: Add `trace_singleton_class_method` for tracing singleton class methods. ([#5334][])
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
* Dynamic Instrumentation: Improve error reporting when instrumentation fails or is removed due to circuit breaker ([#5371][])
|
|
49
|
+
* SSI: Reduce SSI package size ([#5352][])
|
|
50
|
+
* Core: Change default logger output from stdout to stderr ([#5342][])
|
|
51
|
+
* AppSec: Make AppSec blocking page more friendly for vulnerability scanners ([#5341][])
|
|
52
|
+
* Core: Add process tags and container id to process discovery payloads when the experimental setting `DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=true` is enabled. ([#5336][])
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
* Dynamic Instrumentation: Fix Live Debugger UI for forking web servers with more than one worker process ([#5304][])
|
|
57
|
+
|
|
5
58
|
## [2.28.0] - 2026-02-04
|
|
6
59
|
|
|
7
60
|
### Added
|
|
@@ -3486,7 +3539,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3486
3539
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3487
3540
|
|
|
3488
3541
|
|
|
3489
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3542
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.30.0...master
|
|
3543
|
+
[2.30.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.29.0...v2.30.0
|
|
3544
|
+
[2.29.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.28.0...v2.29.0
|
|
3490
3545
|
[2.28.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.27.0...v2.28.0
|
|
3491
3546
|
[2.27.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.26.0...v2.27.0
|
|
3492
3547
|
[2.26.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.25.0...v2.26.0
|
|
@@ -5153,6 +5208,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5153
5208
|
[#5176]: https://github.com/DataDog/dd-trace-rb/issues/5176
|
|
5154
5209
|
[#5194]: https://github.com/DataDog/dd-trace-rb/issues/5194
|
|
5155
5210
|
[#5197]: https://github.com/DataDog/dd-trace-rb/issues/5197
|
|
5211
|
+
[#5201]: https://github.com/DataDog/dd-trace-rb/issues/5201
|
|
5156
5212
|
[#5206]: https://github.com/DataDog/dd-trace-rb/issues/5206
|
|
5157
5213
|
[#5210]: https://github.com/DataDog/dd-trace-rb/issues/5210
|
|
5158
5214
|
[#5215]: https://github.com/DataDog/dd-trace-rb/issues/5215
|
|
@@ -5164,8 +5220,38 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5164
5220
|
[#5247]: https://github.com/DataDog/dd-trace-rb/issues/5247
|
|
5165
5221
|
[#5254]: https://github.com/DataDog/dd-trace-rb/issues/5254
|
|
5166
5222
|
[#5273]: https://github.com/DataDog/dd-trace-rb/issues/5273
|
|
5223
|
+
[#5274]: https://github.com/DataDog/dd-trace-rb/issues/5274
|
|
5167
5224
|
[#5278]: https://github.com/DataDog/dd-trace-rb/issues/5278
|
|
5168
5225
|
[#5283]: https://github.com/DataDog/dd-trace-rb/issues/5283
|
|
5226
|
+
[#5294]: https://github.com/DataDog/dd-trace-rb/issues/5294
|
|
5227
|
+
[#5304]: https://github.com/DataDog/dd-trace-rb/issues/5304
|
|
5228
|
+
[#5305]: https://github.com/DataDog/dd-trace-rb/issues/5305
|
|
5229
|
+
[#5320]: https://github.com/DataDog/dd-trace-rb/issues/5320
|
|
5230
|
+
[#5321]: https://github.com/DataDog/dd-trace-rb/issues/5321
|
|
5231
|
+
[#5334]: https://github.com/DataDog/dd-trace-rb/issues/5334
|
|
5232
|
+
[#5335]: https://github.com/DataDog/dd-trace-rb/issues/5335
|
|
5233
|
+
[#5336]: https://github.com/DataDog/dd-trace-rb/issues/5336
|
|
5234
|
+
[#5341]: https://github.com/DataDog/dd-trace-rb/issues/5341
|
|
5235
|
+
[#5342]: https://github.com/DataDog/dd-trace-rb/issues/5342
|
|
5236
|
+
[#5347]: https://github.com/DataDog/dd-trace-rb/issues/5347
|
|
5237
|
+
[#5351]: https://github.com/DataDog/dd-trace-rb/issues/5351
|
|
5238
|
+
[#5352]: https://github.com/DataDog/dd-trace-rb/issues/5352
|
|
5239
|
+
[#5368]: https://github.com/DataDog/dd-trace-rb/issues/5368
|
|
5240
|
+
[#5371]: https://github.com/DataDog/dd-trace-rb/issues/5371
|
|
5241
|
+
[#5375]: https://github.com/DataDog/dd-trace-rb/issues/5375
|
|
5242
|
+
[#5396]: https://github.com/DataDog/dd-trace-rb/issues/5396
|
|
5243
|
+
[#5414]: https://github.com/DataDog/dd-trace-rb/issues/5414
|
|
5244
|
+
[#5424]: https://github.com/DataDog/dd-trace-rb/issues/5424
|
|
5245
|
+
[#5425]: https://github.com/DataDog/dd-trace-rb/issues/5425
|
|
5246
|
+
[#5427]: https://github.com/DataDog/dd-trace-rb/issues/5427
|
|
5247
|
+
[#5432]: https://github.com/DataDog/dd-trace-rb/issues/5432
|
|
5248
|
+
[#5434]: https://github.com/DataDog/dd-trace-rb/issues/5434
|
|
5249
|
+
[#5435]: https://github.com/DataDog/dd-trace-rb/issues/5435
|
|
5250
|
+
[#5436]: https://github.com/DataDog/dd-trace-rb/issues/5436
|
|
5251
|
+
[#5448]: https://github.com/DataDog/dd-trace-rb/issues/5448
|
|
5252
|
+
[#5449]: https://github.com/DataDog/dd-trace-rb/issues/5449
|
|
5253
|
+
[#5461]: https://github.com/DataDog/dd-trace-rb/issues/5461
|
|
5254
|
+
[#5469]: https://github.com/DataDog/dd-trace-rb/issues/5469
|
|
5169
5255
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5170
5256
|
[@Azure7111]: https://github.com/Azure7111
|
|
5171
5257
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -87,6 +87,7 @@ unsigned int MAX_ALLOC_WEIGHT = 10000;
|
|
|
87
87
|
static rb_postponed_job_handle_t sample_from_postponed_job_handle;
|
|
88
88
|
static rb_postponed_job_handle_t after_gc_from_postponed_job_handle;
|
|
89
89
|
static rb_postponed_job_handle_t after_gvl_running_from_postponed_job_handle;
|
|
90
|
+
static rb_postponed_job_handle_t after_allocation_from_postponed_job_handle;
|
|
90
91
|
#endif
|
|
91
92
|
|
|
92
93
|
// Contains state for a single CpuAndWallTimeWorker instance
|
|
@@ -101,6 +102,7 @@ typedef struct {
|
|
|
101
102
|
bool gvl_profiling_enabled;
|
|
102
103
|
bool skip_idle_samples_for_testing;
|
|
103
104
|
bool sighandler_sampling_enabled;
|
|
105
|
+
uint32_t cpu_sampling_interval_ms;
|
|
104
106
|
VALUE self_instance;
|
|
105
107
|
VALUE thread_context_collector_instance;
|
|
106
108
|
VALUE idle_sampling_helper_instance;
|
|
@@ -138,6 +140,8 @@ typedef struct {
|
|
|
138
140
|
// # Generic stats
|
|
139
141
|
// How many times we tried to trigger a sample
|
|
140
142
|
unsigned int trigger_sample_attempts;
|
|
143
|
+
// How many times extra sleep was triggered by dynamic sampling rate
|
|
144
|
+
unsigned int trigger_sample_extra_sleep;
|
|
141
145
|
// How many times we tried to simulate signal delivery
|
|
142
146
|
unsigned int trigger_simulated_signal_delivery_attempts;
|
|
143
147
|
// How many times we actually simulated signal delivery
|
|
@@ -229,23 +233,26 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
229
233
|
static void disable_tracepoints(cpu_and_wall_time_worker_state *state);
|
|
230
234
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
|
|
231
235
|
static VALUE rescued_sample_allocation(VALUE tracepoint_data);
|
|
236
|
+
static VALUE rescued_after_allocation(VALUE self_instance);
|
|
232
237
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
|
|
233
238
|
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state);
|
|
234
239
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
|
|
235
240
|
static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
|
|
236
241
|
static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
|
237
242
|
#ifndef NO_GVL_INSTRUMENTATION
|
|
238
|
-
static void on_gvl_event(rb_event_flag_t event_id, const rb_internal_thread_event_data_t *event_data, DDTRACE_UNUSED void *_unused);
|
|
239
|
-
static void after_gvl_running_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
243
|
+
static void on_gvl_event(rb_event_flag_t event_id, const rb_internal_thread_event_data_t *event_data, DDTRACE_UNUSED void *_unused);
|
|
244
|
+
static void after_gvl_running_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
245
|
+
static VALUE rescued_after_gvl_running_from_postponed_job(VALUE self_instance);
|
|
246
|
+
static VALUE handle_sampling_failure_rescued_after_gvl_running_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
240
247
|
#endif
|
|
241
|
-
static VALUE rescued_after_gvl_running_from_postponed_job(VALUE self_instance);
|
|
242
248
|
static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
243
249
|
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
244
250
|
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception);
|
|
245
251
|
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception);
|
|
246
|
-
static VALUE
|
|
252
|
+
static VALUE handle_sampling_failure_rescued_after_allocation(VALUE self_instance, VALUE exception);
|
|
247
253
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state);
|
|
248
254
|
static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
255
|
+
static void after_allocation_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
249
256
|
|
|
250
257
|
// We're using `on_newobj_event` function with `rb_add_event_hook2`, which requires in its public signature a function
|
|
251
258
|
// with signature `rb_event_hook_func_t` which doesn't match `on_newobj_event`.
|
|
@@ -293,11 +300,13 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
293
300
|
sample_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, sample_from_postponed_job, NULL);
|
|
294
301
|
after_gc_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gc_from_postponed_job, NULL);
|
|
295
302
|
after_gvl_running_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gvl_running_from_postponed_job, NULL);
|
|
303
|
+
after_allocation_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_allocation_from_postponed_job, NULL);
|
|
296
304
|
|
|
297
305
|
if (
|
|
298
306
|
sample_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
299
307
|
after_gc_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
300
|
-
after_gvl_running_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID
|
|
308
|
+
after_gvl_running_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
309
|
+
after_allocation_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID
|
|
301
310
|
) {
|
|
302
311
|
raise_error(rb_eRuntimeError, "Failed to register profiler postponed jobs (got POSTPONED_JOB_HANDLE_INVALID)");
|
|
303
312
|
}
|
|
@@ -375,6 +384,7 @@ static VALUE _native_new(VALUE klass) {
|
|
|
375
384
|
state->gvl_profiling_enabled = false;
|
|
376
385
|
state->skip_idle_samples_for_testing = false;
|
|
377
386
|
state->sighandler_sampling_enabled = false;
|
|
387
|
+
state->cpu_sampling_interval_ms = 10;
|
|
378
388
|
state->thread_context_collector_instance = Qnil;
|
|
379
389
|
state->idle_sampling_helper_instance = Qnil;
|
|
380
390
|
state->owner_thread = Qnil;
|
|
@@ -419,6 +429,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
419
429
|
VALUE gvl_profiling_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("gvl_profiling_enabled")));
|
|
420
430
|
VALUE skip_idle_samples_for_testing = rb_hash_fetch(options, ID2SYM(rb_intern("skip_idle_samples_for_testing")));
|
|
421
431
|
VALUE sighandler_sampling_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("sighandler_sampling_enabled")));
|
|
432
|
+
VALUE cpu_sampling_interval_ms = rb_hash_fetch(options, ID2SYM(rb_intern("cpu_sampling_interval_ms")));
|
|
422
433
|
|
|
423
434
|
ENFORCE_BOOLEAN(gc_profiling_enabled);
|
|
424
435
|
ENFORCE_BOOLEAN(no_signals_workaround_enabled);
|
|
@@ -429,6 +440,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
429
440
|
ENFORCE_BOOLEAN(gvl_profiling_enabled);
|
|
430
441
|
ENFORCE_BOOLEAN(skip_idle_samples_for_testing)
|
|
431
442
|
ENFORCE_BOOLEAN(sighandler_sampling_enabled)
|
|
443
|
+
ENFORCE_TYPE(cpu_sampling_interval_ms, T_FIXNUM);
|
|
432
444
|
|
|
433
445
|
cpu_and_wall_time_worker_state *state;
|
|
434
446
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
@@ -441,6 +453,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
441
453
|
state->gvl_profiling_enabled = (gvl_profiling_enabled == Qtrue);
|
|
442
454
|
state->skip_idle_samples_for_testing = (skip_idle_samples_for_testing == Qtrue);
|
|
443
455
|
state->sighandler_sampling_enabled = (sighandler_sampling_enabled == Qtrue);
|
|
456
|
+
state->cpu_sampling_interval_ms = NUM2INT(cpu_sampling_interval_ms);
|
|
444
457
|
|
|
445
458
|
double total_overhead_target_percentage = NUM2DBL(dynamic_sampling_rate_overhead_target_percentage);
|
|
446
459
|
if (!state->allocation_profiling_enabled) {
|
|
@@ -548,8 +561,9 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
548
561
|
// @ivoanjo: I suspect this will never happen, but the cost of getting it wrong is really high (VM terminates) so this
|
|
549
562
|
// is a just-in-case situation.
|
|
550
563
|
//
|
|
551
|
-
// Note 2:
|
|
552
|
-
replace_sigprof_signal_handler_with_empty_handler
|
|
564
|
+
// Note 2: If exception_state is set, we have a pending exception that we'll re-raise below.
|
|
565
|
+
// In that case, we don't want replace_sigprof_signal_handler_with_empty_handler to raise another exception.
|
|
566
|
+
replace_sigprof_signal_handler_with_empty_handler(handle_sampling_signal, !exception_state);
|
|
553
567
|
|
|
554
568
|
// Ensure that instance is not garbage collected while the native sampling loop is running; this is probably not needed, but just in case
|
|
555
569
|
RB_GC_GUARD(instance);
|
|
@@ -660,7 +674,7 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
660
674
|
static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
661
675
|
cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
|
|
662
676
|
|
|
663
|
-
uint64_t minimum_time_between_signals = MILLIS_AS_NS(
|
|
677
|
+
uint64_t minimum_time_between_signals = MILLIS_AS_NS(state->cpu_sampling_interval_ms);
|
|
664
678
|
|
|
665
679
|
while (atomic_load(&state->should_run)) {
|
|
666
680
|
state->stats.trigger_sample_attempts++;
|
|
@@ -713,7 +727,10 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
|
713
727
|
// `dynamic_sampling_rate_get_sleep` may have changed while the above sleep was ongoing.
|
|
714
728
|
uint64_t extra_sleep =
|
|
715
729
|
dynamic_sampling_rate_get_sleep(&state->cpu_dynamic_sampling_rate, monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE));
|
|
716
|
-
if (state->dynamic_sampling_rate_enabled && extra_sleep > 0)
|
|
730
|
+
if (state->dynamic_sampling_rate_enabled && extra_sleep > 0) {
|
|
731
|
+
state->stats.trigger_sample_extra_sleep++;
|
|
732
|
+
sleep_for(extra_sleep);
|
|
733
|
+
}
|
|
717
734
|
}
|
|
718
735
|
|
|
719
736
|
return NULL; // Unused
|
|
@@ -1049,6 +1066,7 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
|
1049
1066
|
VALUE stats_as_hash = rb_hash_new();
|
|
1050
1067
|
VALUE arguments[] = {
|
|
1051
1068
|
ID2SYM(rb_intern("trigger_sample_attempts")), /* => */ UINT2NUM(state->stats.trigger_sample_attempts),
|
|
1069
|
+
ID2SYM(rb_intern("trigger_sample_extra_sleep")), /* => */ UINT2NUM(state->stats.trigger_sample_extra_sleep),
|
|
1052
1070
|
ID2SYM(rb_intern("trigger_simulated_signal_delivery_attempts")), /* => */ UINT2NUM(state->stats.trigger_simulated_signal_delivery_attempts),
|
|
1053
1071
|
ID2SYM(rb_intern("simulated_signal_delivery")), /* => */ UINT2NUM(state->stats.simulated_signal_delivery),
|
|
1054
1072
|
ID2SYM(rb_intern("signal_handler_enqueued_sample")), /* => */ UINT2NUM(state->stats.signal_handler_enqueued_sample),
|
|
@@ -1312,13 +1330,21 @@ static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
|
|
|
1312
1330
|
// To control bias from sampling, we clamp the maximum weight attributed to a single allocation sample. This avoids
|
|
1313
1331
|
// assigning a very large number to a sample, if for instance the dynamic sampling mechanism chose a really big interval.
|
|
1314
1332
|
unsigned int weight = allocations_since_last_sample > MAX_ALLOC_WEIGHT ? MAX_ALLOC_WEIGHT : (unsigned int) allocations_since_last_sample;
|
|
1315
|
-
thread_context_collector_sample_allocation(state->thread_context_collector_instance, weight, new_object);
|
|
1333
|
+
bool needs_after_allocation = thread_context_collector_sample_allocation(state->thread_context_collector_instance, weight, new_object);
|
|
1316
1334
|
// ...but we still represent the skipped samples in the profile, thus the data will account for all allocations.
|
|
1317
1335
|
if (weight < allocations_since_last_sample) {
|
|
1318
1336
|
uint32_t skipped_samples = (uint32_t) uint64_min_of(allocations_since_last_sample - weight, UINT32_MAX);
|
|
1319
1337
|
thread_context_collector_sample_skipped_allocation_samples(state->thread_context_collector_instance, skipped_samples);
|
|
1320
1338
|
}
|
|
1321
1339
|
|
|
1340
|
+
if (needs_after_allocation) {
|
|
1341
|
+
#ifndef NO_POSTPONED_TRIGGER
|
|
1342
|
+
rb_postponed_job_trigger(after_allocation_from_postponed_job_handle);
|
|
1343
|
+
#else
|
|
1344
|
+
// Not needed on legacy rubies
|
|
1345
|
+
#endif
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1322
1348
|
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
|
1323
1349
|
return Qnil;
|
|
1324
1350
|
}
|
|
@@ -1449,6 +1475,11 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1449
1475
|
|
|
1450
1476
|
return state->gvl_profiling_hook != NULL ? Qtrue : Qfalse;
|
|
1451
1477
|
}
|
|
1478
|
+
|
|
1479
|
+
static VALUE handle_sampling_failure_rescued_after_gvl_running_from_postponed_job(VALUE self_instance, VALUE exception) {
|
|
1480
|
+
stop(self_instance, exception, "rescued_after_gvl_running_from_postponed_job");
|
|
1481
|
+
return Qnil;
|
|
1482
|
+
}
|
|
1452
1483
|
#else
|
|
1453
1484
|
static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, DDTRACE_UNUSED VALUE instance) {
|
|
1454
1485
|
return Qfalse;
|
|
@@ -1470,11 +1501,50 @@ static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instan
|
|
|
1470
1501
|
return Qnil;
|
|
1471
1502
|
}
|
|
1472
1503
|
|
|
1473
|
-
static VALUE
|
|
1474
|
-
stop(self_instance, exception, "
|
|
1504
|
+
static VALUE handle_sampling_failure_rescued_after_allocation(VALUE self_instance, VALUE exception) {
|
|
1505
|
+
stop(self_instance, exception, "rescued_after_allocation");
|
|
1506
|
+
return Qnil;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
static VALUE rescued_after_allocation(VALUE self_instance) {
|
|
1510
|
+
cpu_and_wall_time_worker_state *state;
|
|
1511
|
+
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1512
|
+
|
|
1513
|
+
thread_context_collector_after_allocation(state->thread_context_collector_instance);
|
|
1514
|
+
|
|
1515
|
+
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
|
1475
1516
|
return Qnil;
|
|
1476
1517
|
}
|
|
1477
1518
|
|
|
1519
|
+
// This postponed job callback is used to finalize heap allocation recordings on Ruby 4+.
|
|
1520
|
+
// During on_newobj_event, calling rb_obj_id() is unsafe because it mutates the object.
|
|
1521
|
+
// So we defer getting the object_id until after the event completes.
|
|
1522
|
+
#pragma GCC diagnostic push
|
|
1523
|
+
#pragma GCC diagnostic ignored "-Wunused-function" // This is only used for some Rubies, but we want to build on all to make it easier to dev
|
|
1524
|
+
static void after_allocation_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
1525
|
+
cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
|
|
1526
|
+
|
|
1527
|
+
if (state == NULL || !ddtrace_rb_ractor_main_p()) return;
|
|
1528
|
+
|
|
1529
|
+
// Protect against nested operations
|
|
1530
|
+
if (state->during_sample) return;
|
|
1531
|
+
|
|
1532
|
+
during_sample_enter(state);
|
|
1533
|
+
|
|
1534
|
+
// NOTE: We're not updating the allocation_sampler here.
|
|
1535
|
+
// This means work done in this function isn't accounted for as profiler overhead.
|
|
1536
|
+
// This is acceptable as the amount of work done here is expected to be small.
|
|
1537
|
+
safely_call(
|
|
1538
|
+
rescued_after_allocation,
|
|
1539
|
+
state->self_instance,
|
|
1540
|
+
state->self_instance,
|
|
1541
|
+
handle_sampling_failure_rescued_after_allocation
|
|
1542
|
+
);
|
|
1543
|
+
|
|
1544
|
+
during_sample_exit(state);
|
|
1545
|
+
}
|
|
1546
|
+
#pragma GCC diagnostic pop
|
|
1547
|
+
|
|
1478
1548
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state) {
|
|
1479
1549
|
// Tell the compiler it's not allowed to reorder the `during_sample` flag with anything that happens after.
|
|
1480
1550
|
//
|
|
@@ -290,11 +290,13 @@ static bool handle_gvl_waiting(
|
|
|
290
290
|
sampling_buffer* sampling_buffer,
|
|
291
291
|
long current_cpu_time_ns
|
|
292
292
|
);
|
|
293
|
-
|
|
294
|
-
static VALUE
|
|
295
|
-
static VALUE
|
|
296
|
-
static VALUE
|
|
297
|
-
static VALUE
|
|
293
|
+
#ifndef NO_GVL_INSTRUMENTATION
|
|
294
|
+
static VALUE _native_on_gvl_waiting(DDTRACE_UNUSED VALUE self, VALUE thread);
|
|
295
|
+
static VALUE _native_gvl_waiting_at_for(DDTRACE_UNUSED VALUE self, VALUE thread);
|
|
296
|
+
static VALUE _native_on_gvl_running(DDTRACE_UNUSED VALUE self, VALUE thread);
|
|
297
|
+
static VALUE _native_sample_after_gvl_running(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE thread, VALUE allow_exception);
|
|
298
|
+
static VALUE _native_apply_delta_to_cpu_time_at_previous_sample_ns(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE thread, VALUE delta_ns);
|
|
299
|
+
#endif
|
|
298
300
|
static void otel_without_ddtrace_trace_identifiers_for(
|
|
299
301
|
thread_context_collector_state *state,
|
|
300
302
|
VALUE thread,
|
|
@@ -1339,6 +1341,16 @@ VALUE enforce_thread_context_collector_instance(VALUE object) {
|
|
|
1339
1341
|
return object;
|
|
1340
1342
|
}
|
|
1341
1343
|
|
|
1344
|
+
// Finalize any pending heap allocation recordings.
|
|
1345
|
+
// On Ruby 4+, heap allocations are recorded in two phases: during on_newobj_event we capture
|
|
1346
|
+
// the object reference, then later we safely call rb_obj_id() to get the object ID.
|
|
1347
|
+
void thread_context_collector_after_allocation(VALUE self_instance) {
|
|
1348
|
+
thread_context_collector_state *state;
|
|
1349
|
+
TypedData_Get_Struct(self_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
|
|
1350
|
+
|
|
1351
|
+
recorder_after_sample(state->recorder_instance);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1342
1354
|
// This method exists only to enable testing Datadog::Profiling::Collectors::ThreadContext behavior using RSpec.
|
|
1343
1355
|
// It SHOULD NOT be used for other purposes.
|
|
1344
1356
|
static VALUE _native_stats(DDTRACE_UNUSED VALUE _self, VALUE collector_instance) {
|
|
@@ -1483,7 +1495,12 @@ bool thread_context_collector_prepare_sample_inside_signal_handler(VALUE self_in
|
|
|
1483
1495
|
return prepare_sample_thread(current_thread, &thread_context->sampling_buffer);
|
|
1484
1496
|
}
|
|
1485
1497
|
|
|
1486
|
-
|
|
1498
|
+
// This method gets called from inside the RUBY_INTERNAL_EVENT_NEWOBJ tracepoint so it should never allocate in the
|
|
1499
|
+
// Ruby heap.
|
|
1500
|
+
//
|
|
1501
|
+
// Returns true if the after_allocation needs to be called (to do work that can't be done from inside the
|
|
1502
|
+
// tracepoint, such as allocate new objects), and false if it doesn't
|
|
1503
|
+
bool thread_context_collector_sample_allocation(VALUE self_instance, unsigned int sample_weight, VALUE new_object) {
|
|
1487
1504
|
thread_context_collector_state *state;
|
|
1488
1505
|
TypedData_Get_Struct(self_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
|
|
1489
1506
|
|
|
@@ -1553,7 +1570,7 @@ void thread_context_collector_sample_allocation(VALUE self_instance, unsigned in
|
|
|
1553
1570
|
class_name = ruby_vm_type; // For other weird internal things we just use the VM type
|
|
1554
1571
|
}
|
|
1555
1572
|
|
|
1556
|
-
track_object(state->recorder_instance, new_object, sample_weight, class_name);
|
|
1573
|
+
bool needs_after_allocation = track_object(state->recorder_instance, new_object, sample_weight, class_name);
|
|
1557
1574
|
|
|
1558
1575
|
per_thread_context *thread_context = get_or_create_context_for(current_thread, state);
|
|
1559
1576
|
|
|
@@ -1570,6 +1587,8 @@ void thread_context_collector_sample_allocation(VALUE self_instance, unsigned in
|
|
|
1570
1587
|
/* is_gvl_waiting_state: */ false,
|
|
1571
1588
|
/* is_safe_to_allocate_objects: */ false // Not safe to allocate further inside the NEWOBJ tracepoint
|
|
1572
1589
|
);
|
|
1590
|
+
|
|
1591
|
+
return needs_after_allocation;
|
|
1573
1592
|
}
|
|
1574
1593
|
|
|
1575
1594
|
// This method exists only to enable testing Datadog::Profiling::Collectors::ThreadContext behavior using RSpec.
|
|
@@ -1577,11 +1596,13 @@ void thread_context_collector_sample_allocation(VALUE self_instance, unsigned in
|
|
|
1577
1596
|
static VALUE _native_sample_allocation(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE sample_weight, VALUE new_object) {
|
|
1578
1597
|
debug_enter_unsafe_context();
|
|
1579
1598
|
|
|
1580
|
-
thread_context_collector_sample_allocation(collector_instance, NUM2UINT(sample_weight), new_object);
|
|
1599
|
+
bool needs_after_allocation = thread_context_collector_sample_allocation(collector_instance, NUM2UINT(sample_weight), new_object);
|
|
1581
1600
|
|
|
1582
1601
|
debug_leave_unsafe_context();
|
|
1583
1602
|
|
|
1584
|
-
|
|
1603
|
+
// We could instead choose to automatically trigger the after allocation here; yet, it seems kinda nice to keep it manual for
|
|
1604
|
+
// the tests so we can pull on each lever separately and observe "the sausage being made" in steps
|
|
1605
|
+
return needs_after_allocation ? Qtrue : Qfalse;
|
|
1585
1606
|
}
|
|
1586
1607
|
|
|
1587
1608
|
static VALUE new_empty_thread_inner(DDTRACE_UNUSED void *arg) { return Qnil; }
|
|
@@ -1799,7 +1820,7 @@ static void otel_without_ddtrace_trace_identifiers_for(
|
|
|
1799
1820
|
VALUE otel_current_span_key = get_otel_current_span_key(state, is_safe_to_allocate_objects);
|
|
1800
1821
|
if (otel_current_span_key == Qnil) return;
|
|
1801
1822
|
|
|
1802
|
-
|
|
1823
|
+
long active_context_index = RARRAY_LEN(context_storage) - 1;
|
|
1803
1824
|
if (active_context_index < 0) return;
|
|
1804
1825
|
|
|
1805
1826
|
otel_span active_span = otel_span_from(rb_ary_entry(context_storage, active_context_index), otel_current_span_key);
|
|
@@ -1808,7 +1829,7 @@ static void otel_without_ddtrace_trace_identifiers_for(
|
|
|
1808
1829
|
otel_span local_root_span = active_span;
|
|
1809
1830
|
|
|
1810
1831
|
// Now find the oldest span starting from the active span that still has the same trace id as the active span
|
|
1811
|
-
for (
|
|
1832
|
+
for (long i = active_context_index - 1; i >= 0; i--) {
|
|
1812
1833
|
otel_span checking_span = otel_span_from(rb_ary_entry(context_storage, i), otel_current_span_key);
|
|
1813
1834
|
if (checking_span.span == Qnil) return;
|
|
1814
1835
|
|
|
@@ -11,13 +11,15 @@ void thread_context_collector_sample(
|
|
|
11
11
|
VALUE profiler_overhead_stack_thread
|
|
12
12
|
);
|
|
13
13
|
__attribute__((warn_unused_result)) bool thread_context_collector_prepare_sample_inside_signal_handler(VALUE self_instance);
|
|
14
|
-
|
|
14
|
+
__attribute__((warn_unused_result)) bool thread_context_collector_sample_allocation(VALUE self_instance, unsigned int sample_weight, VALUE new_object);
|
|
15
|
+
void thread_context_collector_after_allocation(VALUE self_instance);
|
|
15
16
|
void thread_context_collector_sample_skipped_allocation_samples(VALUE self_instance, unsigned int skipped_samples);
|
|
16
17
|
VALUE thread_context_collector_sample_after_gc(VALUE self_instance);
|
|
17
18
|
void thread_context_collector_on_gc_start(VALUE self_instance);
|
|
18
19
|
__attribute__((warn_unused_result)) bool thread_context_collector_on_gc_finish(VALUE self_instance);
|
|
19
20
|
VALUE enforce_thread_context_collector_instance(VALUE object);
|
|
20
21
|
|
|
22
|
+
|
|
21
23
|
#ifndef NO_GVL_INSTRUMENTATION
|
|
22
24
|
typedef enum {
|
|
23
25
|
ON_GVL_RUNNING_UNKNOWN, // Thread is not known, it may not even be from the current Ractor
|
|
@@ -82,7 +82,8 @@ append_cflags "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
|
|
|
82
82
|
# * by upstream Ruby -- search for gnu99 in the codebase
|
|
83
83
|
# * by msgpack, another datadog gem dependency
|
|
84
84
|
# (https://github.com/msgpack/msgpack-ruby/blob/18ce08f6d612fe973843c366ac9a0b74c4e50599/ext/msgpack/extconf.rb#L8)
|
|
85
|
-
|
|
85
|
+
# @ivoanjo: We could probably start using C11/gnu11 for non macOS-too but it's somewhat hard to validate so I chickened out for now
|
|
86
|
+
append_cflags RUBY_PLATFORM.include?('darwin') ? '-std=gnu11' : '-std=gnu99'
|
|
86
87
|
|
|
87
88
|
# Gets really noisy when we include the MJIT header, let's omit it (TODO: Use #pragma GCC diagnostic instead?)
|
|
88
89
|
append_cflags "-Wno-unused-function"
|
|
@@ -144,6 +145,11 @@ $defs << "-DNO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE" if RUBY_VERSION < "4"
|
|
|
144
145
|
# On Ruby 4, we can't ask the object_id from IMEMOs (https://github.com/ruby/ruby/pull/13347)
|
|
145
146
|
$defs << "-DNO_IMEMO_OBJECT_ID" unless RUBY_VERSION < "4"
|
|
146
147
|
|
|
148
|
+
# On Ruby 4, we need to defer calling rb_obj_id during heap allocation recording
|
|
149
|
+
# because it's not safe to mutate objects during the newobj tracepoint
|
|
150
|
+
# (see https://bugs.ruby-lang.org/issues/21710)
|
|
151
|
+
$defs << "-DUSE_DEFERRED_HEAP_ALLOCATION_RECORDING" unless RUBY_VERSION < "4"
|
|
152
|
+
|
|
147
153
|
# This symbol is exclusively visible on certain Ruby versions: 2.6 to 3.2, as well as 3.4 (but not 4.0+)
|
|
148
154
|
# It's only used to get extra information about an object when a failure happens, so it's a "very nice to have" but not
|
|
149
155
|
# actually required for correct behavior of the profiler.
|
|
@@ -205,37 +211,16 @@ $defs << "-DNO_GVL_OWNER" if RUBY_VERSION < "2.6"
|
|
|
205
211
|
$defs << "-DNO_THREAD_INVOKE_ARG" if RUBY_VERSION < "2.6"
|
|
206
212
|
|
|
207
213
|
# If we got here, libdatadog is available and loaded
|
|
208
|
-
ENV["PKG_CONFIG_PATH"] = "#{ENV["PKG_CONFIG_PATH"]}:#{Libdatadog.pkgconfig_folder}"
|
|
209
|
-
Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV["PKG_CONFIG_PATH"].inspect}\n")
|
|
210
214
|
$stderr.puts("Using libdatadog #{Libdatadog::VERSION} from #{Libdatadog.pkgconfig_folder}")
|
|
211
215
|
|
|
212
|
-
unless
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
skip_building_extension!(
|
|
216
|
-
if Datadog::LibdatadogExtconfHelpers.pkg_config_missing?
|
|
217
|
-
Datadog::Profiling::NativeExtensionHelpers::Supported::PKG_CONFIG_IS_MISSING
|
|
218
|
-
else
|
|
219
|
-
# Less specific error message
|
|
220
|
-
Datadog::Profiling::NativeExtensionHelpers::Supported::FAILED_TO_CONFIGURE_LIBDATADOG
|
|
221
|
-
end
|
|
222
|
-
)
|
|
216
|
+
unless Datadog::LibdatadogExtconfHelpers.configure_libdatadog(extconf_folder: __dir__)
|
|
217
|
+
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::FAILED_TO_CONFIGURE_LIBDATADOG)
|
|
223
218
|
end
|
|
224
219
|
|
|
225
220
|
unless have_type("atomic_int", ["stdatomic.h"])
|
|
226
221
|
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
|
|
227
222
|
end
|
|
228
223
|
|
|
229
|
-
# See comments on the helper methods being used for why we need to additionally set this.
|
|
230
|
-
# The extremely excessive escaping around ORIGIN below seems to be correct and was determined after a lot of
|
|
231
|
-
# experimentation. We need to get these special characters across a lot of tools untouched...
|
|
232
|
-
extra_relative_rpaths = [
|
|
233
|
-
Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_native_lib_folder(current_folder: __dir__),
|
|
234
|
-
*Datadog::LibdatadogExtconfHelpers.libdatadog_folder_relative_to_ruby_extensions_folders,
|
|
235
|
-
]
|
|
236
|
-
extra_relative_rpaths.each { |folder| $LDFLAGS += " -Wl,-rpath,$$$\\\\{ORIGIN\\}/#{folder.to_str}" }
|
|
237
|
-
Logging.message("[datadog] After pkg-config $LDFLAGS were set to: #{$LDFLAGS.inspect}\n")
|
|
238
|
-
|
|
239
224
|
# Tag the native extension library with the Ruby version and Ruby platform.
|
|
240
225
|
# This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
|
|
241
226
|
# the wrong library is never loaded.
|