datadog 2.30.0 → 2.32.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 +44 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +17 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +11 -4
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +6 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +18 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -4
- data/ext/datadog_profiling_native_extension/http_transport.c +10 -5
- data/ext/libdatadog_api/crashtracker.c +5 -8
- data/ext/libdatadog_api/datadog_ruby_common.c +18 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/di.c +127 -0
- data/ext/libdatadog_api/extconf.rb +9 -4
- data/ext/libdatadog_api/init.c +5 -2
- data/ext/libdatadog_extconf_helpers.rb +46 -1
- data/lib/datadog/ai_guard/component.rb +2 -0
- data/lib/datadog/ai_guard/configuration.rb +105 -2
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +41 -3
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation/request.rb +14 -9
- data/lib/datadog/ai_guard/evaluation/result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation.rb +37 -7
- data/lib/datadog/ai_guard/ext.rb +1 -0
- data/lib/datadog/ai_guard.rb +26 -8
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +11 -7
- data/lib/datadog/appsec/configuration.rb +414 -1
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +6 -7
- data/lib/datadog/appsec/instrumentation/gateway.rb +0 -13
- data/lib/datadog/appsec/metrics/telemetry.rb +13 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -0
- data/lib/datadog/appsec/security_engine/runner.rb +1 -1
- data/lib/datadog/appsec/trace_keeper.rb +18 -6
- data/lib/datadog/appsec/utils/http/media_type.rb +1 -2
- data/lib/datadog/appsec/utils/http/url_encoded.rb +3 -3
- data/lib/datadog/appsec.rb +5 -9
- data/lib/datadog/core/configuration/base.rb +17 -5
- data/lib/datadog/core/configuration/components.rb +22 -9
- data/lib/datadog/core/configuration/config_helper.rb +9 -0
- data/lib/datadog/core/configuration/option.rb +30 -5
- data/lib/datadog/core/configuration/option_definition.rb +38 -12
- data/lib/datadog/core/configuration/options.rb +40 -6
- data/lib/datadog/core/configuration/settings.rb +18 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
- data/lib/datadog/core/contrib/rails/utils.rb +7 -3
- data/lib/datadog/core/crashtracking/component.rb +3 -3
- data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/core/environment/container.rb +2 -2
- data/lib/datadog/core/environment/ext.rb +1 -0
- data/lib/datadog/core/environment/identity.rb +25 -3
- data/lib/datadog/core/environment/process.rb +12 -0
- data/lib/datadog/core/feature_flags.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +5 -5
- data/lib/datadog/core/remote/client.rb +1 -1
- data/lib/datadog/core/remote/component.rb +38 -21
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +3 -0
- data/lib/datadog/core/telemetry/emitter.rb +1 -1
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
- data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +151 -169
- data/lib/datadog/core/telemetry/event.rb +1 -7
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -0
- data/lib/datadog/core/telemetry/worker.rb +20 -0
- data/lib/datadog/core/transport/http.rb +2 -0
- data/lib/datadog/core/utils/only_once.rb +1 -1
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +36 -0
- data/lib/datadog/core/utils.rb +1 -1
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core.rb +1 -2
- data/lib/datadog/data_streams/configuration.rb +40 -1
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +1 -1
- data/lib/datadog/data_streams.rb +1 -1
- data/lib/datadog/di/base.rb +8 -5
- data/lib/datadog/di/boot.rb +2 -4
- data/lib/datadog/di/code_tracker.rb +179 -1
- data/lib/datadog/di/component.rb +5 -1
- data/lib/datadog/di/configuration.rb +235 -2
- data/lib/datadog/di/instrumenter.rb +55 -29
- data/lib/datadog/di/probe_builder.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +2 -2
- data/lib/datadog/di/probe_manager.rb +6 -6
- data/lib/datadog/di/probe_notification_builder.rb +110 -2
- data/lib/datadog/di/probe_notifier_worker.rb +2 -2
- data/lib/datadog/di/remote.rb +6 -6
- data/lib/datadog/di/transport/input.rb +3 -3
- data/lib/datadog/di.rb +81 -0
- data/lib/datadog/error_tracking/configuration.rb +55 -2
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/open_feature/component.rb +18 -1
- data/lib/datadog/open_feature/evaluation_engine.rb +2 -2
- data/lib/datadog/open_feature/hooks/flag_eval_hook.rb +49 -0
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
- data/lib/datadog/open_feature/provider.rb +19 -1
- data/lib/datadog/open_feature/remote.rb +1 -1
- data/lib/datadog/open_feature/transport.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +2 -0
- data/lib/datadog/opentelemetry/metrics.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +1 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +36 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +31 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +8 -2
- data/lib/datadog/profiling/collectors/info.rb +16 -3
- data/lib/datadog/profiling/component.rb +12 -4
- data/lib/datadog/profiling/exporter.rb +37 -12
- data/lib/datadog/profiling/ext.rb +0 -2
- data/lib/datadog/profiling/flush.rb +21 -12
- data/lib/datadog/profiling/http_transport.rb +12 -1
- data/lib/datadog/profiling/load_native_extension.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +13 -5
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +8 -3
- data/lib/datadog/profiling/tasks/help.rb +1 -0
- data/lib/datadog/profiling/tasks/setup.rb +2 -2
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/symbol_database/configuration.rb +65 -0
- data/lib/datadog/symbol_database/extractor.rb +915 -0
- data/lib/datadog/symbol_database/file_hash.rb +46 -0
- data/lib/datadog/symbol_database/logger.rb +43 -0
- data/lib/datadog/symbol_database/scope.rb +98 -0
- data/lib/datadog/symbol_database/service_version.rb +57 -0
- data/lib/datadog/symbol_database/symbol.rb +66 -0
- data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
- data/lib/datadog/symbol_database/transport/http.rb +45 -0
- data/lib/datadog/symbol_database/transport.rb +54 -0
- data/lib/datadog/symbol_database/uploader.rb +166 -0
- data/lib/datadog/symbol_database.rb +49 -0
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/component.rb +11 -0
- data/lib/datadog/tracing/configuration/settings.rb +2 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -3
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +20 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/component.rb +1 -1
- data/lib/datadog/tracing/contrib/configurable.rb +18 -3
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +7 -4
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/extensions.rb +9 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +5 -5
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +2 -2
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -2
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +3 -3
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
- data/lib/datadog/tracing/contrib.rb +8 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/tracing/distributed/baggage.rb +59 -5
- data/lib/datadog/tracing/distributed/datadog.rb +13 -11
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -1
- data/lib/datadog/tracing/distributed/propagation.rb +2 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +74 -32
- data/lib/datadog/tracing/event.rb +1 -1
- data/lib/datadog/tracing/metadata/tagging.rb +2 -2
- data/lib/datadog/tracing/pipeline.rb +1 -1
- data/lib/datadog/tracing/remote.rb +1 -1
- data/lib/datadog/tracing/sampling/ext.rb +2 -0
- data/lib/datadog/tracing/sampling/priority_sampler.rb +13 -0
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +4 -4
- data/lib/datadog/tracing/trace_operation.rb +53 -9
- data/lib/datadog/tracing/tracer.rb +29 -4
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +1 -1
- data/lib/datadog/tracing/workers.rb +2 -1
- data/lib/datadog/version.rb +1 -1
- metadata +27 -12
- data/lib/datadog/ai_guard/configuration/settings.rb +0 -113
- data/lib/datadog/appsec/configuration/settings.rb +0 -423
- data/lib/datadog/data_streams/configuration/settings.rb +0 -49
- data/lib/datadog/di/configuration/settings.rb +0 -243
- data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 04ff51661b0a7d494e4beaf4d142c723bce97e2c2a14ad708e1bfd12e780129a
|
|
4
|
+
data.tar.gz: 0a4a3f4ccc112c3c805a035072270781e360f68ae1f3464356abde84b97944ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c664b9d447c8645e4a202f04e5b2f690b85f15b62689f3312a8d5d3ccb2a08ec289a6d07fa414eee8e5dd92a3bea9f040b758fbfed97ab602bdcf4a989e47d6b
|
|
7
|
+
data.tar.gz: 92ce248e3e351d774b043921c18cd73f3ba064eed1203246a81ef1de9500cb4c6220fc7df81187b5b49bd4062fa87228bf8be8817c599315da8853752740ab96
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.31.0] - 2026-04-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* Core: Add `app-extended-heartbeat` telemetry event to resend full configuration every 24h for long-running services. ([#5531][])
|
|
10
|
+
* AI Guard: Add multi-model messages support to AI Guard, enabling text and image URL content parts in evaluation SDK ([#5564][])
|
|
11
|
+
* AI Guard: Add evaluation of images in user prompt and tool output for RubyLLM contrib. ([#5573][])
|
|
12
|
+
* AI Guard: Expose Sensitive Data Scanner findings in AI Guard results via `AIGuard::Evaluation::Result#sds_findings`. ([#5579][])
|
|
13
|
+
* AI Guard: Expose tag probabilities in AI Guard results via `AIGuard::Evaluation::Result#tag_probabilities`. ([#5580][])
|
|
14
|
+
* Tracing: Integrations: Add `rails.application` to the process tags. ([#5468][])
|
|
15
|
+
* Tracing: Report and display all configurations used by a service in the 'SDK & Agent Configurations' tab of a Ruby service page in Datadog UI ([#5483][])
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
* Core: Upgrade `libdatadog` dependency to version 30.0.0 ([#5574][])
|
|
20
|
+
* AI Guard: **Breaking change:** AIGuard.evaluate now defaults to `allow_raise: true`. Pass `allow_raise: false` to keep the previous non-raising behavior. ([#5587][])
|
|
21
|
+
* Dynamic Instrumentation: Report exception messages in method probe snapshots. Require the libdatadog_api C extension for Dynamic Instrumentation. ([#5111][])
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
* Profiling: Detect when `libdatadog` version does not match expected version. ([#5484][])
|
|
26
|
+
* Profiling: Log profiler initialization errors as warnings instead of raising them. ([#5509][])
|
|
27
|
+
* Tracing: Fix `NoMethodError` in `extract_trace_id!` caused by `extract_tags` returning `true`. ([#5499][])
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
|
|
31
|
+
* Core: Removed JRuby from the CI test matrix ([#5594][])
|
|
32
|
+
|
|
5
33
|
## [2.30.0] - 2026-03-19
|
|
6
34
|
|
|
7
35
|
### Added
|
|
@@ -3539,7 +3567,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
3539
3567
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
3540
3568
|
|
|
3541
3569
|
|
|
3542
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.
|
|
3570
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.31.0...master
|
|
3571
|
+
[2.31.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.30.0...v2.31.0
|
|
3543
3572
|
[2.30.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.29.0...v2.30.0
|
|
3544
3573
|
[2.29.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.28.0...v2.29.0
|
|
3545
3574
|
[2.28.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.27.0...v2.28.0
|
|
@@ -5193,6 +5222,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5193
5222
|
[#5076]: https://github.com/DataDog/dd-trace-rb/issues/5076
|
|
5194
5223
|
[#5086]: https://github.com/DataDog/dd-trace-rb/issues/5086
|
|
5195
5224
|
[#5091]: https://github.com/DataDog/dd-trace-rb/issues/5091
|
|
5225
|
+
[#5111]: https://github.com/DataDog/dd-trace-rb/issues/5111
|
|
5196
5226
|
[#5122]: https://github.com/DataDog/dd-trace-rb/issues/5122
|
|
5197
5227
|
[#5144]: https://github.com/DataDog/dd-trace-rb/issues/5144
|
|
5198
5228
|
[#5145]: https://github.com/DataDog/dd-trace-rb/issues/5145
|
|
@@ -5251,7 +5281,20 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
5251
5281
|
[#5448]: https://github.com/DataDog/dd-trace-rb/issues/5448
|
|
5252
5282
|
[#5449]: https://github.com/DataDog/dd-trace-rb/issues/5449
|
|
5253
5283
|
[#5461]: https://github.com/DataDog/dd-trace-rb/issues/5461
|
|
5284
|
+
[#5468]: https://github.com/DataDog/dd-trace-rb/issues/5468
|
|
5254
5285
|
[#5469]: https://github.com/DataDog/dd-trace-rb/issues/5469
|
|
5286
|
+
[#5483]: https://github.com/DataDog/dd-trace-rb/issues/5483
|
|
5287
|
+
[#5484]: https://github.com/DataDog/dd-trace-rb/issues/5484
|
|
5288
|
+
[#5499]: https://github.com/DataDog/dd-trace-rb/issues/5499
|
|
5289
|
+
[#5509]: https://github.com/DataDog/dd-trace-rb/issues/5509
|
|
5290
|
+
[#5531]: https://github.com/DataDog/dd-trace-rb/issues/5531
|
|
5291
|
+
[#5564]: https://github.com/DataDog/dd-trace-rb/issues/5564
|
|
5292
|
+
[#5573]: https://github.com/DataDog/dd-trace-rb/issues/5573
|
|
5293
|
+
[#5574]: https://github.com/DataDog/dd-trace-rb/issues/5574
|
|
5294
|
+
[#5579]: https://github.com/DataDog/dd-trace-rb/issues/5579
|
|
5295
|
+
[#5580]: https://github.com/DataDog/dd-trace-rb/issues/5580
|
|
5296
|
+
[#5587]: https://github.com/DataDog/dd-trace-rb/issues/5587
|
|
5297
|
+
[#5594]: https://github.com/DataDog/dd-trace-rb/issues/5594
|
|
5255
5298
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
5256
5299
|
[@Azure7111]: https://github.com/Azure7111
|
|
5257
5300
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -186,6 +186,11 @@ typedef struct {
|
|
|
186
186
|
uint64_t gvl_sampling_time_ns_min;
|
|
187
187
|
uint64_t gvl_sampling_time_ns_max;
|
|
188
188
|
uint64_t gvl_sampling_time_ns_total;
|
|
189
|
+
|
|
190
|
+
struct vm_metrics {
|
|
191
|
+
// Total time spent waiting for the GVL
|
|
192
|
+
uint64_t gvl_waiting_time_ns_total;
|
|
193
|
+
} vm_metrics;
|
|
189
194
|
} stats;
|
|
190
195
|
} cpu_and_wall_time_worker_state;
|
|
191
196
|
|
|
@@ -1101,6 +1106,7 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
|
1101
1106
|
ID2SYM(rb_intern("gvl_sampling_time_ns_max")), /* => */ RUBY_NUM_OR_NIL(state->stats.gvl_sampling_time_ns_max, > 0, ULL2NUM),
|
|
1102
1107
|
ID2SYM(rb_intern("gvl_sampling_time_ns_total")), /* => */ RUBY_NUM_OR_NIL(state->stats.gvl_sampling_time_ns_total, > 0, ULL2NUM),
|
|
1103
1108
|
ID2SYM(rb_intern("gvl_sampling_time_ns_avg")), /* => */ RUBY_AVG_OR_NIL(state->stats.gvl_sampling_time_ns_total, state->stats.after_gvl_running),
|
|
1109
|
+
ID2SYM(rb_intern("gvl_waiting_time_ns_total")), /* => */ state->gvl_profiling_enabled ? ULL2NUM(state->stats.vm_metrics.gvl_waiting_time_ns_total) : Qnil,
|
|
1104
1110
|
};
|
|
1105
1111
|
for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(stats_as_hash, arguments[i], arguments[i+1]);
|
|
1106
1112
|
return stats_as_hash;
|
|
@@ -1141,6 +1147,7 @@ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state) {
|
|
|
1141
1147
|
.cpu_sampling_time_ns_min = UINT64_MAX,
|
|
1142
1148
|
.allocation_sampling_time_ns_min = UINT64_MAX,
|
|
1143
1149
|
.gvl_sampling_time_ns_min = UINT64_MAX,
|
|
1150
|
+
// Other fields are reset to 0
|
|
1144
1151
|
};
|
|
1145
1152
|
}
|
|
1146
1153
|
|
|
@@ -1399,7 +1406,7 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1399
1406
|
// Interesting note: A RUBY_INTERNAL_THREAD_EVENT_RESUMED is guaranteed to be called with the GVL being acquired.
|
|
1400
1407
|
// (And... I think target_thread will be == rb_thread_current()?)
|
|
1401
1408
|
//
|
|
1402
|
-
// But we're not sure if we're on the main Ractor yet. The thread context collector
|
|
1409
|
+
// But we're not sure if we're on the main Ractor yet. The thread context collector can actually help here:
|
|
1403
1410
|
// it tags threads it's tracking, so if a thread is tagged then by definition we know that thread belongs to the main
|
|
1404
1411
|
// Ractor. Thus, if we get a ON_GVL_RUNNING_UNKNOWN result we shouldn't touch any state, but otherwise we're good to go.
|
|
1405
1412
|
|
|
@@ -1407,19 +1414,22 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1407
1414
|
target_thread = gvl_profiling_state_maybe_initialize();
|
|
1408
1415
|
#endif
|
|
1409
1416
|
|
|
1417
|
+
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1418
|
+
if (state == NULL) return; // This should not happen, but just in case...
|
|
1419
|
+
|
|
1410
1420
|
on_gvl_running_result result = thread_context_collector_on_gvl_running(target_thread);
|
|
1411
1421
|
|
|
1412
|
-
if (result
|
|
1422
|
+
if (result.waiting_for_gvl_duration_ns > 0) {
|
|
1423
|
+
state->stats.vm_metrics.gvl_waiting_time_ns_total += (uint64_t) result.waiting_for_gvl_duration_ns;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
if (result.action == ON_GVL_RUNNING_SAMPLE) {
|
|
1413
1427
|
#ifndef NO_POSTPONED_TRIGGER
|
|
1414
1428
|
rb_postponed_job_trigger(after_gvl_running_from_postponed_job_handle);
|
|
1415
1429
|
#else
|
|
1416
1430
|
rb_postponed_job_register_one(0, after_gvl_running_from_postponed_job, NULL);
|
|
1417
1431
|
#endif
|
|
1418
|
-
} else if (result == ON_GVL_RUNNING_DONT_SAMPLE) {
|
|
1419
|
-
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1420
|
-
|
|
1421
|
-
if (state == NULL) return; // This should not happen, but just in case...
|
|
1422
|
-
|
|
1432
|
+
} else if (result.action == ON_GVL_RUNNING_DONT_SAMPLE) {
|
|
1423
1433
|
state->stats.gvl_dont_sample++;
|
|
1424
1434
|
}
|
|
1425
1435
|
} else {
|
|
@@ -1924,10 +1924,14 @@ static uint64_t otel_span_id_to_uint(VALUE otel_span_id) {
|
|
|
1924
1924
|
intptr_t gvl_waiting_at = gvl_profiling_state_get(thread);
|
|
1925
1925
|
|
|
1926
1926
|
// Thread was not being profiled / not waiting on gvl
|
|
1927
|
-
if (gvl_waiting_at == 0 || gvl_waiting_at == GVL_WAITING_ENABLED_EMPTY)
|
|
1927
|
+
if (gvl_waiting_at == 0 || gvl_waiting_at == GVL_WAITING_ENABLED_EMPTY) {
|
|
1928
|
+
return (on_gvl_running_result) {.action = ON_GVL_RUNNING_UNKNOWN, .waiting_for_gvl_duration_ns = 0};
|
|
1929
|
+
}
|
|
1928
1930
|
|
|
1929
1931
|
// @ivoanjo: I'm not sure if this can happen -- It means we should've sampled already but haven't gotten the chance yet?
|
|
1930
|
-
if (gvl_waiting_at < 0)
|
|
1932
|
+
if (gvl_waiting_at < 0) {
|
|
1933
|
+
return (on_gvl_running_result) {.action = ON_GVL_RUNNING_SAMPLE, .waiting_for_gvl_duration_ns = 0};
|
|
1934
|
+
}
|
|
1931
1935
|
|
|
1932
1936
|
long waiting_for_gvl_duration_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - gvl_waiting_at;
|
|
1933
1937
|
|
|
@@ -1943,7 +1947,10 @@ static uint64_t otel_span_id_to_uint(VALUE otel_span_id) {
|
|
|
1943
1947
|
gvl_profiling_state_set(thread, GVL_WAITING_ENABLED_EMPTY);
|
|
1944
1948
|
}
|
|
1945
1949
|
|
|
1946
|
-
return
|
|
1950
|
+
return (on_gvl_running_result) {
|
|
1951
|
+
.action = should_sample ? ON_GVL_RUNNING_SAMPLE : ON_GVL_RUNNING_DONT_SAMPLE,
|
|
1952
|
+
.waiting_for_gvl_duration_ns = waiting_for_gvl_duration_ns,
|
|
1953
|
+
};
|
|
1947
1954
|
}
|
|
1948
1955
|
|
|
1949
1956
|
__attribute__((warn_unused_result))
|
|
@@ -2146,7 +2153,7 @@ static uint64_t otel_span_id_to_uint(VALUE otel_span_id) {
|
|
|
2146
2153
|
|
|
2147
2154
|
debug_enter_unsafe_context();
|
|
2148
2155
|
|
|
2149
|
-
VALUE result = thread_context_collector_on_gvl_running(thread_from_thread_object(thread)) == ON_GVL_RUNNING_SAMPLE ? Qtrue : Qfalse;
|
|
2156
|
+
VALUE result = thread_context_collector_on_gvl_running(thread_from_thread_object(thread)).action == ON_GVL_RUNNING_SAMPLE ? Qtrue : Qfalse;
|
|
2150
2157
|
|
|
2151
2158
|
debug_leave_unsafe_context();
|
|
2152
2159
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include <ruby.h>
|
|
4
4
|
#include <stdbool.h>
|
|
5
|
+
#include <stdint.h>
|
|
5
6
|
|
|
6
7
|
#include "gvl_profiling_helper.h"
|
|
7
8
|
|
|
@@ -25,6 +26,11 @@ VALUE enforce_thread_context_collector_instance(VALUE object);
|
|
|
25
26
|
ON_GVL_RUNNING_UNKNOWN, // Thread is not known, it may not even be from the current Ractor
|
|
26
27
|
ON_GVL_RUNNING_DONT_SAMPLE, // Thread is known, but "Waiting for GVL" period was too small to be sampled
|
|
27
28
|
ON_GVL_RUNNING_SAMPLE, // Thread is known, and "Waiting for GVL" period should be sampled
|
|
29
|
+
} on_gvl_running_enum;
|
|
30
|
+
|
|
31
|
+
typedef struct {
|
|
32
|
+
on_gvl_running_enum action;
|
|
33
|
+
long waiting_for_gvl_duration_ns;
|
|
28
34
|
} on_gvl_running_result;
|
|
29
35
|
|
|
30
36
|
void thread_context_collector_on_gvl_waiting(gvl_profiling_thread thread);
|
|
@@ -122,6 +122,24 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
|
|
|
122
122
|
return error_msg_size;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
static void verify_libdatadog_version(void) {
|
|
126
|
+
rb_eval_string(
|
|
127
|
+
"require 'libdatadog';"
|
|
128
|
+
"expected = '" EXPECTED_LIBDATADOG_VERSION "';"
|
|
129
|
+
"if expected != Libdatadog::VERSION;"
|
|
130
|
+
"raise(LoadError, <<MSG\n"
|
|
131
|
+
"The `datadog` gem needs to be reinstalled whenever the `libdatadog` gem version is changed. "
|
|
132
|
+
"The currently-installed version of `datadog` was built to work with `libdatadog` gem version #{expected} "
|
|
133
|
+
"but the currently-loaded version of `libdatadog` is #{Libdatadog::VERSION}. "
|
|
134
|
+
"To fix this, reinstall the `datadog` gem (e.g. `bundle exec gem pristine datadog`) "
|
|
135
|
+
"or contact Datadog support for help at <https://docs.datadoghq.com/help/>.\n"
|
|
136
|
+
"MSG\n"
|
|
137
|
+
");"
|
|
138
|
+
"end"
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
125
142
|
void datadog_ruby_common_init(void) {
|
|
126
143
|
telemetry_message_id = rb_intern("@telemetry_message");
|
|
144
|
+
verify_libdatadog_version();
|
|
127
145
|
}
|
|
@@ -102,3 +102,13 @@ static inline VALUE get_error_details_and_drop(ddog_Error *error) {
|
|
|
102
102
|
// Returns the amount of characters written to string (which are necessarily
|
|
103
103
|
// bounded by capacity - 1 since the string will be null-terminated).
|
|
104
104
|
size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capacity);
|
|
105
|
+
|
|
106
|
+
#define IMEMO_MASK 0x0f
|
|
107
|
+
|
|
108
|
+
// Returns the imemo type of an imemo object.
|
|
109
|
+
// This mask is the same between Ruby 2.5 and 3.3-preview3. Furthermore, the intention of this method is to be used
|
|
110
|
+
// to call `rb_imemo_name` which correctly handles invalid numbers so even if the mask changes in the future, at most
|
|
111
|
+
// we'll get incorrect results (and never a VM crash)
|
|
112
|
+
static inline int ddtrace_imemo_type(VALUE imemo) {
|
|
113
|
+
return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
|
|
114
|
+
}
|
|
@@ -69,11 +69,16 @@ $stderr.puts(
|
|
|
69
69
|
# NOTE: we MUST NOT require 'mkmf' before we check the #skip_building_extension? because the require triggers checks
|
|
70
70
|
# that may fail on an environment not properly setup for building Ruby extensions.
|
|
71
71
|
require "mkmf"
|
|
72
|
+
Datadog::LibdatadogExtconfHelpers.dump_mkmf_log_on_failure!
|
|
72
73
|
|
|
73
74
|
Logging.message("[datadog] Using compiler:\n")
|
|
74
75
|
xsystem("#{CONFIG["CC"]} -v")
|
|
75
76
|
Logging.message("[datadog] End of compiler information\n")
|
|
76
77
|
|
|
78
|
+
# We must *never* `append_cflags "-Wall"` or `append_cflags "-Wextra"`, because those add the flag at the end,
|
|
79
|
+
# which then overrides earlier -Wno-* flags from RbConfig::CONFIG["warnflags"], and causes errors if -Werror is added.
|
|
80
|
+
# There is no need to add them anyway, Ruby since 1.9 has RbConfig::CONFIG["warnflags"] starting with "-Wall -Wextra ".
|
|
81
|
+
|
|
77
82
|
# Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
|
|
78
83
|
# But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
|
|
79
84
|
append_cflags "-Werror" if ENV["DATADOG_GEM_CI"] == "true"
|
|
@@ -106,10 +111,6 @@ append_cflags "-fvisibility=hidden"
|
|
|
106
111
|
# Avoid legacy C definitions
|
|
107
112
|
append_cflags "-Wold-style-definition"
|
|
108
113
|
|
|
109
|
-
# Enable all other compiler warnings
|
|
110
|
-
append_cflags "-Wall"
|
|
111
|
-
append_cflags "-Wextra"
|
|
112
|
-
|
|
113
114
|
if ENV["DDTRACE_DEBUG"] == "true"
|
|
114
115
|
$defs << "-DDD_DEBUG"
|
|
115
116
|
CONFIG["optflags"] = "-O0"
|
|
@@ -217,6 +218,8 @@ unless Datadog::LibdatadogExtconfHelpers.configure_libdatadog(extconf_folder: __
|
|
|
217
218
|
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::FAILED_TO_CONFIGURE_LIBDATADOG)
|
|
218
219
|
end
|
|
219
220
|
|
|
221
|
+
Datadog::LibdatadogExtconfHelpers.add_libdatadog_version_define
|
|
222
|
+
|
|
220
223
|
unless have_type("atomic_int", ["stdatomic.h"])
|
|
221
224
|
skip_building_extension!(Datadog::Profiling::NativeExtensionHelpers::Supported::COMPILER_ATOMIC_MISSING)
|
|
222
225
|
end
|
|
@@ -198,15 +198,15 @@ static VALUE _native_do_export(
|
|
|
198
198
|
VALUE flush
|
|
199
199
|
) {
|
|
200
200
|
VALUE encoded_profile = rb_funcall(flush, rb_intern("encoded_profile"), 0);
|
|
201
|
-
VALUE code_provenance_file_name = rb_funcall(flush, rb_intern("code_provenance_file_name"), 0);
|
|
202
201
|
VALUE code_provenance_data = rb_funcall(flush, rb_intern("code_provenance_data"), 0);
|
|
202
|
+
VALUE metrics_json = rb_funcall(flush, rb_intern("metrics"), 0);
|
|
203
203
|
VALUE tags_as_array = rb_funcall(flush, rb_intern("tags_as_array"), 0);
|
|
204
204
|
VALUE internal_metadata_json = rb_funcall(flush, rb_intern("internal_metadata_json"), 0);
|
|
205
205
|
VALUE info_json = rb_funcall(flush, rb_intern("info_json"), 0);
|
|
206
206
|
VALUE process_tags = rb_funcall(flush, rb_intern("process_tags"), 0);
|
|
207
207
|
|
|
208
208
|
enforce_encoded_profile_instance(encoded_profile);
|
|
209
|
-
ENFORCE_TYPE(
|
|
209
|
+
ENFORCE_TYPE(metrics_json, T_STRING);
|
|
210
210
|
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
|
211
211
|
ENFORCE_TYPE(internal_metadata_json, T_STRING);
|
|
212
212
|
ENFORCE_TYPE(info_json, T_STRING);
|
|
@@ -216,13 +216,18 @@ static VALUE _native_do_export(
|
|
|
216
216
|
bool have_code_provenance = !NIL_P(code_provenance_data);
|
|
217
217
|
if (have_code_provenance) ENFORCE_TYPE(code_provenance_data, T_STRING);
|
|
218
218
|
|
|
219
|
-
int to_compress_length = have_code_provenance ? 1 : 0;
|
|
219
|
+
int to_compress_length = 1 + (have_code_provenance ? 1 : 0);
|
|
220
220
|
ddog_prof_Exporter_File to_compress[to_compress_length];
|
|
221
221
|
ddog_prof_Exporter_Slice_File files_to_compress_and_export = {.ptr = to_compress, .len = to_compress_length};
|
|
222
222
|
|
|
223
|
+
to_compress[0] = (ddog_prof_Exporter_File) {
|
|
224
|
+
.name = DDOG_CHARSLICE_C("metrics.json"),
|
|
225
|
+
.file = byte_slice_from_ruby_string(metrics_json),
|
|
226
|
+
};
|
|
227
|
+
|
|
223
228
|
if (have_code_provenance) {
|
|
224
|
-
to_compress[
|
|
225
|
-
.name =
|
|
229
|
+
to_compress[1] = (ddog_prof_Exporter_File) {
|
|
230
|
+
.name = DDOG_CHARSLICE_C("code-provenance.json"),
|
|
226
231
|
.file = byte_slice_from_ruby_string(code_provenance_data),
|
|
227
232
|
};
|
|
228
233
|
}
|
|
@@ -51,12 +51,8 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
|
51
51
|
|
|
52
52
|
VALUE version = datadog_gem_version();
|
|
53
53
|
|
|
54
|
-
// Tags
|
|
54
|
+
// Tags are heap-allocated, so after here we can't raise exceptions otherwise we'll leak this memory
|
|
55
55
|
// Start of exception-free zone to prevent leaks {{
|
|
56
|
-
ddog_Endpoint *endpoint = ddog_endpoint_from_url(char_slice_from_ruby_string(agent_base_url));
|
|
57
|
-
if (endpoint == NULL) {
|
|
58
|
-
raise_error(rb_eRuntimeError, "Failed to create endpoint from agent_base_url: %"PRIsVALUE, agent_base_url);
|
|
59
|
-
}
|
|
60
56
|
ddog_Vec_Tag tags = convert_tags(tags_as_array);
|
|
61
57
|
|
|
62
58
|
ddog_crasht_Config config = {
|
|
@@ -73,7 +69,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
|
73
69
|
// overriding what Ruby set up seems a saner default to keep anyway.
|
|
74
70
|
.create_alt_stack = false,
|
|
75
71
|
.use_alt_stack = true,
|
|
76
|
-
.endpoint =
|
|
72
|
+
.endpoint = {.url = char_slice_from_ruby_string(agent_base_url)},
|
|
77
73
|
.resolve_frames = DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER,
|
|
78
74
|
.timeout_ms = FIX2INT(upload_timeout_seconds) * 1000,
|
|
79
75
|
};
|
|
@@ -106,11 +102,12 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
|
|
|
106
102
|
) :
|
|
107
103
|
ddog_crasht_update_on_fork(config, receiver_config, metadata);
|
|
108
104
|
|
|
109
|
-
first_init
|
|
105
|
+
// We use first_init to know which of [init, reconfigure] needs to be called. BUT if init failed we actually need
|
|
106
|
+
// to call init next time again, not reconfigure.
|
|
107
|
+
if (result.tag == DDOG_VOID_RESULT_OK) first_init = false;
|
|
110
108
|
|
|
111
109
|
// Clean up before potentially raising any exceptions
|
|
112
110
|
ddog_Vec_Tag_drop(tags);
|
|
113
|
-
ddog_endpoint_drop(endpoint);
|
|
114
111
|
// }} End of exception-free zone to prevent leaks
|
|
115
112
|
|
|
116
113
|
CHECK_VOID_RESULT("Failed to start/update the crash tracker", result);
|
|
@@ -122,6 +122,24 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
|
|
|
122
122
|
return error_msg_size;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
static void verify_libdatadog_version(void) {
|
|
126
|
+
rb_eval_string(
|
|
127
|
+
"require 'libdatadog';"
|
|
128
|
+
"expected = '" EXPECTED_LIBDATADOG_VERSION "';"
|
|
129
|
+
"if expected != Libdatadog::VERSION;"
|
|
130
|
+
"raise(LoadError, <<MSG\n"
|
|
131
|
+
"The `datadog` gem needs to be reinstalled whenever the `libdatadog` gem version is changed. "
|
|
132
|
+
"The currently-installed version of `datadog` was built to work with `libdatadog` gem version #{expected} "
|
|
133
|
+
"but the currently-loaded version of `libdatadog` is #{Libdatadog::VERSION}. "
|
|
134
|
+
"To fix this, reinstall the `datadog` gem (e.g. `bundle exec gem pristine datadog`) "
|
|
135
|
+
"or contact Datadog support for help at <https://docs.datadoghq.com/help/>.\n"
|
|
136
|
+
"MSG\n"
|
|
137
|
+
");"
|
|
138
|
+
"end"
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
125
142
|
void datadog_ruby_common_init(void) {
|
|
126
143
|
telemetry_message_id = rb_intern("@telemetry_message");
|
|
144
|
+
verify_libdatadog_version();
|
|
127
145
|
}
|
|
@@ -102,3 +102,13 @@ static inline VALUE get_error_details_and_drop(ddog_Error *error) {
|
|
|
102
102
|
// Returns the amount of characters written to string (which are necessarily
|
|
103
103
|
// bounded by capacity - 1 since the string will be null-terminated).
|
|
104
104
|
size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capacity);
|
|
105
|
+
|
|
106
|
+
#define IMEMO_MASK 0x0f
|
|
107
|
+
|
|
108
|
+
// Returns the imemo type of an imemo object.
|
|
109
|
+
// This mask is the same between Ruby 2.5 and 3.3-preview3. Furthermore, the intention of this method is to be used
|
|
110
|
+
// to call `rb_imemo_name` which correctly handles invalid numbers so even if the mask changes in the future, at most
|
|
111
|
+
// we'll get incorrect results (and never a VM crash)
|
|
112
|
+
static inline int ddtrace_imemo_type(VALUE imemo) {
|
|
113
|
+
return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
|
|
114
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#include <stdbool.h>
|
|
2
|
+
|
|
3
|
+
#include "datadog_ruby_common.h"
|
|
4
|
+
|
|
5
|
+
// Prototypes for Ruby functions declared in internal Ruby headers.
|
|
6
|
+
// rb_iseqw_new wraps an internal iseq pointer into a Ruby-visible
|
|
7
|
+
// RubyVM::InstructionSequence object.
|
|
8
|
+
VALUE rb_iseqw_new(const void *iseq);
|
|
9
|
+
// rb_iseqw_to_iseq unwraps a RubyVM::InstructionSequence object back
|
|
10
|
+
// to its internal iseq pointer.
|
|
11
|
+
const void *rb_iseqw_to_iseq(VALUE iseqw);
|
|
12
|
+
int rb_objspace_internal_object_p(VALUE obj);
|
|
13
|
+
void rb_objspace_each_objects(
|
|
14
|
+
int (*callback)(void *start, void *end, size_t stride, void *data),
|
|
15
|
+
void *data);
|
|
16
|
+
|
|
17
|
+
#define IMEMO_TYPE_ISEQ 7
|
|
18
|
+
|
|
19
|
+
// The ID value of the string "mesg" which is used in Ruby source as
|
|
20
|
+
// id_mesg or idMesg, and is used to set and retrieve the exception message
|
|
21
|
+
// from standard library exception classes like NameError.
|
|
22
|
+
static ID id_mesg;
|
|
23
|
+
|
|
24
|
+
// Returns whether the argument is an IMEMO of type ISEQ.
|
|
25
|
+
static bool ddtrace_imemo_iseq_p(VALUE v) {
|
|
26
|
+
return rb_objspace_internal_object_p(v) && RB_TYPE_P(v, T_IMEMO) && ddtrace_imemo_type(v) == IMEMO_TYPE_ISEQ;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static int ddtrace_di_os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
|
|
30
|
+
{
|
|
31
|
+
VALUE *array = (VALUE *)data;
|
|
32
|
+
|
|
33
|
+
VALUE v = (VALUE)vstart;
|
|
34
|
+
for (; v != (VALUE)vend; v += stride) {
|
|
35
|
+
if (ddtrace_imemo_iseq_p(v)) {
|
|
36
|
+
VALUE iseq = rb_iseqw_new((void *) v);
|
|
37
|
+
rb_ary_push(*array, iseq);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
Returns all RubyVM::InstructionSequence objects existing in the current process.
|
|
46
|
+
|
|
47
|
+
This uses the same approach as ruby/debug's iseq_collector.c:
|
|
48
|
+
https://github.com/ruby/debug/blob/master/ext/debug/iseq_collector.c
|
|
49
|
+
*/
|
|
50
|
+
static VALUE all_iseqs(DDTRACE_UNUSED VALUE _self) {
|
|
51
|
+
VALUE array = rb_ary_new();
|
|
52
|
+
rb_objspace_each_objects(ddtrace_di_os_obj_of_i, &array);
|
|
53
|
+
return array;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* call-seq:
|
|
58
|
+
* DI.exception_message(exception) -> String | Object
|
|
59
|
+
*
|
|
60
|
+
* Returns the exception message associated with the exception via the
|
|
61
|
+
* exception's constructor.
|
|
62
|
+
*
|
|
63
|
+
* This method does not invoke Ruby code and as such will not call
|
|
64
|
+
* the +message+ method, if one is defined on the exception object.
|
|
65
|
+
*
|
|
66
|
+
* Normally, the exception message is a string, however there is no
|
|
67
|
+
* type enforcement done by Ruby for the messages and objects of arbitrary
|
|
68
|
+
* classes can be passed to exception constructors and will, subsequently,
|
|
69
|
+
* be returned by this method.
|
|
70
|
+
*
|
|
71
|
+
* @param exception [Exception] The exception object
|
|
72
|
+
* @return [String | Object] The exception message
|
|
73
|
+
*/
|
|
74
|
+
static VALUE exception_message(DDTRACE_UNUSED VALUE _self, VALUE exception) {
|
|
75
|
+
return rb_ivar_get(exception, id_mesg);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// rb_iseq_type was added in Ruby 3.1 (commit 89a02d89 by Koichi Sasada,
|
|
79
|
+
// 2021-12-19). It returns the iseq type as a Symbol. On Ruby < 3.1 this
|
|
80
|
+
// function does not exist, so have_func('rb_iseq_type') in extconf.rb
|
|
81
|
+
// gates compilation. When unavailable, backfill_registry falls back to
|
|
82
|
+
// the first_lineno == 0 heuristic.
|
|
83
|
+
#ifdef HAVE_RB_ISEQ_TYPE
|
|
84
|
+
VALUE rb_iseq_type(const void *iseq);
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* call-seq:
|
|
88
|
+
* DI.iseq_type(iseq) -> Symbol
|
|
89
|
+
*
|
|
90
|
+
* Returns the type of an InstructionSequence as a symbol by calling
|
|
91
|
+
* the internal rb_iseq_type() function (available since Ruby 3.1).
|
|
92
|
+
*
|
|
93
|
+
* This method is only defined when rb_iseq_type is detected at compile
|
|
94
|
+
* time via have_func in extconf.rb. On Ruby < 3.1 it is not available
|
|
95
|
+
* and callers must use an alternative (e.g. first_lineno heuristic).
|
|
96
|
+
*
|
|
97
|
+
* Possible return values: :top, :method, :block, :class, :rescue,
|
|
98
|
+
* :ensure, :eval, :main, :plain.
|
|
99
|
+
*
|
|
100
|
+
* :top and :main represent whole-file iseqs (from require/load and the
|
|
101
|
+
* entry point script respectively). Other types represent sub-file
|
|
102
|
+
* constructs (method definitions, class bodies, blocks, etc.).
|
|
103
|
+
*
|
|
104
|
+
* Used by CodeTracker#backfill_registry to distinguish whole-file iseqs
|
|
105
|
+
* from per-method/block/class iseqs when populating the registry from
|
|
106
|
+
* the object space.
|
|
107
|
+
*
|
|
108
|
+
* @param iseq [RubyVM::InstructionSequence] The instruction sequence
|
|
109
|
+
* @return [Symbol] The iseq type
|
|
110
|
+
*/
|
|
111
|
+
static VALUE iseq_type(DDTRACE_UNUSED VALUE _self, VALUE iseq_val) {
|
|
112
|
+
const void *iseq = rb_iseqw_to_iseq(iseq_val);
|
|
113
|
+
if (!iseq) return Qnil;
|
|
114
|
+
return rb_iseq_type(iseq);
|
|
115
|
+
}
|
|
116
|
+
#endif
|
|
117
|
+
|
|
118
|
+
void di_init(VALUE datadog_module) {
|
|
119
|
+
id_mesg = rb_intern("mesg");
|
|
120
|
+
|
|
121
|
+
VALUE di_module = rb_define_module_under(datadog_module, "DI");
|
|
122
|
+
rb_define_singleton_method(di_module, "all_iseqs", all_iseqs, 0);
|
|
123
|
+
rb_define_singleton_method(di_module, "exception_message", exception_message, 1);
|
|
124
|
+
#ifdef HAVE_RB_ISEQ_TYPE
|
|
125
|
+
rb_define_singleton_method(di_module, "iseq_type", iseq_type, 1);
|
|
126
|
+
#endif
|
|
127
|
+
}
|
|
@@ -31,6 +31,11 @@ libdatadog_issue = Datadog::LibdatadogExtconfHelpers.load_libdatadog_or_get_issu
|
|
|
31
31
|
skip_building_extension!("issue setting up `libdatadog` gem: #{libdatadog_issue}") if libdatadog_issue
|
|
32
32
|
|
|
33
33
|
require 'mkmf'
|
|
34
|
+
Datadog::LibdatadogExtconfHelpers.dump_mkmf_log_on_failure!
|
|
35
|
+
|
|
36
|
+
# We must *never* `append_cflags "-Wall"` or `append_cflags "-Wextra"`, because those add the flag at the end,
|
|
37
|
+
# which then overrides earlier -Wno-* flags from RbConfig::CONFIG["warnflags"], and causes errors if -Werror is added.
|
|
38
|
+
# There is no need to add them anyway, Ruby since 1.9 has RbConfig::CONFIG["warnflags"] starting with "-Wall -Wextra ".
|
|
34
39
|
|
|
35
40
|
# Because we can't control what compiler versions our customers use, shipping with -Werror by default is a no-go.
|
|
36
41
|
# But we can enable it in CI, so that we quickly spot any new warnings that just got introduced.
|
|
@@ -64,10 +69,6 @@ append_cflags '-fvisibility=hidden'
|
|
|
64
69
|
# Avoid legacy C definitions
|
|
65
70
|
append_cflags '-Wold-style-definition'
|
|
66
71
|
|
|
67
|
-
# Enable all other compiler warnings
|
|
68
|
-
append_cflags '-Wall'
|
|
69
|
-
append_cflags '-Wextra'
|
|
70
|
-
|
|
71
72
|
if ENV['DDTRACE_DEBUG'] == 'true'
|
|
72
73
|
$defs << '-DDD_DEBUG'
|
|
73
74
|
CONFIG['optflags'] = '-O0'
|
|
@@ -81,12 +82,16 @@ unless Datadog::LibdatadogExtconfHelpers.configure_libdatadog(extconf_folder: __
|
|
|
81
82
|
skip_building_extension!('there was a problem in setting up the `libdatadog` dependency')
|
|
82
83
|
end
|
|
83
84
|
|
|
85
|
+
Datadog::LibdatadogExtconfHelpers.add_libdatadog_version_define
|
|
86
|
+
|
|
84
87
|
# Tag the native extension library with the Ruby version and Ruby platform.
|
|
85
88
|
# This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
|
|
86
89
|
# the wrong library is never loaded.
|
|
87
90
|
# When requiring, we need to use the exact same string, including the version and the platform.
|
|
88
91
|
EXTENSION_NAME = "libdatadog_api.#{RUBY_VERSION[/\d+.\d+/]}_#{RUBY_PLATFORM}".freeze
|
|
89
92
|
|
|
93
|
+
have_func('rb_iseq_type')
|
|
94
|
+
|
|
90
95
|
create_makefile(EXTENSION_NAME)
|
|
91
96
|
|
|
92
97
|
# rubocop:enable Style/GlobalVars
|
data/ext/libdatadog_api/init.c
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
2
|
|
|
3
3
|
#include "datadog_ruby_common.h"
|
|
4
|
+
|
|
4
5
|
#include "crashtracker.h"
|
|
5
|
-
#include "process_discovery.h"
|
|
6
|
-
#include "library_config.h"
|
|
7
6
|
#include "feature_flags.h"
|
|
7
|
+
#include "library_config.h"
|
|
8
|
+
#include "process_discovery.h"
|
|
8
9
|
|
|
9
10
|
void ddsketch_init(VALUE core_module);
|
|
11
|
+
void di_init(VALUE datadog_module);
|
|
10
12
|
|
|
11
13
|
void DDTRACE_EXPORT Init_libdatadog_api(void) {
|
|
12
14
|
VALUE datadog_module = rb_define_module("Datadog");
|
|
@@ -21,4 +23,5 @@ void DDTRACE_EXPORT Init_libdatadog_api(void) {
|
|
|
21
23
|
library_config_init(core_module);
|
|
22
24
|
ddsketch_init(core_module);
|
|
23
25
|
feature_flags_init(core_module);
|
|
26
|
+
di_init(datadog_module);
|
|
24
27
|
}
|
|
@@ -10,7 +10,7 @@ module Datadog
|
|
|
10
10
|
module LibdatadogExtconfHelpers
|
|
11
11
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
|
12
12
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
|
13
|
-
LIBDATADOG_VERSION = '~>
|
|
13
|
+
LIBDATADOG_VERSION = '~> 30.0.0.1.0'
|
|
14
14
|
|
|
15
15
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
|
16
16
|
# libdatadog are moved after the extension gets compiled.
|
|
@@ -162,6 +162,51 @@ module Datadog
|
|
|
162
162
|
end
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
+
# Adds a C preprocessor define with the libdatadog version used at compile time.
|
|
166
|
+
# This allows runtime verification that the loaded libdatadog matches what was compiled against.
|
|
167
|
+
# rubocop:disable Style/GlobalVars
|
|
168
|
+
def self.add_libdatadog_version_define
|
|
169
|
+
$defs << %(-DEXPECTED_LIBDATADOG_VERSION=\\"#{Libdatadog::VERSION}\\")
|
|
170
|
+
end
|
|
171
|
+
# rubocop:enable Style/GlobalVars
|
|
172
|
+
|
|
173
|
+
# When setting up the extension build fails (e.g. a missing header), the actual failure ends up in mkmf.log
|
|
174
|
+
# and is not printed, which is confusing and complicates debugging. To fix that, this monkey patch actually
|
|
175
|
+
# prints the failure.
|
|
176
|
+
def self.dump_mkmf_log_on_failure!
|
|
177
|
+
# Doesn't work on 2.5/2.6 and not worth extra complexity to support
|
|
178
|
+
return if RUBY_VERSION < '2.7'
|
|
179
|
+
|
|
180
|
+
MakeMakefile.prepend(DumpMkmfLogOnFailure)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# rubocop:disable Style/GlobalVars,Style/StderrPuts
|
|
184
|
+
# See `dump_mkmf_log_on_failure!` for details.
|
|
185
|
+
module DumpMkmfLogOnFailure
|
|
186
|
+
def mkmf_failed(path)
|
|
187
|
+
unless $makefile_created || File.exist?('Makefile')
|
|
188
|
+
log_path = File.expand_path('mkmf.log')
|
|
189
|
+
if File.exist?(log_path)
|
|
190
|
+
# The full log is very verbose so let's grab only the last check which should be the one that failed
|
|
191
|
+
entries = File.read(log_path).split(/^-{20}$\n?/)
|
|
192
|
+
last_entry = entries.reverse.find { |e| !e.strip.empty? } || ''
|
|
193
|
+
|
|
194
|
+
$stderr.puts(
|
|
195
|
+
"+------------------------------------------------------------------------------+\n" \
|
|
196
|
+
"| There was an issue setting up extension build: |\n" \
|
|
197
|
+
"+------------------------------------------------------------------------------+" \
|
|
198
|
+
"#{last_entry.chomp}" \
|
|
199
|
+
"+------------------------------------------------------------------------------+\n" \
|
|
200
|
+
"| Full failure log is at #{log_path}\n" \
|
|
201
|
+
"+------------------------------------------------------------------------------+\n" \
|
|
202
|
+
)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
super
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
# rubocop:enable Style/GlobalVars,Style/StderrPuts
|
|
209
|
+
|
|
165
210
|
# Note: This helper is currently only used in the `libdatadog_api/extconf.rb` BUT still lives here to enable testing.
|
|
166
211
|
def self.load_libdatadog_or_get_issue
|
|
167
212
|
try_loading_libdatadog do |exception|
|