datadog 2.23.0 → 2.28.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 +132 -2
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +2 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +100 -29
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +2 -2
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
- data/ext/datadog_profiling_native_extension/collectors_stack.c +23 -10
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -12
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +48 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +41 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +4 -1
- data/ext/datadog_profiling_native_extension/heap_recorder.c +24 -24
- data/ext/datadog_profiling_native_extension/http_transport.c +10 -4
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +3 -22
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +0 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +21 -8
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
- data/ext/datadog_profiling_native_extension/profiling.c +22 -15
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +55 -44
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +17 -5
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +8 -2
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +3 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +16 -16
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +5 -2
- data/ext/libdatadog_api/crashtracker.c +5 -8
- data/ext/libdatadog_api/datadog_ruby_common.c +48 -1
- data/ext/libdatadog_api/datadog_ruby_common.h +41 -0
- data/ext/libdatadog_api/ddsketch.c +4 -8
- data/ext/libdatadog_api/feature_flags.c +5 -5
- data/ext/libdatadog_api/helpers.h +27 -0
- data/ext/libdatadog_api/init.c +4 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/api_client.rb +82 -0
- data/lib/datadog/ai_guard/component.rb +42 -0
- data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
- data/lib/datadog/ai_guard/configuration/settings.rb +110 -0
- data/lib/datadog/ai_guard/configuration.rb +11 -0
- data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +42 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +34 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +81 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +43 -0
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
- data/lib/datadog/ai_guard/evaluation.rb +72 -0
- data/lib/datadog/ai_guard/ext.rb +16 -0
- data/lib/datadog/ai_guard.rb +155 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +8 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +9 -2
- data/lib/datadog/appsec/component.rb +1 -1
- data/lib/datadog/appsec/context.rb +5 -4
- data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +47 -12
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +32 -15
- data/lib/datadog/appsec/contrib/rails/patcher.rb +10 -2
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +50 -14
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +5 -4
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +4 -4
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +1 -1
- data/lib/datadog/appsec/ext.rb +2 -0
- data/lib/datadog/appsec/metrics/collector.rb +8 -3
- data/lib/datadog/appsec/metrics/exporter.rb +7 -0
- data/lib/datadog/appsec/metrics/telemetry.rb +7 -2
- data/lib/datadog/appsec/metrics.rb +5 -5
- data/lib/datadog/appsec/remote.rb +7 -14
- data/lib/datadog/appsec/security_engine/engine.rb +3 -3
- data/lib/datadog/appsec/security_engine/result.rb +2 -1
- data/lib/datadog/appsec/security_engine/runner.rb +2 -2
- data/lib/datadog/appsec/utils/http/media_type.rb +37 -23
- data/lib/datadog/appsec.rb +7 -1
- data/lib/datadog/core/configuration/components.rb +7 -0
- data/lib/datadog/core/configuration/config_helper.rb +1 -1
- data/lib/datadog/core/configuration/deprecations.rb +2 -2
- data/lib/datadog/core/configuration/option_definition.rb +4 -2
- data/lib/datadog/core/configuration/options.rb +8 -5
- data/lib/datadog/core/configuration/settings.rb +31 -3
- data/lib/datadog/core/configuration/supported_configurations.rb +10 -1
- data/lib/datadog/core/crashtracking/tag_builder.rb +6 -0
- data/lib/datadog/core/environment/cgroup.rb +52 -25
- data/lib/datadog/core/environment/container.rb +140 -46
- data/lib/datadog/core/environment/ext.rb +1 -0
- data/lib/datadog/core/environment/process.rb +9 -1
- data/lib/datadog/core/error.rb +6 -6
- data/lib/datadog/core/knuth_sampler.rb +57 -0
- data/lib/datadog/core/pin.rb +4 -0
- data/lib/datadog/core/rate_limiter.rb +9 -1
- data/lib/datadog/core/remote/client.rb +14 -6
- data/lib/datadog/core/remote/component.rb +6 -4
- data/lib/datadog/core/remote/configuration/content.rb +15 -2
- data/lib/datadog/core/remote/configuration/digest.rb +14 -7
- data/lib/datadog/core/remote/configuration/repository.rb +1 -1
- data/lib/datadog/core/remote/configuration/target.rb +13 -6
- data/lib/datadog/core/remote/transport/config.rb +3 -16
- data/lib/datadog/core/remote/transport/http/config.rb +4 -44
- data/lib/datadog/core/remote/transport/http/negotiation.rb +0 -39
- data/lib/datadog/core/remote/transport/http.rb +13 -24
- data/lib/datadog/core/remote/transport/negotiation.rb +7 -16
- data/lib/datadog/core/runtime/metrics.rb +11 -1
- data/lib/datadog/core/semaphore.rb +1 -4
- data/lib/datadog/core/telemetry/component.rb +52 -13
- data/lib/datadog/core/telemetry/event/app_started.rb +36 -1
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
- data/lib/datadog/core/telemetry/logger.rb +2 -0
- data/lib/datadog/core/telemetry/logging.rb +20 -2
- data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
- data/lib/datadog/core/telemetry/request.rb +17 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -32
- data/lib/datadog/core/telemetry/transport/http.rb +21 -16
- data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -10
- data/lib/datadog/core/telemetry/worker.rb +88 -32
- data/lib/datadog/core/transport/ext.rb +2 -0
- data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
- data/lib/datadog/core/transport/http/api/instance.rb +4 -21
- data/lib/datadog/core/transport/http/builder.rb +9 -5
- data/lib/datadog/core/transport/http/client.rb +19 -8
- data/lib/datadog/core/transport/http.rb +22 -19
- data/lib/datadog/core/transport/response.rb +12 -1
- data/lib/datadog/core/transport/transport.rb +90 -0
- data/lib/datadog/core/utils/only_once_successful.rb +2 -0
- data/lib/datadog/core/utils/safe_dup.rb +2 -2
- data/lib/datadog/core/utils/sequence.rb +2 -0
- data/lib/datadog/core/utils/time.rb +1 -1
- data/lib/datadog/core/workers/async.rb +10 -1
- data/lib/datadog/core/workers/interval_loop.rb +44 -3
- data/lib/datadog/core/workers/polling.rb +2 -0
- data/lib/datadog/core/workers/queue.rb +100 -1
- data/lib/datadog/data_streams/processor.rb +1 -1
- data/lib/datadog/data_streams/transport/http/stats.rb +1 -36
- data/lib/datadog/data_streams/transport/http.rb +5 -6
- data/lib/datadog/data_streams/transport/stats.rb +3 -17
- data/lib/datadog/di/boot.rb +4 -2
- data/lib/datadog/di/configuration/settings.rb +22 -0
- data/lib/datadog/di/contrib/active_record.rb +30 -5
- data/lib/datadog/di/el/compiler.rb +8 -4
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +26 -7
- data/lib/datadog/di/logger.rb +2 -2
- data/lib/datadog/di/probe_builder.rb +2 -1
- data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
- data/lib/datadog/di/probe_manager.rb +37 -31
- data/lib/datadog/di/probe_notification_builder.rb +15 -2
- data/lib/datadog/di/probe_notifier_worker.rb +5 -5
- data/lib/datadog/di/redactor.rb +8 -1
- data/lib/datadog/di/remote.rb +89 -84
- data/lib/datadog/di/transport/diagnostics.rb +7 -35
- data/lib/datadog/di/transport/http/diagnostics.rb +1 -31
- data/lib/datadog/di/transport/http/input.rb +1 -31
- data/lib/datadog/di/transport/http.rb +28 -17
- data/lib/datadog/di/transport/input.rb +7 -34
- data/lib/datadog/di.rb +61 -5
- data/lib/datadog/error_tracking/filters.rb +2 -2
- data/lib/datadog/kit/appsec/events/v2.rb +2 -3
- data/lib/datadog/open_feature/evaluation_engine.rb +2 -1
- data/lib/datadog/open_feature/remote.rb +3 -10
- data/lib/datadog/open_feature/transport.rb +9 -11
- data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +2 -2
- data/lib/datadog/opentelemetry/metrics.rb +21 -14
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +5 -8
- data/lib/datadog/profiling/collectors/code_provenance.rb +27 -2
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -2
- data/lib/datadog/profiling/collectors/info.rb +5 -4
- data/lib/datadog/profiling/component.rb +25 -11
- data/lib/datadog/profiling/exporter.rb +4 -0
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +18 -0
- data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
- data/lib/datadog/profiling/flush.rb +3 -0
- data/lib/datadog/profiling/http_transport.rb +4 -1
- data/lib/datadog/profiling/profiler.rb +3 -5
- data/lib/datadog/profiling/scheduler.rb +8 -7
- data/lib/datadog/profiling/tag_builder.rb +1 -0
- data/lib/datadog/tracing/contrib/extensions.rb +10 -2
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +31 -32
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +2 -1
- data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +6 -3
- data/lib/datadog/tracing/contrib/waterdrop.rb +4 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -2
- data/lib/datadog/tracing/remote.rb +1 -9
- data/lib/datadog/tracing/sampling/priority_sampler.rb +3 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
- data/lib/datadog/tracing/span.rb +1 -1
- data/lib/datadog/tracing/span_event.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +20 -9
- data/lib/datadog/tracing/trace_operation.rb +44 -6
- data/lib/datadog/tracing/tracer.rb +42 -16
- data/lib/datadog/tracing/transport/http/traces.rb +2 -50
- data/lib/datadog/tracing/transport/http.rb +15 -9
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/transport/traces.rb +6 -66
- data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
- data/lib/datadog/tracing/writer.rb +1 -0
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +1 -0
- metadata +33 -19
- data/lib/datadog/core/remote/transport/http/api.rb +0 -53
- data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
- data/lib/datadog/core/transport/http/api/spec.rb +0 -36
- data/lib/datadog/data_streams/transport/http/api.rb +0 -33
- data/lib/datadog/data_streams/transport/http/client.rb +0 -21
- data/lib/datadog/di/transport/http/api.rb +0 -42
- data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
- data/lib/datadog/tracing/transport/http/api.rb +0 -44
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 91ec2ddb3720f61843ee7526cd4e3493a646ab7afaf3d6e4cce71019d1dfd582
|
|
4
|
+
data.tar.gz: d0996f8b1eb568aea751a1e781fa4d9dcc7e1d436911fd579c7aa43947340f32
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fb8da926cd9a09a500c781f60ad5fb35c72c9b3162acc067229f88d01281c63c6753c4230a2cf56f803fb0174994707b159e31f5d584e6682313a13e2187b61e
|
|
7
|
+
data.tar.gz: 8c93304f737b5798af5d6ed520f7006d7aa2e7644243fbfcd38994d66dde0aefb53084bca96024e61a7cbebcb72e60f958715fe4864c1e7fe90733103f9cb527
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,100 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.28.0] - 2026-02-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* AI Guard: Add instrumentation for `ruby_llm` gem. ([#5273][])
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
* Core: Bump minimum version of datadog-ruby_core_source to 3.5.2 ([#5278][])
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
* AppSec: Fix exception in Rails contrib `:after_routes_loaded` hook when routes are reloaded. ([#5283][])
|
|
18
|
+
|
|
19
|
+
## [2.27.0] - 2026-01-21
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
* AppSec: Add analysis of the downstream requests ([#5206][])
|
|
24
|
+
* Telemetry: Add static error reporting for native extensions ([#5076][])
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
* SSI: Update injector to v1.2.1 ([#5254][])
|
|
29
|
+
* SSI: Prepare for expanded platform support ([#5254][])
|
|
30
|
+
* SSI: Improve remote resolution with expanded platform support via fallback to local gems ([#5254][])
|
|
31
|
+
* SSI: Introduce experimental fully local resolution support ([#5254][])
|
|
32
|
+
* Profiling: Telemetry-safe error reporting for native extensions ([#5076][])
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
* Profiler: Fix interrupting new processes with the message `Profiling timer expired` during `exec` ([#5246][])
|
|
38
|
+
* Profiler: Fix rare race in profiler causing flaky spec on Ruby 2.7 ([#5247][])
|
|
39
|
+
* Appsec: Fix reporting of multi-method routes for Endpoint Collection ([#5240][])
|
|
40
|
+
* AppSec: Fix reporting of Rails routes that accept multiple request methods. ([#5240][])
|
|
41
|
+
|
|
42
|
+
## [2.26.0] - 2026-01-16
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
* Core: Add process tags to runtime metrics when `DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED` is enabled. ([#5210][])
|
|
47
|
+
* SSI: Add experimental dependency injection validation.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
* Profiling: Improve profiler error reporting. ([#5237][])
|
|
52
|
+
* SSI: Improve injection debug error reporting. ([#5238][])
|
|
53
|
+
|
|
54
|
+
## [2.25.0] - 2026-01-13
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
AI Guard: Add SDK for evaluating the safety of user messages and assistant commands for LLM session ([#5144][])
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
Core: Bump minimum version of `datadog-ruby_core_source` dependency ([#5215][])
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
AppSec: Fix processing of numeric data for WAF and RASP checks ([#5222][])
|
|
67
|
+
|
|
68
|
+
## [2.24.0] - 2026-01-08
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
* Core: Add support for installing the gem on Ruby 4.0.x stable ([#5157][])
|
|
73
|
+
* Tracing: Add origin detection using extra headers and the `DD_EXTERNAL_ENV` variable. ([#5028][])
|
|
74
|
+
* Dynamic Instrumentation: Add one-click enablement support ([#5150][])
|
|
75
|
+
* SSI: Add support for Bundler deployment mode ([#5053][])
|
|
76
|
+
* SSI: Report UI-oriented injection results ([#5053][])
|
|
77
|
+
* SSI: Guard against Bundler global force_ruby_platform ([#5053][])
|
|
78
|
+
* SSI: Guard against Bundler 4.0 and Bundler 2.7 in 4.0 mode ([#5053][])
|
|
79
|
+
* SSI: Guard against Ruby 3.5+ ([#5053][])
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
* Profiling: Remove profiler warning related to the Ractor issue ([#5194][])
|
|
84
|
+
* Profiling: Disable heap profiling on Ruby 4 due to incompatibility ([#5148][])
|
|
85
|
+
* Dynamic Instrumentation: Stop using customer-provided time provider for method duration calculation ([#5153][])
|
|
86
|
+
* Live Debugger / Dynamic Instrumentation: Improve probe instrumentation ([#5165][])
|
|
87
|
+
* Live Debugger / Dynamic Instrumentation: Improve instrumentation reliability for probes ([#5169][])
|
|
88
|
+
|
|
89
|
+
### Fixed
|
|
90
|
+
|
|
91
|
+
* Core: Improve reliability of worker shutdown ([#5176][])
|
|
92
|
+
* Core: Fix RDoc error when installing the `datadog` gem ([#5145][])
|
|
93
|
+
* Tracing: Ensure `Tracing.continue_from!` keeps the active trace for the full block duration. ([#4941][])
|
|
94
|
+
* Profiling: Fix and refine profiler thread state categorization for Ruby 4 ([#5197][])
|
|
95
|
+
* Profiling: Fix profiler error triggering `Bundler::PermissionError` ([#5146][])
|
|
96
|
+
* Live Debugger / Dynamic Instrumentation: Fix Live Debugger and Dynamic Instrumentation UI for forking web servers ([#5159][])
|
|
97
|
+
* Live Debugger / Dynamic Instrumentation: Fix method probe leak when a referenced class loads after the probe reaches the application ([#5168][])
|
|
98
|
+
|
|
5
99
|
## [2.23.0] - 2025-12-11
|
|
6
100
|
|
|
7
101
|
### Added
|
|
@@ -3392,7 +3486,12 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3392
3486
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3393
3487
|
|
|
3394
3488
|
|
|
3395
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3489
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.28.0...master
|
|
3490
|
+
[2.28.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.27.0...v2.28.0
|
|
3491
|
+
[2.27.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.26.0...v2.27.0
|
|
3492
|
+
[2.26.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.25.0...v2.26.0
|
|
3493
|
+
[2.25.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.24.0...v2.25.0
|
|
3494
|
+
[2.24.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.23.0...v2.24.0
|
|
3396
3495
|
[2.23.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.22.0...v2.23.0
|
|
3397
3496
|
[2.22.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.21.0...v2.22.0
|
|
3398
3497
|
[2.21.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.20.0...v2.21.0
|
|
@@ -5010,6 +5109,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5010
5109
|
[#4914]: https://github.com/DataDog/dd-trace-rb/issues/4914
|
|
5011
5110
|
[#4918]: https://github.com/DataDog/dd-trace-rb/issues/4918
|
|
5012
5111
|
[#4919]: https://github.com/DataDog/dd-trace-rb/issues/4919
|
|
5112
|
+
[#4941]: https://github.com/DataDog/dd-trace-rb/issues/4941
|
|
5013
5113
|
[#4957]: https://github.com/DataDog/dd-trace-rb/issues/4957
|
|
5014
5114
|
[#4965]: https://github.com/DataDog/dd-trace-rb/issues/4965
|
|
5015
5115
|
[#4969]: https://github.com/DataDog/dd-trace-rb/issues/4969
|
|
@@ -5024,18 +5124,48 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5024
5124
|
[#5021]: https://github.com/DataDog/dd-trace-rb/issues/5021
|
|
5025
5125
|
[#5024]: https://github.com/DataDog/dd-trace-rb/issues/5024
|
|
5026
5126
|
[#5025]: https://github.com/DataDog/dd-trace-rb/issues/5025
|
|
5127
|
+
[#5028]: https://github.com/DataDog/dd-trace-rb/issues/5028
|
|
5027
5128
|
[#5031]: https://github.com/DataDog/dd-trace-rb/issues/5031
|
|
5028
5129
|
[#5033]: https://github.com/DataDog/dd-trace-rb/issues/5033
|
|
5029
5130
|
[#5042]: https://github.com/DataDog/dd-trace-rb/issues/5042
|
|
5030
5131
|
[#5044]: https://github.com/DataDog/dd-trace-rb/issues/5044
|
|
5031
5132
|
[#5045]: https://github.com/DataDog/dd-trace-rb/issues/5045
|
|
5032
5133
|
[#5049]: https://github.com/DataDog/dd-trace-rb/issues/5049
|
|
5134
|
+
[#5053]: https://github.com/DataDog/dd-trace-rb/issues/5053
|
|
5033
5135
|
[#5054]: https://github.com/DataDog/dd-trace-rb/issues/5054
|
|
5034
5136
|
[#5058]: https://github.com/DataDog/dd-trace-rb/issues/5058
|
|
5035
5137
|
[#5073]: https://github.com/DataDog/dd-trace-rb/issues/5073
|
|
5138
|
+
[#5076]: https://github.com/DataDog/dd-trace-rb/issues/5076
|
|
5036
5139
|
[#5086]: https://github.com/DataDog/dd-trace-rb/issues/5086
|
|
5037
5140
|
[#5091]: https://github.com/DataDog/dd-trace-rb/issues/5091
|
|
5038
5141
|
[#5122]: https://github.com/DataDog/dd-trace-rb/issues/5122
|
|
5142
|
+
[#5144]: https://github.com/DataDog/dd-trace-rb/issues/5144
|
|
5143
|
+
[#5145]: https://github.com/DataDog/dd-trace-rb/issues/5145
|
|
5144
|
+
[#5146]: https://github.com/DataDog/dd-trace-rb/issues/5146
|
|
5145
|
+
[#5148]: https://github.com/DataDog/dd-trace-rb/issues/5148
|
|
5146
|
+
[#5150]: https://github.com/DataDog/dd-trace-rb/issues/5150
|
|
5147
|
+
[#5153]: https://github.com/DataDog/dd-trace-rb/issues/5153
|
|
5148
|
+
[#5157]: https://github.com/DataDog/dd-trace-rb/issues/5157
|
|
5149
|
+
[#5159]: https://github.com/DataDog/dd-trace-rb/issues/5159
|
|
5150
|
+
[#5165]: https://github.com/DataDog/dd-trace-rb/issues/5165
|
|
5151
|
+
[#5168]: https://github.com/DataDog/dd-trace-rb/issues/5168
|
|
5152
|
+
[#5169]: https://github.com/DataDog/dd-trace-rb/issues/5169
|
|
5153
|
+
[#5176]: https://github.com/DataDog/dd-trace-rb/issues/5176
|
|
5154
|
+
[#5194]: https://github.com/DataDog/dd-trace-rb/issues/5194
|
|
5155
|
+
[#5197]: https://github.com/DataDog/dd-trace-rb/issues/5197
|
|
5156
|
+
[#5206]: https://github.com/DataDog/dd-trace-rb/issues/5206
|
|
5157
|
+
[#5210]: https://github.com/DataDog/dd-trace-rb/issues/5210
|
|
5158
|
+
[#5215]: https://github.com/DataDog/dd-trace-rb/issues/5215
|
|
5159
|
+
[#5222]: https://github.com/DataDog/dd-trace-rb/issues/5222
|
|
5160
|
+
[#5237]: https://github.com/DataDog/dd-trace-rb/issues/5237
|
|
5161
|
+
[#5238]: https://github.com/DataDog/dd-trace-rb/issues/5238
|
|
5162
|
+
[#5240]: https://github.com/DataDog/dd-trace-rb/issues/5240
|
|
5163
|
+
[#5246]: https://github.com/DataDog/dd-trace-rb/issues/5246
|
|
5164
|
+
[#5247]: https://github.com/DataDog/dd-trace-rb/issues/5247
|
|
5165
|
+
[#5254]: https://github.com/DataDog/dd-trace-rb/issues/5254
|
|
5166
|
+
[#5273]: https://github.com/DataDog/dd-trace-rb/issues/5273
|
|
5167
|
+
[#5278]: https://github.com/DataDog/dd-trace-rb/issues/5278
|
|
5168
|
+
[#5283]: https://github.com/DataDog/dd-trace-rb/issues/5283
|
|
5039
5169
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5040
5170
|
[@Azure7111]: https://github.com/Azure7111
|
|
5041
5171
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -5190,4 +5320,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5190
5320
|
[@y-yagi]: https://github.com/y-yagi
|
|
5191
5321
|
[@yujideveloper]: https://github.com/yujideveloper
|
|
5192
5322
|
[@yukimurasawa]: https://github.com/yukimurasawa
|
|
5193
|
-
[@zachmccormick]: https://github.com/zachmccormick
|
|
5323
|
+
[@zachmccormick]: https://github.com/zachmccormick
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include "clock_id.h"
|
|
12
12
|
#include "helpers.h"
|
|
13
13
|
#include "private_vm_api_access.h"
|
|
14
|
+
#include "ruby_helpers.h"
|
|
14
15
|
#include "time_helpers.h"
|
|
15
16
|
|
|
16
17
|
// Validate that our home-cooked pthread_id_for() matches pthread_self() for the current thread
|
|
@@ -18,7 +19,7 @@ void self_test_clock_id(void) {
|
|
|
18
19
|
rb_nativethread_id_t expected_pthread_id = pthread_self();
|
|
19
20
|
rb_nativethread_id_t actual_pthread_id = pthread_id_for(rb_thread_current());
|
|
20
21
|
|
|
21
|
-
if (expected_pthread_id != actual_pthread_id)
|
|
22
|
+
if (expected_pthread_id != actual_pthread_id) raise_error(rb_eRuntimeError, "pthread_id_for() self-test failed");
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// Safety: This function is assumed never to raise exceptions by callers
|
|
@@ -76,8 +76,6 @@
|
|
|
76
76
|
//
|
|
77
77
|
// ---
|
|
78
78
|
|
|
79
|
-
#define ERR_CLOCK_FAIL "failed to get clock time"
|
|
80
|
-
|
|
81
79
|
// Maximum allowed value for an allocation weight. Attempts to use higher values will result in clamping.
|
|
82
80
|
// See https://docs.google.com/document/d/1lWLB714wlLBBq6T4xZyAc4a5wtWhSmr4-hgiPKeErlA/edit#heading=h.ugp0zxcj5iqh
|
|
83
81
|
// (Datadog-only link) for research backing the choice of this value.
|
|
@@ -117,6 +115,7 @@ typedef struct {
|
|
|
117
115
|
// When something goes wrong during sampling, we record the Ruby exception here, so that it can be "re-raised" on
|
|
118
116
|
// the CpuAndWallTimeWorker thread
|
|
119
117
|
VALUE failure_exception;
|
|
118
|
+
const char *failure_exception_during_operation;
|
|
120
119
|
// Used by `_native_stop` to flag the worker thread to start (see comment on `_native_sampling_loop`)
|
|
121
120
|
VALUE stop_thread;
|
|
122
121
|
|
|
@@ -191,17 +190,17 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
191
190
|
static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
|
|
192
191
|
static VALUE _native_sampling_loop(VALUE self, VALUE instance);
|
|
193
192
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread);
|
|
194
|
-
static VALUE stop(VALUE self_instance, VALUE optional_exception);
|
|
195
|
-
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception);
|
|
193
|
+
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation);
|
|
194
|
+
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception, const char *optional_operation_name);
|
|
196
195
|
static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
|
|
197
196
|
static void *run_sampling_trigger_loop(void *state_ptr);
|
|
198
197
|
static void interrupt_sampling_trigger_loop(void *state_ptr);
|
|
199
198
|
static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
200
199
|
static VALUE rescued_sample_from_postponed_job(VALUE self_instance);
|
|
201
|
-
static VALUE handle_sampling_failure(VALUE self_instance, VALUE exception);
|
|
202
200
|
static VALUE _native_current_sigprof_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
203
201
|
static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance);
|
|
204
202
|
static VALUE _native_is_running(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
203
|
+
static VALUE _native_failure_exception_during_operation(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
205
204
|
static void testing_signal_handler(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
|
|
206
205
|
static VALUE _native_install_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
207
206
|
static VALUE _native_remove_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
@@ -209,7 +208,12 @@ static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self);
|
|
|
209
208
|
static VALUE _native_gc_tracepoint(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
210
209
|
static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused);
|
|
211
210
|
static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
212
|
-
static VALUE safely_call(
|
|
211
|
+
static VALUE safely_call(
|
|
212
|
+
VALUE (*function_to_call_safely)(VALUE),
|
|
213
|
+
VALUE function_to_call_safely_arg,
|
|
214
|
+
VALUE instance,
|
|
215
|
+
VALUE (*handle_sampling_failure)(VALUE, VALUE)
|
|
216
|
+
);
|
|
213
217
|
static VALUE _native_simulate_handle_sampling_signal(DDTRACE_UNUSED VALUE self);
|
|
214
218
|
static VALUE _native_simulate_sample_from_postponed_job(DDTRACE_UNUSED VALUE self);
|
|
215
219
|
static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
@@ -226,6 +230,7 @@ static void disable_tracepoints(cpu_and_wall_time_worker_state *state);
|
|
|
226
230
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
|
|
227
231
|
static VALUE rescued_sample_allocation(VALUE tracepoint_data);
|
|
228
232
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
|
|
233
|
+
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state);
|
|
229
234
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
|
|
230
235
|
static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
|
|
231
236
|
static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
|
@@ -235,6 +240,10 @@ static void after_gvl_running_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
|
235
240
|
#endif
|
|
236
241
|
static VALUE rescued_after_gvl_running_from_postponed_job(VALUE self_instance);
|
|
237
242
|
static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
243
|
+
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
244
|
+
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception);
|
|
245
|
+
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception);
|
|
246
|
+
static VALUE handle_sampling_failure_rescued_after_gvl_running_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
238
247
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state);
|
|
239
248
|
static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
240
249
|
|
|
@@ -262,6 +271,7 @@ static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
|
262
271
|
// (e.g. signal handler) where it's impossible or just awkward to pass it as an argument.
|
|
263
272
|
static VALUE active_sampler_instance = Qnil;
|
|
264
273
|
static cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
|
|
274
|
+
static VALUE clock_failure_exception_class = Qnil;
|
|
265
275
|
|
|
266
276
|
// See handle_sampling_signal for details on what this does
|
|
267
277
|
#ifdef NO_POSTPONED_TRIGGER
|
|
@@ -289,7 +299,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
289
299
|
after_gc_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
290
300
|
after_gvl_running_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID
|
|
291
301
|
) {
|
|
292
|
-
|
|
302
|
+
raise_error(rb_eRuntimeError, "Failed to register profiler postponed jobs (got POSTPONED_JOB_HANDLE_INVALID)");
|
|
293
303
|
}
|
|
294
304
|
#else
|
|
295
305
|
gc_finalize_deferred_workaround = objspace_ptr_for_gc_finalize_deferred_workaround();
|
|
@@ -299,6 +309,8 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
299
309
|
VALUE collectors_cpu_and_wall_time_worker_class = rb_define_class_under(collectors_module, "CpuAndWallTimeWorker", rb_cObject);
|
|
300
310
|
// Hosts methods used for testing the native code using RSpec
|
|
301
311
|
VALUE testing_module = rb_define_module_under(collectors_cpu_and_wall_time_worker_class, "Testing");
|
|
312
|
+
clock_failure_exception_class = rb_define_class_under(collectors_cpu_and_wall_time_worker_class, "ClockFailure", rb_eRuntimeError);
|
|
313
|
+
rb_gc_register_mark_object(clock_failure_exception_class);
|
|
302
314
|
|
|
303
315
|
// Instances of the CpuAndWallTimeWorker class are "TypedData" objects.
|
|
304
316
|
// "TypedData" objects are special objects in the Ruby VM that can wrap C structs.
|
|
@@ -318,6 +330,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
318
330
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stats_reset_not_thread_safe", _native_stats_reset_not_thread_safe, 1);
|
|
319
331
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_allocation_count", _native_allocation_count, 0);
|
|
320
332
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_is_running?", _native_is_running, 1);
|
|
333
|
+
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_failure_exception_during_operation", _native_failure_exception_during_operation, 1);
|
|
321
334
|
rb_define_singleton_method(testing_module, "_native_current_sigprof_signal_handler", _native_current_sigprof_signal_handler, 0);
|
|
322
335
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_hold_signals", _native_hold_signals, 0);
|
|
323
336
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_resume_signals", _native_resume_signals, 0);
|
|
@@ -370,6 +383,7 @@ static VALUE _native_new(VALUE klass) {
|
|
|
370
383
|
|
|
371
384
|
atomic_init(&state->should_run, false);
|
|
372
385
|
state->failure_exception = Qnil;
|
|
386
|
+
state->failure_exception_during_operation = NULL;
|
|
373
387
|
state->stop_thread = Qnil;
|
|
374
388
|
|
|
375
389
|
during_sample_exit(state);
|
|
@@ -472,10 +486,7 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
472
486
|
cpu_and_wall_time_worker_state *old_state = active_sampler_instance_state;
|
|
473
487
|
if (old_state != NULL) {
|
|
474
488
|
if (is_thread_alive(old_state->owner_thread)) {
|
|
475
|
-
|
|
476
|
-
rb_eRuntimeError,
|
|
477
|
-
"Could not start CpuAndWallTimeWorker: There's already another instance of CpuAndWallTimeWorker active in a different thread"
|
|
478
|
-
);
|
|
489
|
+
raise_error(rb_eRuntimeError, "Could not start CpuAndWallTimeWorker: There's already another instance of CpuAndWallTimeWorker active in a different thread");
|
|
479
490
|
} else {
|
|
480
491
|
// The previously active thread seems to have died without cleaning up after itself.
|
|
481
492
|
// In this case, we can still go ahead and start the profiler BUT we make sure to disable any existing tracepoint
|
|
@@ -554,22 +565,24 @@ static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE
|
|
|
554
565
|
|
|
555
566
|
state->stop_thread = worker_thread;
|
|
556
567
|
|
|
557
|
-
return stop(self_instance,
|
|
568
|
+
return stop(self_instance, Qnil, NULL);
|
|
558
569
|
}
|
|
559
570
|
|
|
560
|
-
|
|
571
|
+
// When providing an `optional_exception`, `optional_exception_during_operation` should be provided as well
|
|
572
|
+
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception, const char *optional_exception_during_operation) {
|
|
561
573
|
atomic_store(&state->should_run, false);
|
|
562
574
|
state->failure_exception = optional_exception;
|
|
575
|
+
state->failure_exception_during_operation = optional_exception_during_operation;
|
|
563
576
|
|
|
564
577
|
// Disable the tracepoints as soon as possible, so the VM doesn't keep on calling them
|
|
565
578
|
disable_tracepoints(state);
|
|
566
579
|
}
|
|
567
580
|
|
|
568
|
-
static VALUE stop(VALUE self_instance, VALUE optional_exception) {
|
|
581
|
+
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation) {
|
|
569
582
|
cpu_and_wall_time_worker_state *state;
|
|
570
583
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
571
584
|
|
|
572
|
-
stop_state(state, optional_exception);
|
|
585
|
+
stop_state(state, optional_exception, optional_exception_during_operation);
|
|
573
586
|
|
|
574
587
|
return Qtrue;
|
|
575
588
|
}
|
|
@@ -669,6 +682,10 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
|
669
682
|
// we're doing this, so we may still not signal the correct thread from time to time, but our signal handler
|
|
670
683
|
// includes a check to see if it got called in the right thread
|
|
671
684
|
state->stats.interrupt_thread_attempts++;
|
|
685
|
+
|
|
686
|
+
// Pick up any last-minute attempts to stop before we send the signal
|
|
687
|
+
if (!atomic_load(&state->should_run)) return NULL;
|
|
688
|
+
|
|
672
689
|
pthread_kill(owner.owner, SIGPROF);
|
|
673
690
|
} else {
|
|
674
691
|
if (state->skip_idle_samples_for_testing) {
|
|
@@ -726,7 +743,12 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
726
743
|
during_sample_enter(state);
|
|
727
744
|
|
|
728
745
|
// Rescue against any exceptions that happen during sampling
|
|
729
|
-
safely_call(
|
|
746
|
+
safely_call(
|
|
747
|
+
rescued_sample_from_postponed_job,
|
|
748
|
+
state->self_instance,
|
|
749
|
+
state->self_instance,
|
|
750
|
+
handle_sampling_failure_rescued_sample_from_postponed_job
|
|
751
|
+
);
|
|
730
752
|
|
|
731
753
|
during_sample_exit(state);
|
|
732
754
|
}
|
|
@@ -763,11 +785,6 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
|
763
785
|
return Qnil;
|
|
764
786
|
}
|
|
765
787
|
|
|
766
|
-
static VALUE handle_sampling_failure(VALUE self_instance, VALUE exception) {
|
|
767
|
-
stop(self_instance, exception);
|
|
768
|
-
return Qnil;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
788
|
// This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
|
|
772
789
|
// It SHOULD NOT be used for other purposes.
|
|
773
790
|
static VALUE _native_current_sigprof_signal_handler(DDTRACE_UNUSED VALUE self) {
|
|
@@ -821,7 +838,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
|
821
838
|
NULL
|
|
822
839
|
);
|
|
823
840
|
#else
|
|
824
|
-
|
|
841
|
+
raise_error(rb_eArgError, "GVL profiling is not supported in this Ruby version");
|
|
825
842
|
#endif
|
|
826
843
|
}
|
|
827
844
|
|
|
@@ -844,6 +861,15 @@ static VALUE _native_is_running(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
|
844
861
|
return (state != NULL && is_thread_alive(state->owner_thread) && state->self_instance == instance) ? Qtrue : Qfalse;
|
|
845
862
|
}
|
|
846
863
|
|
|
864
|
+
static VALUE _native_failure_exception_during_operation(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
865
|
+
cpu_and_wall_time_worker_state *state;
|
|
866
|
+
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
867
|
+
|
|
868
|
+
if (state->failure_exception_during_operation == NULL) return Qnil;
|
|
869
|
+
|
|
870
|
+
return rb_str_new_cstr(state->failure_exception_during_operation);
|
|
871
|
+
}
|
|
872
|
+
|
|
847
873
|
static void testing_signal_handler(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext) {
|
|
848
874
|
/* Does nothing on purpose */
|
|
849
875
|
}
|
|
@@ -936,14 +962,24 @@ static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
936
962
|
|
|
937
963
|
during_sample_enter(state);
|
|
938
964
|
|
|
939
|
-
safely_call(
|
|
965
|
+
safely_call(
|
|
966
|
+
thread_context_collector_sample_after_gc,
|
|
967
|
+
state->thread_context_collector_instance,
|
|
968
|
+
state->self_instance,
|
|
969
|
+
handle_sampling_failure_thread_context_collector_sample_after_gc
|
|
970
|
+
);
|
|
940
971
|
|
|
941
972
|
during_sample_exit(state);
|
|
942
973
|
}
|
|
943
974
|
|
|
944
975
|
// Equivalent to Ruby begin/rescue call, where we call a C function and jump to the exception handler if an
|
|
945
976
|
// exception gets raised within
|
|
946
|
-
static VALUE safely_call(
|
|
977
|
+
static VALUE safely_call(
|
|
978
|
+
VALUE (*function_to_call_safely)(VALUE),
|
|
979
|
+
VALUE function_to_call_safely_arg,
|
|
980
|
+
VALUE instance,
|
|
981
|
+
VALUE (*handle_sampling_failure)(VALUE, VALUE)
|
|
982
|
+
) {
|
|
947
983
|
VALUE exception_handler_function_arg = instance;
|
|
948
984
|
return rb_rescue2(
|
|
949
985
|
function_to_call_safely,
|
|
@@ -1119,7 +1155,7 @@ static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
|
|
|
1119
1155
|
#define HANDLE_CLOCK_FAILURE(call) ({ \
|
|
1120
1156
|
long _result = (call); \
|
|
1121
1157
|
if (_result == 0) { \
|
|
1122
|
-
|
|
1158
|
+
delayed_error_clock_failure(state); \
|
|
1123
1159
|
return; \
|
|
1124
1160
|
} \
|
|
1125
1161
|
_result; \
|
|
@@ -1203,12 +1239,17 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1203
1239
|
during_sample_enter(state);
|
|
1204
1240
|
|
|
1205
1241
|
// Rescue against any exceptions that happen during sampling
|
|
1206
|
-
safely_call(
|
|
1242
|
+
safely_call(
|
|
1243
|
+
rescued_sample_allocation,
|
|
1244
|
+
Qnil,
|
|
1245
|
+
state->self_instance,
|
|
1246
|
+
handle_sampling_failure_rescued_sample_allocation
|
|
1247
|
+
);
|
|
1207
1248
|
|
|
1208
1249
|
if (state->dynamic_sampling_rate_enabled) {
|
|
1209
1250
|
long now = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
|
1210
1251
|
if (now == 0) {
|
|
1211
|
-
|
|
1252
|
+
delayed_error_clock_failure(state);
|
|
1212
1253
|
// NOTE: Not short-circuiting here to make sure cleanup happens
|
|
1213
1254
|
}
|
|
1214
1255
|
uint64_t sampling_time_ns = discrete_dynamic_sampler_after_sample(&state->allocation_sampler, now);
|
|
@@ -1284,7 +1325,12 @@ static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
|
|
|
1284
1325
|
|
|
1285
1326
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error) {
|
|
1286
1327
|
// If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
|
|
1287
|
-
stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error));
|
|
1328
|
+
stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error), "delayed_error");
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state) {
|
|
1332
|
+
// If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
|
|
1333
|
+
stop_state(state, rb_exc_new_cstr(clock_failure_exception_class, "failed to get clock time"), "delayed_error_clock_failure");
|
|
1288
1334
|
}
|
|
1289
1335
|
|
|
1290
1336
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg) {
|
|
@@ -1365,7 +1411,12 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1365
1411
|
during_sample_enter(state);
|
|
1366
1412
|
|
|
1367
1413
|
// Rescue against any exceptions that happen during sampling
|
|
1368
|
-
safely_call(
|
|
1414
|
+
safely_call(
|
|
1415
|
+
rescued_after_gvl_running_from_postponed_job,
|
|
1416
|
+
state->self_instance,
|
|
1417
|
+
state->self_instance,
|
|
1418
|
+
handle_sampling_failure_rescued_after_gvl_running_from_postponed_job
|
|
1419
|
+
);
|
|
1369
1420
|
|
|
1370
1421
|
during_sample_exit(state);
|
|
1371
1422
|
}
|
|
@@ -1404,6 +1455,26 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1404
1455
|
}
|
|
1405
1456
|
#endif
|
|
1406
1457
|
|
|
1458
|
+
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception) {
|
|
1459
|
+
stop(self_instance, exception, "rescued_sample_from_postponed_job");
|
|
1460
|
+
return Qnil;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception) {
|
|
1464
|
+
stop(self_instance, exception, "thread_context_collector_sample_after_gc");
|
|
1465
|
+
return Qnil;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception) {
|
|
1469
|
+
stop(self_instance, exception, "rescued_sample_allocation");
|
|
1470
|
+
return Qnil;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
static VALUE handle_sampling_failure_rescued_after_gvl_running_from_postponed_job(VALUE self_instance, VALUE exception) {
|
|
1474
|
+
stop(self_instance, exception, "rescued_after_gvl_running_from_postponed_job");
|
|
1475
|
+
return Qnil;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1407
1478
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state) {
|
|
1408
1479
|
// Tell the compiler it's not allowed to reorder the `during_sample` flag with anything that happens after.
|
|
1409
1480
|
//
|
|
@@ -51,7 +51,7 @@ void discrete_dynamic_sampler_reset(discrete_dynamic_sampler *sampler, long now_
|
|
|
51
51
|
|
|
52
52
|
void discrete_dynamic_sampler_set_overhead_target_percentage(discrete_dynamic_sampler *sampler, double target_overhead, long now_ns) {
|
|
53
53
|
if (target_overhead <= 0 || target_overhead > 100) {
|
|
54
|
-
|
|
54
|
+
raise_error(rb_eArgError, "Target overhead must be a double between ]0,100] was %f", target_overhead);
|
|
55
55
|
}
|
|
56
56
|
sampler->target_overhead = target_overhead;
|
|
57
57
|
return discrete_dynamic_sampler_reset(sampler, now_ns);
|
|
@@ -369,7 +369,7 @@ static VALUE _native_new(VALUE klass) {
|
|
|
369
369
|
|
|
370
370
|
long now_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
|
371
371
|
if (now_ns == 0) {
|
|
372
|
-
|
|
372
|
+
raise_error(rb_eRuntimeError, "failed to get clock time");
|
|
373
373
|
}
|
|
374
374
|
discrete_dynamic_sampler_init(&state->sampler, "test sampler", now_ns);
|
|
375
375
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include <datadog/profiling.h>
|
|
3
3
|
|
|
4
4
|
#include "collectors_gc_profiling_helper.h"
|
|
5
|
+
#include "ruby_helpers.h"
|
|
5
6
|
|
|
6
7
|
// This helper is used by the Datadog::Profiling::Collectors::ThreadContext to profile garbage collection.
|
|
7
8
|
// It's tested through that class' interfaces.
|
|
@@ -71,7 +72,7 @@ uint8_t gc_profiling_set_metadata(ddog_prof_Label *labels, int labels_length) {
|
|
|
71
72
|
1; // gc type
|
|
72
73
|
|
|
73
74
|
if (max_label_count > labels_length) {
|
|
74
|
-
|
|
75
|
+
raise_error(rb_eArgError, "BUG: gc_profiling_set_metadata invalid labels_length (%d) < max_label_count (%d)", labels_length, max_label_count);
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
uint8_t label_pos = 0;
|
|
@@ -119,7 +120,7 @@ uint8_t gc_profiling_set_metadata(ddog_prof_Label *labels, int labels_length) {
|
|
|
119
120
|
};
|
|
120
121
|
|
|
121
122
|
if (label_pos > max_label_count) {
|
|
122
|
-
|
|
123
|
+
raise_error(rb_eRuntimeError, "BUG: gc_profiling_set_metadata unexpected label_pos (%d) > max_label_count (%d)", label_pos, max_label_count);
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
return label_pos;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
#include "datadog_ruby_common.h"
|
|
19
19
|
#include "private_vm_api_access.h"
|
|
20
|
+
#include "ruby_helpers.h"
|
|
20
21
|
#include "stack_recorder.h"
|
|
21
22
|
#include "collectors_stack.h"
|
|
22
23
|
|
|
@@ -284,11 +285,11 @@ void sample_thread(
|
|
|
284
285
|
// here, but >= 0 makes this easier to understand/debug.
|
|
285
286
|
bool only_wall_time = cpu_or_wall_sample && values.cpu_time_ns == 0 && values.wall_time_ns >= 0;
|
|
286
287
|
|
|
287
|
-
if (cpu_or_wall_sample && state_label == NULL)
|
|
288
|
+
if (cpu_or_wall_sample && state_label == NULL) raise_error(rb_eRuntimeError, "BUG: Unexpected missing state_label");
|
|
288
289
|
|
|
289
290
|
if (has_cpu_time) {
|
|
290
291
|
state_label->str = DDOG_CHARSLICE_C("had cpu");
|
|
291
|
-
if (labels.is_gvl_waiting_state)
|
|
292
|
+
if (labels.is_gvl_waiting_state) raise_error(rb_eRuntimeError, "BUG: Unexpected combination of cpu-time with is_gvl_waiting");
|
|
292
293
|
}
|
|
293
294
|
|
|
294
295
|
int top_of_stack_position = captured_frames - 1;
|
|
@@ -347,8 +348,10 @@ void sample_thread(
|
|
|
347
348
|
} else if (CHARSLICE_EQUALS("select", name_slice)) { // Expected to be Kernel.select
|
|
348
349
|
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
349
350
|
} else if (
|
|
350
|
-
CHARSLICE_EQUALS("synchronize", name_slice) || // Expected to be Monitor/Mutex#synchronize
|
|
351
|
-
|
|
351
|
+
CHARSLICE_EQUALS("synchronize", name_slice) || // Expected to be Monitor/Mutex#synchronize on Ruby 2 & 3, and Monitor#synchronize on 4 (Mutex becomes <internal:thread_sync>)
|
|
352
|
+
#ifdef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby < 4
|
|
353
|
+
CHARSLICE_EQUALS("lock", name_slice) || // Expected to be Mutex#lock
|
|
354
|
+
#endif
|
|
352
355
|
CHARSLICE_EQUALS("join", name_slice) // Expected to be Thread#join
|
|
353
356
|
) {
|
|
354
357
|
state_label->str = DDOG_CHARSLICE_C("blocked");
|
|
@@ -366,9 +369,19 @@ void sample_thread(
|
|
|
366
369
|
#endif
|
|
367
370
|
} else {
|
|
368
371
|
#ifndef NO_PRIMITIVE_POP // Ruby >= 3.2
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
+
if (CHARSLICE_EQUALS("<internal:thread_sync>", filename_slice)) {
|
|
373
|
+
if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
|
|
374
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
375
|
+
}
|
|
376
|
+
#ifndef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby >= 4
|
|
377
|
+
else if (CHARSLICE_EQUALS("synchronize", name_slice) || CHARSLICE_EQUALS("lock", name_slice)) { // Expected to be Mutex#lock/synchronize
|
|
378
|
+
state_label->str = DDOG_CHARSLICE_C("blocked");
|
|
379
|
+
} else if (CHARSLICE_EQUALS("sleep", name_slice)) { // Expected to be Mutex#sleep
|
|
380
|
+
state_label->str = DDOG_CHARSLICE_C("sleeping");
|
|
381
|
+
} else if (CHARSLICE_EQUALS("wait", name_slice)) { // Expected to be ConditionVariable#wait
|
|
382
|
+
state_label->str = DDOG_CHARSLICE_C("waiting");
|
|
383
|
+
}
|
|
384
|
+
#endif
|
|
372
385
|
}
|
|
373
386
|
#endif
|
|
374
387
|
}
|
|
@@ -600,8 +613,8 @@ bool prepare_sample_thread(VALUE thread, sampling_buffer *buffer) {
|
|
|
600
613
|
}
|
|
601
614
|
|
|
602
615
|
uint16_t sampling_buffer_check_max_frames(int max_frames) {
|
|
603
|
-
if (max_frames < 5)
|
|
604
|
-
if (max_frames > MAX_FRAMES_LIMIT)
|
|
616
|
+
if (max_frames < 5) raise_error(rb_eArgError, "Invalid max_frames: value must be >= 5");
|
|
617
|
+
if (max_frames > MAX_FRAMES_LIMIT) raise_error(rb_eArgError, "Invalid max_frames: value must be <= " MAX_FRAMES_LIMIT_AS_STRING);
|
|
605
618
|
return max_frames;
|
|
606
619
|
}
|
|
607
620
|
|
|
@@ -618,7 +631,7 @@ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames, dd
|
|
|
618
631
|
|
|
619
632
|
void sampling_buffer_free(sampling_buffer *buffer) {
|
|
620
633
|
if (buffer->max_frames == 0 || buffer->locations == NULL || buffer->stack_buffer == NULL) {
|
|
621
|
-
|
|
634
|
+
raise_error(rb_eArgError, "sampling_buffer_free called with invalid buffer");
|
|
622
635
|
}
|
|
623
636
|
|
|
624
637
|
ruby_xfree(buffer->stack_buffer);
|