datadog 2.38.0 → 2.47.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 +279 -35
- data/README.md +3 -0
- data/bin/ddprofrb +4 -4
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +12 -24
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +256 -117
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -5
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +0 -2
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +19 -20
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +5 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +267 -171
- data/ext/datadog_profiling_native_extension/collectors_stack.h +17 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +307 -217
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -5
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +5 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +19 -11
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +7 -10
- data/ext/datadog_profiling_native_extension/extconf.rb +68 -100
- data/ext/datadog_profiling_native_extension/heap_recorder.c +353 -257
- data/ext/datadog_profiling_native_extension/heap_recorder.h +50 -31
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -27
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +853 -496
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +42 -15
- data/ext/datadog_profiling_native_extension/profiling.c +30 -23
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +4 -80
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -7
- data/ext/datadog_profiling_native_extension/stack_recorder.c +116 -89
- data/ext/datadog_profiling_native_extension/stack_recorder.h +12 -5
- data/ext/datadog_profiling_native_extension/time_helpers.c +2 -4
- data/ext/datadog_profiling_native_extension/time_helpers.h +15 -15
- data/ext/libdatadog_api/datadog_ruby_common.c +19 -11
- data/ext/libdatadog_api/datadog_ruby_common.h +7 -10
- data/ext/libdatadog_api/di.c +43 -3
- data/ext/libdatadog_api/extconf.rb +29 -24
- data/ext/libdatadog_api/feature_flags.c +34 -0
- data/ext/libdatadog_api/init.c +9 -1
- data/ext/libdatadog_api/otel_thread_context.c +274 -0
- data/ext/libdatadog_api/otel_thread_context.h +5 -0
- data/ext/libdatadog_api/process_discovery.c +15 -1
- data/ext/libdatadog_api/trace_exporter.c +2078 -0
- data/ext/libdatadog_api/trace_exporter.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +22 -17
- data/lib/datadog/ai_guard/component.rb +24 -15
- data/lib/datadog/ai_guard/configuration/ext.rb +2 -0
- data/lib/datadog/ai_guard/configuration.rb +13 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +48 -55
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +1 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +135 -0
- data/lib/datadog/ai_guard/evaluation/client.rb +50 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +12 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -7
- data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +6 -6
- data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +8 -64
- data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +11 -18
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +15 -2
- data/lib/datadog/ai_guard/evaluation.rb +36 -14
- data/lib/datadog/ai_guard/ext.rb +4 -1
- data/lib/datadog/ai_guard/{api_client.rb → http_client.rb} +9 -7
- data/lib/datadog/ai_guard/metrics/telemetry.rb +43 -0
- data/lib/datadog/ai_guard/redaction/replacements.rb +97 -0
- data/lib/datadog/ai_guard/redaction/result.rb +29 -0
- data/lib/datadog/ai_guard/redaction.rb +80 -0
- data/lib/datadog/ai_guard.rb +58 -57
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +22 -43
- data/lib/datadog/appsec/actions_handler.rb +6 -6
- data/lib/datadog/appsec/anonymizer.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +2 -2
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +6 -6
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +2 -2
- data/lib/datadog/appsec/api_security/route_extractor.rb +11 -11
- data/lib/datadog/appsec/api_security/sampler.rb +5 -5
- data/lib/datadog/appsec/api_security.rb +1 -1
- data/lib/datadog/appsec/assets/blocked.html +1 -108
- data/lib/datadog/appsec/assets.rb +7 -7
- data/lib/datadog/appsec/autoload.rb +3 -3
- data/lib/datadog/appsec/component.rb +15 -15
- data/lib/datadog/appsec/compressed_json.rb +6 -6
- data/lib/datadog/appsec/configuration.rb +70 -61
- data/lib/datadog/appsec/context.rb +7 -7
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +6 -6
- data/lib/datadog/appsec/contrib/active_record/integration.rb +4 -4
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -4
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +7 -7
- data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +2 -2
- data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +36 -34
- data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/data_extractor.rb +3 -3
- data/lib/datadog/appsec/contrib/devise/ext.rb +20 -20
- data/lib/datadog/appsec/contrib/devise/integration.rb +4 -4
- data/lib/datadog/appsec/contrib/devise/patcher.rb +8 -8
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +12 -12
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +8 -8
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +24 -9
- data/lib/datadog/appsec/contrib/excon/integration.rb +4 -4
- data/lib/datadog/appsec/contrib/excon/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +26 -26
- data/lib/datadog/appsec/contrib/faraday/integration.rb +4 -4
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +4 -4
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +22 -22
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +2 -2
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +7 -7
- data/lib/datadog/appsec/contrib/graphql/integration.rb +9 -9
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/buffered_input.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/ext.rb +29 -29
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +14 -18
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +24 -24
- data/lib/datadog/appsec/contrib/rack/input_peeker.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/integration.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/patcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +11 -8
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +26 -26
- data/lib/datadog/appsec/contrib/rack/response_body.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/gateway/request.rb +10 -10
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +38 -11
- data/lib/datadog/appsec/contrib/rails/integration.rb +5 -5
- data/lib/datadog/appsec/contrib/rails/patcher.rb +17 -17
- data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +10 -9
- data/lib/datadog/appsec/contrib/rails/request.rb +3 -3
- data/lib/datadog/appsec/contrib/rails/request_middleware.rb +2 -1
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +5 -5
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +23 -23
- data/lib/datadog/appsec/contrib/sinatra/gateway/request.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/route_params.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +28 -16
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +5 -5
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +11 -11
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +10 -9
- data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +2 -1
- data/lib/datadog/appsec/counter_sampler.rb +1 -1
- data/lib/datadog/appsec/event.rb +14 -14
- data/lib/datadog/appsec/ext.rb +11 -11
- data/lib/datadog/appsec/extensions.rb +2 -2
- data/lib/datadog/appsec/instrumentation/gateway.rb +1 -1
- data/lib/datadog/appsec/metrics/exporter.rb +8 -8
- data/lib/datadog/appsec/metrics/telemetry.rb +7 -7
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +4 -4
- data/lib/datadog/appsec/metrics.rb +4 -4
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +16 -12
- data/lib/datadog/appsec/monitor.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +32 -32
- data/lib/datadog/appsec/rate_limiter.rb +1 -1
- data/lib/datadog/appsec/remote.rb +6 -6
- data/lib/datadog/appsec/response.rb +22 -22
- data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +11 -11
- data/lib/datadog/appsec/route_normalizer/route_pattern.rb +18 -18
- data/lib/datadog/appsec/route_normalizer/route_text.rb +3 -3
- data/lib/datadog/appsec/route_normalizer.rb +15 -15
- data/lib/datadog/appsec/security_engine/engine.rb +41 -40
- data/lib/datadog/appsec/security_engine/runner.rb +2 -2
- data/lib/datadog/appsec/security_event.rb +2 -2
- data/lib/datadog/appsec/utils/http/body.rb +11 -8
- data/lib/datadog/appsec/utils/http/body_reader.rb +1 -1
- data/lib/datadog/appsec/utils/http/media_range.rb +15 -15
- data/lib/datadog/appsec/utils/http/media_type.rb +4 -4
- data/lib/datadog/appsec/utils/http/url_encoded.rb +80 -25
- data/lib/datadog/appsec.rb +16 -16
- data/lib/datadog/auto_instrument.rb +2 -2
- data/lib/datadog/core/buffer/cruby.rb +1 -1
- data/lib/datadog/core/buffer/thread_safe.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +15 -15
- data/lib/datadog/core/configuration/base.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +82 -47
- data/lib/datadog/core/configuration/components_state.rb +8 -1
- data/lib/datadog/core/configuration/config_helper.rb +3 -3
- data/lib/datadog/core/configuration/deprecations.rb +6 -6
- data/lib/datadog/core/configuration/ext.rb +11 -11
- data/lib/datadog/core/configuration/option.rb +16 -16
- data/lib/datadog/core/configuration/option_definition.rb +5 -5
- data/lib/datadog/core/configuration/options.rb +2 -2
- data/lib/datadog/core/configuration/settings.rb +95 -100
- data/lib/datadog/core/configuration/stable_config.rb +1 -1
- data/lib/datadog/core/configuration/supported_configurations.rb +20 -3
- data/lib/datadog/core/configuration.rb +8 -8
- data/lib/datadog/core/contrib/rails/railtie.rb +3 -3
- data/lib/datadog/core/crashtracking/component.rb +14 -10
- data/lib/datadog/core/crashtracking/tag_builder.rb +5 -5
- data/lib/datadog/core/deprecations.rb +1 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +42 -7
- data/lib/datadog/core/diagnostics/health.rb +2 -2
- data/lib/datadog/core/encoding.rb +4 -4
- data/lib/datadog/core/environment/agent_info.rb +2 -2
- data/lib/datadog/core/environment/cgroup.rb +4 -4
- data/lib/datadog/core/environment/container.rb +9 -9
- data/lib/datadog/core/environment/execution.rb +3 -3
- data/lib/datadog/core/environment/ext.rb +18 -18
- data/lib/datadog/core/environment/gc.rb +1 -1
- data/lib/datadog/core/environment/git.rb +2 -2
- data/lib/datadog/core/environment/identity.rb +10 -10
- data/lib/datadog/core/environment/platform.rb +8 -8
- data/lib/datadog/core/environment/process.rb +3 -3
- data/lib/datadog/core/environment/socket.rb +2 -2
- data/lib/datadog/core/environment/variable_helpers.rb +1 -1
- data/lib/datadog/core/environment/vm_cache.rb +1 -1
- data/lib/datadog/core/environment/yjit.rb +2 -2
- data/lib/datadog/core/error.rb +5 -5
- data/lib/datadog/core/evp.rb +2 -2
- data/lib/datadog/core/extensions.rb +1 -1
- data/lib/datadog/core/feature_flags.rb +2 -2
- data/lib/datadog/core/git/ext.rb +4 -4
- data/lib/datadog/core/logger.rb +3 -3
- data/lib/datadog/core/logging/ext.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +20 -20
- data/lib/datadog/core/metrics/ext.rb +5 -5
- data/lib/datadog/core/metrics/helpers.rb +1 -1
- data/lib/datadog/core/metrics/logging.rb +2 -2
- data/lib/datadog/core/metrics/options.rb +5 -5
- data/lib/datadog/core/pin.rb +1 -1
- data/lib/datadog/core/process_discovery.rb +13 -9
- data/lib/datadog/core/rate_limiter.rb +1 -1
- data/lib/datadog/core/remote/client/capabilities.rb +60 -33
- data/lib/datadog/core/remote/client.rb +61 -20
- data/lib/datadog/core/remote/component.rb +48 -17
- data/lib/datadog/core/remote/configuration/content.rb +3 -3
- data/lib/datadog/core/remote/configuration/digest.rb +1 -1
- data/lib/datadog/core/remote/configuration/path.rb +9 -9
- data/lib/datadog/core/remote/configuration/repository.rb +4 -4
- data/lib/datadog/core/remote/configuration/target.rb +9 -9
- data/lib/datadog/core/remote/configuration.rb +4 -4
- data/lib/datadog/core/remote/dispatcher.rb +47 -6
- data/lib/datadog/core/remote/ext.rb +3 -3
- data/lib/datadog/core/remote/negotiation.rb +1 -1
- data/lib/datadog/core/remote/tie/tracing.rb +7 -7
- data/lib/datadog/core/remote/transport/config.rb +4 -4
- data/lib/datadog/core/remote/transport/http/config.rb +7 -7
- data/lib/datadog/core/remote/transport/http/negotiation.rb +4 -4
- data/lib/datadog/core/remote/transport/http.rb +10 -10
- data/lib/datadog/core/remote/transport/negotiation.rb +3 -3
- data/lib/datadog/core/remote/worker.rb +13 -5
- data/lib/datadog/core/runtime/ext.rb +22 -22
- data/lib/datadog/core/runtime/metrics.rb +9 -9
- data/lib/datadog/core/tag_builder.rb +18 -18
- data/lib/datadog/core/tag_normalizer.rb +7 -7
- data/lib/datadog/core/telemetry/component.rb +13 -13
- data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
- data/lib/datadog/core/telemetry/emitter.rb +4 -4
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +8 -6
- data/lib/datadog/core/telemetry/event/app_closing.rb +2 -2
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +2 -2
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +3 -3
- data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +2 -2
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +2 -2
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +2 -2
- data/lib/datadog/core/telemetry/event/app_started.rb +36 -55
- data/lib/datadog/core/telemetry/event/base.rb +1 -1
- data/lib/datadog/core/telemetry/event/distributions.rb +2 -2
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +3 -3
- data/lib/datadog/core/telemetry/event/log.rb +6 -6
- data/lib/datadog/core/telemetry/event/message_batch.rb +1 -1
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +3 -3
- data/lib/datadog/core/telemetry/event.rb +16 -16
- data/lib/datadog/core/telemetry/ext.rb +11 -11
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/logging.rb +5 -5
- data/lib/datadog/core/telemetry/metric.rb +9 -9
- data/lib/datadog/core/telemetry/metrics_collection.rb +2 -2
- data/lib/datadog/core/telemetry/metrics_manager.rb +1 -1
- data/lib/datadog/core/telemetry/request.rb +6 -6
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +14 -14
- data/lib/datadog/core/telemetry/transport/http.rb +7 -7
- data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -3
- data/lib/datadog/core/telemetry/worker.rb +6 -6
- data/lib/datadog/core/transport/ext.rb +14 -14
- data/lib/datadog/core/transport/http/adapters/net.rb +4 -4
- data/lib/datadog/core/transport/http/adapters/test.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +4 -4
- data/lib/datadog/core/transport/http/api/endpoint.rb +1 -1
- data/lib/datadog/core/transport/http/api/map.rb +1 -1
- data/lib/datadog/core/transport/http/builder.rb +5 -5
- data/lib/datadog/core/transport/http/client.rb +2 -2
- data/lib/datadog/core/transport/http/response.rb +1 -1
- data/lib/datadog/core/transport/http.rb +9 -9
- data/lib/datadog/core/transport/transport.rb +2 -2
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +172 -20
- data/lib/datadog/core/utils/base64_codec.rb +3 -3
- data/lib/datadog/core/utils/duration.rb +1 -1
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/lru_cache.rb +3 -3
- data/lib/datadog/core/utils/network.rb +11 -11
- data/lib/datadog/core/utils/only_once_successful.rb +1 -1
- data/lib/datadog/core/utils/safe_dup.rb +2 -1
- data/lib/datadog/core/utils/sequence.rb +3 -6
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +2 -2
- data/lib/datadog/core/utils/time.rb +16 -54
- data/lib/datadog/core/utils/url.rb +1 -1
- data/lib/datadog/core/utils.rb +4 -4
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core/workers/polling.rb +2 -2
- data/lib/datadog/core/workers/runtime_metrics.rb +5 -5
- data/lib/datadog/core.rb +4 -4
- data/lib/datadog/data_streams/configuration.rb +3 -3
- data/lib/datadog/data_streams/ext.rb +1 -1
- data/lib/datadog/data_streams/extensions.rb +2 -2
- data/lib/datadog/data_streams/pathway_context.rb +25 -27
- data/lib/datadog/data_streams/processor.rb +92 -61
- data/lib/datadog/data_streams/transport/http/stats.rb +5 -5
- data/lib/datadog/data_streams/transport/http.rb +5 -5
- data/lib/datadog/data_streams/transport/stats.rb +7 -7
- data/lib/datadog/data_streams.rb +5 -5
- data/lib/datadog/di/base.rb +4 -4
- data/lib/datadog/di/boot.rb +26 -25
- data/lib/datadog/di/capture_expression_evaluator/result.rb +30 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +39 -9
- data/lib/datadog/di/code_tracker.rb +6 -6
- data/lib/datadog/di/component.rb +119 -6
- data/lib/datadog/di/configuration.rb +54 -3
- data/lib/datadog/di/context.rb +7 -2
- data/lib/datadog/di/contrib/active_record.rb +8 -2
- data/lib/datadog/di/contrib/railtie.rb +1 -1
- data/lib/datadog/di/contrib.rb +5 -5
- data/lib/datadog/di/el/compiler.rb +113 -37
- data/lib/datadog/di/el/evaluator.rb +82 -2
- data/lib/datadog/di/el/expression.rb +13 -2
- data/lib/datadog/di/el.rb +3 -3
- data/lib/datadog/di/evaluation_failure.rb +28 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +87 -0
- data/lib/datadog/di/guardrails_telemetry.rb +203 -0
- data/lib/datadog/di/instrumenter.rb +124 -23
- data/lib/datadog/di/logger.rb +32 -10
- data/lib/datadog/di/preload.rb +1 -1
- data/lib/datadog/di/probe.rb +9 -1
- data/lib/datadog/di/probe_builder.rb +25 -24
- data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +5 -5
- data/lib/datadog/di/probe_manager.rb +57 -9
- data/lib/datadog/di/probe_notification_builder.rb +46 -43
- data/lib/datadog/di/probe_notifier_worker.rb +62 -12
- data/lib/datadog/di/probe_repository.rb +1 -1
- data/lib/datadog/di/proc_responder.rb +1 -1
- data/lib/datadog/di/remote.rb +52 -8
- data/lib/datadog/di/serializer.rb +185 -68
- data/lib/datadog/di/snapshot_event.rb +38 -0
- data/lib/datadog/di/transport/diagnostics.rb +5 -5
- data/lib/datadog/di/transport/http/diagnostics.rb +3 -3
- data/lib/datadog/di/transport/http/input.rb +2 -2
- data/lib/datadog/di/transport/http.rb +23 -13
- data/lib/datadog/di/transport/input.rb +41 -16
- data/lib/datadog/di/utils.rb +4 -4
- data/lib/datadog/di.rb +5 -5
- data/lib/datadog/error_tracking/collector.rb +2 -2
- data/lib/datadog/error_tracking/component.rb +12 -12
- data/lib/datadog/error_tracking/configuration.rb +2 -2
- data/lib/datadog/error_tracking/ext.rb +7 -7
- data/lib/datadog/error_tracking/extensions.rb +2 -2
- data/lib/datadog/error_tracking/filters.rb +4 -4
- data/lib/datadog/error_tracking.rb +6 -6
- data/lib/datadog/kit/appsec/events/v2.rb +40 -40
- data/lib/datadog/kit/appsec/events.rb +25 -25
- data/lib/datadog/kit/enable_core_dumps.rb +2 -2
- data/lib/datadog/kit/identity.rb +18 -18
- data/lib/datadog/kit/tracing/method_tracer.rb +7 -7
- data/lib/datadog/kit.rb +1 -1
- data/lib/datadog/open_feature/activation.rb +268 -0
- data/lib/datadog/open_feature/agentless/configuration_source.rb +246 -0
- data/lib/datadog/open_feature/agentless/parser.rb +43 -0
- data/lib/datadog/open_feature/agentless/response.rb +19 -0
- data/lib/datadog/open_feature/agentless/transport.rb +103 -0
- data/lib/datadog/open_feature/component.rb +112 -31
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +90 -0
- data/lib/datadog/open_feature/configuration/source/resolution.rb +22 -0
- data/lib/datadog/open_feature/configuration/source.rb +43 -0
- data/lib/datadog/open_feature/configuration.rb +139 -2
- data/lib/datadog/open_feature/evaluation_engine.rb +36 -10
- data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
- data/lib/datadog/open_feature/exposures/buffer.rb +1 -1
- data/lib/datadog/open_feature/exposures/deduplicator.rb +1 -1
- data/lib/datadog/open_feature/exposures/event.rb +17 -10
- data/lib/datadog/open_feature/exposures/reporter.rb +3 -3
- data/lib/datadog/open_feature/exposures/worker.rb +6 -6
- data/lib/datadog/open_feature/ext.rb +32 -8
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +242 -86
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +211 -100
- data/lib/datadog/open_feature/hooks/evaluation_telemetry_opt_out_hook.rb +25 -0
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +28 -24
- data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +3 -1
- data/lib/datadog/open_feature/hooks/span_enrichment_hook/codec.rb +58 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook/span_enrichment_state.rb +96 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook/span_enrichment_state_store.rb +49 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +184 -0
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +24 -24
- data/lib/datadog/open_feature/native_evaluator.rb +24 -10
- data/lib/datadog/open_feature/noop_evaluator.rb +8 -3
- data/lib/datadog/open_feature/provider.rb +357 -17
- data/lib/datadog/open_feature/remote.rb +7 -7
- data/lib/datadog/open_feature/resolution_details.rb +4 -2
- data/lib/datadog/open_feature/transport.rb +19 -14
- data/lib/datadog/open_feature.rb +33 -3
- data/lib/datadog/opentelemetry/api/baggage.rb +3 -3
- data/lib/datadog/opentelemetry/api/context.rb +4 -4
- data/lib/datadog/opentelemetry/configuration/settings.rb +41 -41
- data/lib/datadog/opentelemetry/ext.rb +1 -1
- data/lib/datadog/opentelemetry/logs.rb +5 -5
- data/lib/datadog/opentelemetry/metrics.rb +7 -7
- data/lib/datadog/opentelemetry/sdk/configurator.rb +8 -8
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +2 -2
- data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +6 -6
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +5 -5
- data/lib/datadog/opentelemetry/sdk/propagator.rb +8 -8
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -15
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +32 -32
- data/lib/datadog/opentelemetry/sdk.rb +2 -2
- data/lib/datadog/opentelemetry/signal_configuration.rb +20 -16
- data/lib/datadog/opentelemetry/trace.rb +4 -1
- data/lib/datadog/opentelemetry.rb +8 -8
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +10 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +5 -7
- data/lib/datadog/profiling/collectors/info.rb +40 -13
- data/lib/datadog/profiling/collectors/thread_context.rb +6 -17
- data/lib/datadog/profiling/component.rb +33 -39
- data/lib/datadog/profiling/exporter.rb +11 -11
- data/lib/datadog/profiling/http_transport.rb +1 -1
- data/lib/datadog/profiling/sequence_tracker.rb +1 -1
- data/lib/datadog/profiling/tag_builder.rb +19 -19
- data/lib/datadog/profiling/tasks/exec.rb +1 -1
- data/lib/datadog/profiling.rb +31 -27
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/symbol_database/component.rb +15 -15
- data/lib/datadog/symbol_database/configuration.rb +3 -3
- data/lib/datadog/symbol_database/extensions.rb +2 -2
- data/lib/datadog/symbol_database/extractor.rb +141 -159
- data/lib/datadog/symbol_database/file_hash.rb +3 -3
- data/lib/datadog/symbol_database/logger.rb +1 -1
- data/lib/datadog/symbol_database/remote.rb +21 -6
- data/lib/datadog/symbol_database/scope.rb +2 -2
- data/lib/datadog/symbol_database/scope_batcher.rb +2 -2
- data/lib/datadog/symbol_database/service_version.rb +4 -4
- data/lib/datadog/symbol_database/symbol.rb +1 -1
- data/lib/datadog/symbol_database/transport/http/endpoint.rb +1 -1
- data/lib/datadog/symbol_database/transport/http.rb +6 -6
- data/lib/datadog/symbol_database/transport.rb +4 -4
- data/lib/datadog/symbol_database/uploader.rb +22 -22
- data/lib/datadog/symbol_database.rb +2 -2
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +5 -5
- data/lib/datadog/tracing/client_ip.rb +4 -4
- data/lib/datadog/tracing/component.rb +51 -9
- data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +13 -11
- data/lib/datadog/tracing/configuration/ext.rb +46 -42
- data/lib/datadog/tracing/configuration/http.rb +2 -2
- data/lib/datadog/tracing/configuration/settings.rb +52 -16
- data/lib/datadog/tracing/context.rb +25 -3
- data/lib/datadog/tracing/context_provider.rb +19 -7
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_cable/event.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/events.rb +5 -5
- data/lib/datadog/tracing/contrib/action_cable/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/action_cable/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +3 -3
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +8 -8
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +4 -4
- data/lib/datadog/tracing/contrib/action_mailer/events.rb +3 -3
- data/lib/datadog/tracing/contrib/action_mailer/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +9 -9
- data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +10 -10
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/action_view/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +6 -6
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +6 -6
- data/lib/datadog/tracing/contrib/action_view/events.rb +3 -3
- data/lib/datadog/tracing/contrib/action_view/ext.rb +10 -10
- data/lib/datadog/tracing/contrib/action_view/integration.rb +11 -11
- data/lib/datadog/tracing/contrib/action_view/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/action_view/utils.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/data_streams.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/event.rb +3 -3
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +5 -5
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +5 -5
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +5 -5
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +5 -5
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +5 -5
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +5 -5
- data/lib/datadog/tracing/contrib/active_job/events.rb +6 -6
- data/lib/datadog/tracing/contrib/active_job/ext.rb +23 -23
- data/lib/datadog/tracing/contrib/active_job/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +7 -7
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +4 -4
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +6 -6
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +6 -6
- data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +3 -3
- data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +10 -10
- data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/active_record/configuration/makara_resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +7 -7
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/active_record/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +8 -8
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +10 -9
- data/lib/datadog/tracing/contrib/active_record/events.rb +3 -3
- data/lib/datadog/tracing/contrib/active_record/ext.rb +15 -15
- data/lib/datadog/tracing/contrib/active_record/integration.rb +11 -11
- data/lib/datadog/tracing/contrib/active_record/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/utils.rb +3 -3
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +12 -12
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/active_support/ext.rb +16 -16
- data/lib/datadog/tracing/contrib/active_support/integration.rb +8 -8
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/analytics.rb +1 -1
- data/lib/datadog/tracing/contrib/auto_instrument.rb +4 -4
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/ext.rb +26 -26
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -5
- data/lib/datadog/tracing/contrib/aws/integration.rb +9 -9
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +4 -4
- data/lib/datadog/tracing/contrib/aws/service/s3.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/service/sns.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/service/sqs.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/service/states.rb +5 -5
- data/lib/datadog/tracing/contrib/aws/services.rb +14 -14
- data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/configurable.rb +2 -2
- data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/dalli/ext.rb +13 -13
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +5 -5
- data/lib/datadog/tracing/contrib/dalli/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/dalli/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +2 -2
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +14 -14
- data/lib/datadog/tracing/contrib/delayed_job/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +5 -5
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +15 -15
- data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +10 -10
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +3 -3
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +18 -13
- data/lib/datadog/tracing/contrib/ethon/ext.rb +13 -13
- data/lib/datadog/tracing/contrib/ethon/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +3 -3
- data/lib/datadog/tracing/contrib/ethon/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +5 -5
- data/lib/datadog/tracing/contrib/excon/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/excon/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/excon/middleware.rb +17 -10
- data/lib/datadog/tracing/contrib/excon/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/extensions.rb +2 -2
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/faraday/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/faraday/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +17 -11
- data/lib/datadog/tracing/contrib/faraday/patcher.rb +6 -6
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +51 -24
- data/lib/datadog/tracing/contrib/grape/ext.rb +15 -15
- data/lib/datadog/tracing/contrib/grape/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/grape/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/grape/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +1 -1
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/ext.rb +9 -9
- data/lib/datadog/tracing/contrib/graphql/integration.rb +9 -9
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +7 -7
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +37 -37
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +8 -8
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +8 -8
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +6 -6
- data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +9 -9
- data/lib/datadog/tracing/contrib/grpc/ext.rb +14 -14
- data/lib/datadog/tracing/contrib/grpc/formatting.rb +7 -7
- data/lib/datadog/tracing/contrib/grpc/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/grpc/intercept_with_datadog.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc.rb +6 -6
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +3 -3
- data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/hanami/ext.rb +8 -8
- data/lib/datadog/tracing/contrib/hanami/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/hanami/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +3 -3
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +5 -4
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +1 -1
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +3 -3
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +8 -8
- data/lib/datadog/tracing/contrib/http/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +22 -7
- data/lib/datadog/tracing/contrib/http/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/http/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/http.rb +6 -6
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +13 -7
- data/lib/datadog/tracing/contrib/httpclient/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +4 -4
- data/lib/datadog/tracing/contrib/httprb/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +16 -10
- data/lib/datadog/tracing/contrib/httprb/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/event.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +7 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +10 -5
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +10 -5
- data/lib/datadog/tracing/contrib/kafka/events.rb +10 -10
- data/lib/datadog/tracing/contrib/kafka/ext.rb +40 -40
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +9 -9
- data/lib/datadog/tracing/contrib/karafka/ext.rb +13 -13
- data/lib/datadog/tracing/contrib/karafka/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +14 -14
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +8 -8
- data/lib/datadog/tracing/contrib/karafka.rb +6 -6
- data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/lograge/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +9 -9
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +5 -5
- data/lib/datadog/tracing/contrib/mongodb/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +13 -13
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/mysql2/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/mysql2/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +23 -23
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -13
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +4 -4
- data/lib/datadog/tracing/contrib/patchable.rb +1 -1
- data/lib/datadog/tracing/contrib/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/pg/ext.rb +19 -19
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/pg/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/pg/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/presto/ext.rb +21 -21
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/presto/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/presto/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +2 -2
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +17 -17
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +1 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +5 -5
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/que/ext.rb +19 -19
- data/lib/datadog/tracing/contrib/que/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/que/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/event.rb +4 -4
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/events/consume.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/events.rb +4 -4
- data/lib/datadog/tracing/contrib/racecar/ext.rb +18 -18
- data/lib/datadog/tracing/contrib/racecar/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/racecar/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/ext.rb +33 -33
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +4 -4
- data/lib/datadog/tracing/contrib/rack/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +24 -24
- data/lib/datadog/tracing/contrib/rack/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +11 -11
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +16 -16
- data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/rails/ext.rb +15 -15
- data/lib/datadog/tracing/contrib/rails/framework.rb +11 -11
- data/lib/datadog/tracing/contrib/rails/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +8 -8
- data/lib/datadog/tracing/contrib/rails/railtie.rb +4 -4
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/rake/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/rake/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/rake/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +3 -3
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/ext.rb +16 -16
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/redis/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/redis/patcher.rb +10 -10
- data/lib/datadog/tracing/contrib/redis/quantize.rb +39 -5
- data/lib/datadog/tracing/contrib/redis/tags.rb +5 -5
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +14 -8
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/resque/ext.rb +7 -7
- data/lib/datadog/tracing/contrib/resque/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/resque/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/resque/resque_job.rb +5 -5
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +10 -10
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/rest_client/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +15 -8
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/roda/ext.rb +6 -6
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/roda/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/roda/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sequel/database.rb +6 -10
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +5 -5
- data/lib/datadog/tracing/contrib/sequel/ext.rb +12 -8
- data/lib/datadog/tracing/contrib/sequel/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
- data/lib/datadog/tracing/contrib/sequel/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/sequel/utils.rb +101 -9
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/shoryuken/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/shoryuken/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +8 -8
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +10 -10
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +30 -30
- data/lib/datadog/tracing/contrib/sidekiq/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +8 -8
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +13 -13
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +9 -9
- data/lib/datadog/tracing/contrib/sidekiq.rb +6 -6
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/sinatra/env.rb +6 -6
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +17 -17
- data/lib/datadog/tracing/contrib/sinatra/framework.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +10 -10
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +8 -8
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/sneakers/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/sneakers/integration.rb +7 -7
- data/lib/datadog/tracing/contrib/sneakers/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +4 -4
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +2 -2
- data/lib/datadog/tracing/contrib/status_range_env_parser.rb +2 -2
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +1 -1
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/stripe/ext.rb +12 -12
- data/lib/datadog/tracing/contrib/stripe/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/stripe/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -3
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sucker_punch/exception_handler.rb +1 -1
- data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +13 -13
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/trilogy/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/trilogy/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/trilogy/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/utils/database.rb +5 -5
- data/lib/datadog/tracing/contrib/utils/quantization/hash_formatter.rb +2 -2
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +118 -13
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +9 -9
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +4 -4
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +7 -7
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +3 -3
- data/lib/datadog/tracing/contrib/waterdrop.rb +6 -6
- data/lib/datadog/tracing/contrib.rb +54 -54
- data/lib/datadog/tracing/correlation.rb +12 -12
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +12 -11
- data/lib/datadog/tracing/diagnostics/ext.rb +19 -19
- data/lib/datadog/tracing/diagnostics/health.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +8 -8
- data/lib/datadog/tracing/distributed/b3_single.rb +4 -4
- data/lib/datadog/tracing/distributed/baggage.rb +27 -29
- data/lib/datadog/tracing/distributed/datadog.rb +23 -23
- data/lib/datadog/tracing/distributed/fetcher.rb +1 -1
- data/lib/datadog/tracing/distributed/helpers.rb +3 -3
- data/lib/datadog/tracing/distributed/propagation.rb +15 -12
- data/lib/datadog/tracing/distributed/propagation_policy.rb +5 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +21 -278
- data/lib/datadog/tracing/distributed/trace_state/datadog.rb +233 -0
- data/lib/datadog/tracing/distributed/trace_state/ext.rb +44 -0
- data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +156 -0
- data/lib/datadog/tracing/distributed/trace_state.rb +121 -0
- data/lib/datadog/tracing/event.rb +1 -1
- data/lib/datadog/tracing/ext.rb +1 -1
- data/lib/datadog/tracing/metadata/analytics.rb +2 -2
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/tracing/metadata/ext.rb +72 -69
- data/lib/datadog/tracing/metadata/metastruct.rb +1 -1
- data/lib/datadog/tracing/metadata/metastruct_tagging.rb +1 -1
- data/lib/datadog/tracing/metadata/tagging.rb +3 -3
- data/lib/datadog/tracing/metadata.rb +4 -4
- data/lib/datadog/tracing/otel_thread_context.rb +97 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/pipeline.rb +2 -2
- data/lib/datadog/tracing/remote.rb +250 -44
- data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/ext.rb +8 -8
- data/lib/datadog/tracing/sampling/matcher.rb +4 -4
- data/lib/datadog/tracing/sampling/priority_sampler.rb +4 -4
- data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +3 -3
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/rule.rb +4 -4
- data/lib/datadog/tracing/sampling/rule_sampler.rb +14 -12
- data/lib/datadog/tracing/sampling/sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/span/ext.rb +3 -3
- data/lib/datadog/tracing/sampling/span/matcher.rb +2 -2
- data/lib/datadog/tracing/sampling/span/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +8 -8
- data/lib/datadog/tracing/span.rb +9 -9
- data/lib/datadog/tracing/span_event.rb +5 -5
- data/lib/datadog/tracing/span_operation.rb +22 -22
- data/lib/datadog/tracing/sync_writer.rb +12 -7
- data/lib/datadog/tracing/trace_digest.rb +22 -4
- data/lib/datadog/tracing/trace_operation.rb +33 -21
- data/lib/datadog/tracing/trace_segment.rb +10 -10
- data/lib/datadog/tracing/tracer.rb +43 -22
- data/lib/datadog/tracing/transport/http/client.rb +4 -4
- data/lib/datadog/tracing/transport/http/statistics.rb +2 -2
- data/lib/datadog/tracing/transport/http/telemetry.rb +94 -0
- data/lib/datadog/tracing/transport/http/traces.rb +10 -8
- data/lib/datadog/tracing/transport/http.rb +10 -10
- data/lib/datadog/tracing/transport/io/client.rb +2 -2
- data/lib/datadog/tracing/transport/io/response.rb +1 -1
- data/lib/datadog/tracing/transport/io/traces.rb +5 -5
- data/lib/datadog/tracing/transport/io.rb +3 -3
- data/lib/datadog/tracing/transport/native/response.rb +71 -0
- data/lib/datadog/tracing/transport/native/telemetry.rb +17 -0
- data/lib/datadog/tracing/transport/native.rb +395 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +19 -19
- data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
- data/lib/datadog/tracing/transport/statistics.rb +2 -2
- data/lib/datadog/tracing/transport/telemetry.rb +62 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +23 -13
- data/lib/datadog/tracing/transport/traces.rb +93 -46
- data/lib/datadog/tracing/utils.rb +2 -2
- data/lib/datadog/tracing/workers.rb +2 -2
- data/lib/datadog/tracing/writer.rb +22 -9
- data/lib/datadog/tracing.rb +3 -3
- data/lib/datadog/version.rb +4 -4
- data/lib/datadog.rb +13 -13
- metadata +55 -13
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +0 -31
- data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -69
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
#include "private_vm_api_access.h"
|
|
17
17
|
#include "setup_signal_handler.h"
|
|
18
18
|
#include "time_helpers.h"
|
|
19
|
+
#include "unsafe_api_calls_check.h"
|
|
19
20
|
|
|
20
21
|
#ifdef __APPLE__
|
|
21
22
|
#include "macos_sampler_thread.h"
|
|
@@ -68,14 +69,24 @@
|
|
|
68
69
|
// 4. The Ruby VM calls our `sample_from_postponed_job` from a thread holding the global VM lock. A sample is recorded by
|
|
69
70
|
// calling `thread_context_collector_sample`.
|
|
70
71
|
//
|
|
71
|
-
//
|
|
72
|
+
//
|
|
73
|
+
// ### Hooks and TracePoints
|
|
74
|
+
//
|
|
75
|
+
// This class uses various hooks:
|
|
76
|
+
// * A RUBY_INTERNAL_EVENT_GC_ENTER & RUBY_INTERNAL_EVENT_GC_EXIT TracePoint
|
|
77
|
+
// * A RUBY_INTERNAL_EVENT_NEWOBJ "event hook"/internal tracepoint
|
|
78
|
+
// * A GVL thread event hook
|
|
79
|
+
//
|
|
80
|
+
// We refer to those collectively as "hooks".
|
|
81
|
+
//
|
|
82
|
+
// ### Hooks and Forking
|
|
72
83
|
//
|
|
73
84
|
// When the Ruby VM forks, the CPU/Wall-time profiling stops naturally because it's triggered by a background thread
|
|
74
85
|
// that doesn't get automatically restarted by the VM on the child process. (The profiler does trigger its restart at
|
|
75
86
|
// some point -- see `Profiling::Tasks::Setup` for details).
|
|
76
87
|
//
|
|
77
|
-
// But this doesn't apply to any
|
|
78
|
-
// always remember consider this case of -- the worker thread may not be alive but the
|
|
88
|
+
// But this doesn't apply to any hooks this class may use, which will continue to be active. Thus, we need to
|
|
89
|
+
// always remember consider this case of -- the worker thread may not be alive but the hooks can continue to
|
|
79
90
|
// trigger samples.
|
|
80
91
|
//
|
|
81
92
|
// ---
|
|
@@ -91,7 +102,7 @@ unsigned int MAX_ALLOC_WEIGHT = 10000;
|
|
|
91
102
|
static rb_postponed_job_handle_t sample_from_postponed_job_handle;
|
|
92
103
|
static rb_postponed_job_handle_t after_gc_from_postponed_job_handle;
|
|
93
104
|
static rb_postponed_job_handle_t after_gvl_running_from_postponed_job_handle;
|
|
94
|
-
static rb_postponed_job_handle_t
|
|
105
|
+
static rb_postponed_job_handle_t commit_heap_recordings_from_postponed_job_may_lose_gvl_handle;
|
|
95
106
|
#endif
|
|
96
107
|
|
|
97
108
|
// Contains state for a single CpuAndWallTimeWorker instance
|
|
@@ -107,9 +118,12 @@ typedef struct {
|
|
|
107
118
|
bool skip_idle_samples_for_testing;
|
|
108
119
|
bool sighandler_sampling_enabled;
|
|
109
120
|
uint32_t cpu_sampling_interval_ms;
|
|
121
|
+
// Minimum duration of a "Waiting for GVL" period to trigger a sample
|
|
122
|
+
uint32_t waiting_for_gvl_threshold_ns;
|
|
110
123
|
VALUE self_instance;
|
|
111
124
|
VALUE thread_context_collector_instance;
|
|
112
125
|
VALUE idle_sampling_helper_instance;
|
|
126
|
+
idle_sampling_loop_state *idle_sampling_helper_state;
|
|
113
127
|
VALUE owner_thread;
|
|
114
128
|
dynamic_sampling_rate_state cpu_dynamic_sampling_rate;
|
|
115
129
|
discrete_dynamic_sampler allocation_sampler;
|
|
@@ -127,13 +141,29 @@ typedef struct {
|
|
|
127
141
|
|
|
128
142
|
// Others
|
|
129
143
|
|
|
130
|
-
// Used to detect/avoid nested sampling,
|
|
131
|
-
//
|
|
132
|
-
// sampling.
|
|
144
|
+
// Used to detect/avoid nested sampling, and intended to behave as a lock to ensure the profiler doesn't recurse on itself,
|
|
145
|
+
// e.g. when on_newobj_event gets triggered by a memory allocation that happens during another sample, or when the
|
|
146
|
+
// signal handler gets triggered while we're already in the middle of sampling.
|
|
147
|
+
//
|
|
148
|
+
// It's not an actual lock because we rely on the GVL for correct synchronization
|
|
149
|
+
// (and thus this flag is only valid when we know we have the GVL).
|
|
150
|
+
// Exception: `on_gvl_event` sets it for RUBY_INTERNAL_THREAD_EVENT_RESUMED without the GVL -- see the notes there.
|
|
151
|
+
//
|
|
152
|
+
// Similar to a lock, it should not be held across long-running operations,
|
|
153
|
+
// **in particular it MUST NEVER be held during operations where we might lose the GVL**
|
|
154
|
+
// because effectively that would stop the profiler from working until control
|
|
155
|
+
// goes back to that special thread, which on a contended Ruby app, can take hundreds of ms (or more).
|
|
156
|
+
//
|
|
157
|
+
// Because what we want is "profiler doesn't recurse on itself" we want this to behave as a non-reentrant lock
|
|
158
|
+
// (FIXME: We should have checks for this)
|
|
133
159
|
//
|
|
134
160
|
// @ivoanjo: Right now we always sample inside `safely_call`; if that ever changes, this flag may need to become
|
|
135
161
|
// volatile/atomic/have some barriers to ensure it's visible during e.g. signal handlers.
|
|
136
162
|
bool during_sample;
|
|
163
|
+
// Used from the signal handler to ask for a sample at the end of GC.
|
|
164
|
+
// The GC_EXIT event is emitted by the thread that had the GVL + was doing GC, e.g. Ruby won't switch threads between
|
|
165
|
+
// this flag getting set in the signal handler and the GC_EXIT event.
|
|
166
|
+
bool prepare_sample_on_gc_finish;
|
|
137
167
|
|
|
138
168
|
#ifndef NO_GVL_INSTRUMENTATION
|
|
139
169
|
// Only set when sampling is active (gets created at start and cleaned on stop)
|
|
@@ -205,6 +235,8 @@ static VALUE _native_new(VALUE klass);
|
|
|
205
235
|
static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
|
206
236
|
static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
|
|
207
237
|
static VALUE _native_sampling_loop(VALUE self, VALUE instance);
|
|
238
|
+
static VALUE _native_profiler_internal_thread_done(VALUE self_instance);
|
|
239
|
+
static VALUE _native_prepare_serialize(DDTRACE_UNUSED VALUE self, VALUE self_instance);
|
|
208
240
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread);
|
|
209
241
|
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation);
|
|
210
242
|
static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception, const char *optional_operation_name);
|
|
@@ -223,6 +255,9 @@ static VALUE _native_remove_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
|
223
255
|
static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self);
|
|
224
256
|
static VALUE _native_gc_tracepoint(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
225
257
|
static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused);
|
|
258
|
+
static void handle_gc_event(cpu_and_wall_time_worker_state *state, rb_event_flag_t event);
|
|
259
|
+
static VALUE _native_on_gc_event(VALUE self, VALUE instance, VALUE event, VALUE during_sample);
|
|
260
|
+
static VALUE _native_request_prepare_on_gc_finish(VALUE self, VALUE instance);
|
|
226
261
|
static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
227
262
|
static VALUE safely_call(
|
|
228
263
|
VALUE (*function_to_call_safely)(VALUE),
|
|
@@ -242,12 +277,11 @@ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state);
|
|
|
242
277
|
static void sleep_for(uint64_t time_ns);
|
|
243
278
|
static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self);
|
|
244
279
|
static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2);
|
|
245
|
-
static void
|
|
280
|
+
static void disable_hooks(cpu_and_wall_time_worker_state *state);
|
|
246
281
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
|
|
247
282
|
static VALUE rescued_sample_allocation(VALUE tracepoint_data);
|
|
248
|
-
static VALUE
|
|
283
|
+
static VALUE rescued_commit_heap_recordings_may_lose_gvl(VALUE self_instance);
|
|
249
284
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
|
|
250
|
-
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state);
|
|
251
285
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
|
|
252
286
|
static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
|
|
253
287
|
static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
|
@@ -260,11 +294,12 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
|
|
260
294
|
static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
261
295
|
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
262
296
|
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception);
|
|
297
|
+
static VALUE handle_sampling_failure_thread_context_collector_heap_update(VALUE self_instance, VALUE exception);
|
|
263
298
|
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception);
|
|
264
|
-
static VALUE
|
|
299
|
+
static VALUE handle_sampling_failure_rescued_commit_heap_recordings(VALUE self_instance, VALUE exception);
|
|
265
300
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state);
|
|
266
301
|
static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
267
|
-
static void
|
|
302
|
+
static void commit_heap_recordings_from_postponed_job_may_lose_gvl(DDTRACE_UNUSED void *_unused);
|
|
268
303
|
|
|
269
304
|
// We're using `on_newobj_event` function with `rb_add_event_hook2`, which requires in its public signature a function
|
|
270
305
|
// with signature `rb_event_hook_func_t` which doesn't match `on_newobj_event`.
|
|
@@ -290,7 +325,6 @@ static void after_allocation_from_postponed_job(DDTRACE_UNUSED void *_unused);
|
|
|
290
325
|
// (e.g. signal handler) where it's impossible or just awkward to pass it as an argument.
|
|
291
326
|
static VALUE active_sampler_instance = Qnil;
|
|
292
327
|
static cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
|
|
293
|
-
static VALUE clock_failure_exception_class = Qnil;
|
|
294
328
|
|
|
295
329
|
// See handle_sampling_signal for details on what this does
|
|
296
330
|
#ifdef NO_POSTPONED_TRIGGER
|
|
@@ -312,13 +346,14 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
312
346
|
sample_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, sample_from_postponed_job, NULL);
|
|
313
347
|
after_gc_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gc_from_postponed_job, NULL);
|
|
314
348
|
after_gvl_running_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gvl_running_from_postponed_job, NULL);
|
|
315
|
-
|
|
349
|
+
commit_heap_recordings_from_postponed_job_may_lose_gvl_handle =
|
|
350
|
+
rb_postponed_job_preregister(unused_flags, commit_heap_recordings_from_postponed_job_may_lose_gvl, NULL);
|
|
316
351
|
|
|
317
352
|
if (
|
|
318
353
|
sample_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
319
354
|
after_gc_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
320
355
|
after_gvl_running_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
321
|
-
|
|
356
|
+
commit_heap_recordings_from_postponed_job_may_lose_gvl_handle == POSTPONED_JOB_HANDLE_INVALID
|
|
322
357
|
) {
|
|
323
358
|
raise_error(rb_eRuntimeError, "Failed to register profiler postponed jobs (got POSTPONED_JOB_HANDLE_INVALID)");
|
|
324
359
|
}
|
|
@@ -330,8 +365,6 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
330
365
|
VALUE collectors_cpu_and_wall_time_worker_class = rb_define_class_under(collectors_module, "CpuAndWallTimeWorker", rb_cObject);
|
|
331
366
|
// Hosts methods used for testing the native code using RSpec
|
|
332
367
|
VALUE testing_module = rb_define_module_under(collectors_cpu_and_wall_time_worker_class, "Testing");
|
|
333
|
-
clock_failure_exception_class = rb_define_class_under(collectors_cpu_and_wall_time_worker_class, "ClockFailure", rb_eRuntimeError);
|
|
334
|
-
rb_gc_register_mark_object(clock_failure_exception_class);
|
|
335
368
|
|
|
336
369
|
// Instances of the CpuAndWallTimeWorker class are "TypedData" objects.
|
|
337
370
|
// "TypedData" objects are special objects in the Ruby VM that can wrap C structs.
|
|
@@ -345,6 +378,8 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
345
378
|
|
|
346
379
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_initialize", _native_initialize, -1);
|
|
347
380
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_sampling_loop", _native_sampling_loop, 1);
|
|
381
|
+
rb_define_method(collectors_cpu_and_wall_time_worker_class, "_native_profiler_internal_thread_done", _native_profiler_internal_thread_done, 0);
|
|
382
|
+
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_prepare_serialize", _native_prepare_serialize, 1);
|
|
348
383
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stop", _native_stop, 2);
|
|
349
384
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
|
|
350
385
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_stats", _native_stats, 1);
|
|
@@ -359,6 +394,8 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
359
394
|
rb_define_singleton_method(testing_module, "_native_remove_testing_signal_handler", _native_remove_testing_signal_handler, 0);
|
|
360
395
|
rb_define_singleton_method(testing_module, "_native_trigger_sample", _native_trigger_sample, 0);
|
|
361
396
|
rb_define_singleton_method(testing_module, "_native_gc_tracepoint", _native_gc_tracepoint, 1);
|
|
397
|
+
rb_define_singleton_method(testing_module, "_native_on_gc_event", _native_on_gc_event, 3);
|
|
398
|
+
rb_define_singleton_method(testing_module, "_native_request_prepare_on_gc_finish", _native_request_prepare_on_gc_finish, 1);
|
|
362
399
|
rb_define_singleton_method(testing_module, "_native_simulate_handle_sampling_signal", _native_simulate_handle_sampling_signal, 0);
|
|
363
400
|
rb_define_singleton_method(testing_module, "_native_simulate_sample_from_postponed_job", _native_simulate_sample_from_postponed_job, 0);
|
|
364
401
|
rb_define_singleton_method(testing_module, "_native_is_sigprof_blocked_in_current_thread", _native_is_sigprof_blocked_in_current_thread, 0);
|
|
@@ -381,7 +418,7 @@ static const rb_data_type_t cpu_and_wall_time_worker_typed_data = {
|
|
|
381
418
|
};
|
|
382
419
|
|
|
383
420
|
static VALUE _native_new(VALUE klass) {
|
|
384
|
-
long now = monotonic_wall_time_now_ns(
|
|
421
|
+
long now = monotonic_wall_time_now_ns();
|
|
385
422
|
|
|
386
423
|
cpu_and_wall_time_worker_state *state = ruby_xcalloc(1, sizeof(cpu_and_wall_time_worker_state));
|
|
387
424
|
|
|
@@ -397,8 +434,10 @@ static VALUE _native_new(VALUE klass) {
|
|
|
397
434
|
state->skip_idle_samples_for_testing = false;
|
|
398
435
|
state->sighandler_sampling_enabled = false;
|
|
399
436
|
state->cpu_sampling_interval_ms = 10;
|
|
437
|
+
state->waiting_for_gvl_threshold_ns = 10 * 1000 * 1000;
|
|
400
438
|
state->thread_context_collector_instance = Qnil;
|
|
401
439
|
state->idle_sampling_helper_instance = Qnil;
|
|
440
|
+
state->idle_sampling_helper_state = NULL;
|
|
402
441
|
state->owner_thread = Qnil;
|
|
403
442
|
dynamic_sampling_rate_init(&state->cpu_dynamic_sampling_rate);
|
|
404
443
|
state->gc_tracepoint = Qnil;
|
|
@@ -442,6 +481,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
442
481
|
VALUE skip_idle_samples_for_testing = rb_hash_fetch(options, ID2SYM(rb_intern("skip_idle_samples_for_testing")));
|
|
443
482
|
VALUE sighandler_sampling_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("sighandler_sampling_enabled")));
|
|
444
483
|
VALUE cpu_sampling_interval_ms = rb_hash_fetch(options, ID2SYM(rb_intern("cpu_sampling_interval_ms")));
|
|
484
|
+
VALUE waiting_for_gvl_threshold_ns = rb_hash_fetch(options, ID2SYM(rb_intern("waiting_for_gvl_threshold_ns")));
|
|
445
485
|
|
|
446
486
|
ENFORCE_BOOLEAN(gc_profiling_enabled);
|
|
447
487
|
ENFORCE_BOOLEAN(no_signals_workaround_enabled);
|
|
@@ -453,6 +493,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
453
493
|
ENFORCE_BOOLEAN(skip_idle_samples_for_testing)
|
|
454
494
|
ENFORCE_BOOLEAN(sighandler_sampling_enabled)
|
|
455
495
|
ENFORCE_TYPE(cpu_sampling_interval_ms, T_FIXNUM);
|
|
496
|
+
ENFORCE_TYPE(waiting_for_gvl_threshold_ns, T_FIXNUM);
|
|
456
497
|
|
|
457
498
|
cpu_and_wall_time_worker_state *state;
|
|
458
499
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
@@ -466,6 +507,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
466
507
|
state->skip_idle_samples_for_testing = (skip_idle_samples_for_testing == Qtrue);
|
|
467
508
|
state->sighandler_sampling_enabled = (sighandler_sampling_enabled == Qtrue);
|
|
468
509
|
state->cpu_sampling_interval_ms = NUM2INT(cpu_sampling_interval_ms);
|
|
510
|
+
state->waiting_for_gvl_threshold_ns = NUM2UINT(waiting_for_gvl_threshold_ns);
|
|
469
511
|
|
|
470
512
|
double total_overhead_target_percentage = NUM2DBL(dynamic_sampling_rate_overhead_target_percentage);
|
|
471
513
|
if (!state->allocation_profiling_enabled) {
|
|
@@ -474,12 +516,14 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
474
516
|
// TODO: May be nice to offer customization here? Distribute available "overhead" margin with a bias towards one or the other
|
|
475
517
|
// sampler.
|
|
476
518
|
dynamic_sampling_rate_set_overhead_target_percentage(&state->cpu_dynamic_sampling_rate, total_overhead_target_percentage / 2);
|
|
477
|
-
|
|
478
|
-
|
|
519
|
+
discrete_dynamic_sampler_set_overhead_target_percentage(
|
|
520
|
+
&state->allocation_sampler, total_overhead_target_percentage / 2, monotonic_wall_time_now_ns()
|
|
521
|
+
);
|
|
479
522
|
}
|
|
480
523
|
|
|
481
524
|
state->thread_context_collector_instance = enforce_thread_context_collector_instance(thread_context_collector_instance);
|
|
482
525
|
state->idle_sampling_helper_instance = idle_sampling_helper_instance;
|
|
526
|
+
state->idle_sampling_helper_state = idle_sampling_helper_get_state(idle_sampling_helper_instance);
|
|
483
527
|
state->gc_tracepoint = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_GC_ENTER | RUBY_INTERNAL_EVENT_GC_EXIT, on_gc_event, NULL /* unused */);
|
|
484
528
|
|
|
485
529
|
return Qtrue;
|
|
@@ -504,7 +548,7 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
504
548
|
|
|
505
549
|
// If we already got a delayed exception registered even before starting, raise before starting
|
|
506
550
|
if (state->failure_exception != Qnil) {
|
|
507
|
-
|
|
551
|
+
disable_hooks(state);
|
|
508
552
|
rb_exc_raise(state->failure_exception);
|
|
509
553
|
}
|
|
510
554
|
|
|
@@ -514,13 +558,13 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
514
558
|
raise_error(rb_eRuntimeError, "Could not start CpuAndWallTimeWorker: There's already another instance of CpuAndWallTimeWorker active in a different thread");
|
|
515
559
|
} else {
|
|
516
560
|
// The previously active thread seems to have died without cleaning up after itself.
|
|
517
|
-
// In this case, we can still go ahead and start the profiler BUT we make sure to disable any existing
|
|
561
|
+
// In this case, we can still go ahead and start the profiler BUT we make sure to disable any existing hooks
|
|
518
562
|
// first as:
|
|
519
|
-
// a) If this is a new instance of the CpuAndWallTimeWorker, we don't want the
|
|
563
|
+
// a) If this is a new instance of the CpuAndWallTimeWorker, we don't want the hooks from the old instance
|
|
520
564
|
// being kept around
|
|
521
565
|
// b) If this is the same instance of the CpuAndWallTimeWorker if we call enable on a tracepoint that is already
|
|
522
566
|
// enabled, it will start firing more than once, see https://bugs.ruby-lang.org/issues/19114 for details.
|
|
523
|
-
|
|
567
|
+
disable_hooks(old_state);
|
|
524
568
|
}
|
|
525
569
|
}
|
|
526
570
|
|
|
@@ -532,13 +576,12 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
532
576
|
|
|
533
577
|
// Reset the dynamic sampling rate state, if any (reminder: the monotonic clock reference may change after a fork)
|
|
534
578
|
dynamic_sampling_rate_reset(&state->cpu_dynamic_sampling_rate);
|
|
535
|
-
|
|
536
|
-
discrete_dynamic_sampler_reset(&state->allocation_sampler, now);
|
|
579
|
+
discrete_dynamic_sampler_reset(&state->allocation_sampler, monotonic_wall_time_now_ns());
|
|
537
580
|
|
|
538
581
|
// Reset per-thread state, if any. This ensures there's no leftover state from a previous profiler run that would
|
|
539
582
|
// affect or be included in samples taken by this profiler about to run.
|
|
540
583
|
//
|
|
541
|
-
// NOTE: This needs to be called before we enable any
|
|
584
|
+
// NOTE: This needs to be called before we enable any hooks or anything that could trigger samples (e.g.
|
|
542
585
|
// reset cannot be concurrent with any sampling activity)
|
|
543
586
|
thread_context_collector_reset_all_per_thread_contexts(state->thread_context_collector_instance);
|
|
544
587
|
|
|
@@ -565,7 +608,7 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
565
608
|
|
|
566
609
|
// The sample trigger loop finished (either cleanly or with an error); let's clean up
|
|
567
610
|
|
|
568
|
-
|
|
611
|
+
disable_hooks(state);
|
|
569
612
|
|
|
570
613
|
active_sampler_instance_state = NULL;
|
|
571
614
|
active_sampler_instance = Qnil;
|
|
@@ -610,6 +653,38 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
610
653
|
return Qnil;
|
|
611
654
|
}
|
|
612
655
|
|
|
656
|
+
static VALUE during_sample_exit_ensure(VALUE state_ptr) {
|
|
657
|
+
during_sample_exit((cpu_and_wall_time_worker_state *) state_ptr);
|
|
658
|
+
return Qnil;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
static VALUE _native_profiler_internal_thread_done(VALUE self_instance) {
|
|
662
|
+
cpu_and_wall_time_worker_state *state;
|
|
663
|
+
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
664
|
+
|
|
665
|
+
during_sample_enter(state);
|
|
666
|
+
return rb_ensure(
|
|
667
|
+
thread_context_collector_profiler_internal_thread_done, state->thread_context_collector_instance,
|
|
668
|
+
during_sample_exit_ensure, (VALUE) state
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// This method exists so that we run `thread_context_prepare_serialize` protected with
|
|
673
|
+
// `during_sample_enter`/`during_sample_exit` before we actually serialize.
|
|
674
|
+
//
|
|
675
|
+
// That's why in normal operation we go through the `CpuAndWallTimeWorker` and not directly to the `ThreadContext` to
|
|
676
|
+
// serialize.
|
|
677
|
+
static VALUE _native_prepare_serialize(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
|
|
678
|
+
cpu_and_wall_time_worker_state *state;
|
|
679
|
+
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
680
|
+
|
|
681
|
+
during_sample_enter(state);
|
|
682
|
+
return rb_ensure(
|
|
683
|
+
thread_context_prepare_serialize, state->thread_context_collector_instance,
|
|
684
|
+
during_sample_exit_ensure, (VALUE) state
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
|
|
613
688
|
static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread) {
|
|
614
689
|
cpu_and_wall_time_worker_state *state;
|
|
615
690
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
@@ -625,8 +700,8 @@ static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exc
|
|
|
625
700
|
state->failure_exception = optional_exception;
|
|
626
701
|
state->failure_exception_during_operation = optional_exception_during_operation;
|
|
627
702
|
|
|
628
|
-
// Disable the
|
|
629
|
-
|
|
703
|
+
// Disable the hooks as soon as possible, so the VM doesn't keep on calling them
|
|
704
|
+
disable_hooks(state);
|
|
630
705
|
}
|
|
631
706
|
|
|
632
707
|
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation) {
|
|
@@ -641,14 +716,16 @@ static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *opt
|
|
|
641
716
|
// NOTE: Remember that this will run in the thread and within the scope of user code, including user C code.
|
|
642
717
|
// We need to be careful not to change any state that may be observed OR to restore it if we do. For instance, if anything
|
|
643
718
|
// we do here can set `errno`, then we must be careful to restore the old `errno` after the fact.
|
|
719
|
+
//
|
|
720
|
+
// Neither this handler nor its callees may dereference Ruby objects before confirming GVL ownership or during GC.
|
|
721
|
+
// Holding the GVL is not enough: we may have interrupted GC itself, with Ruby heap pages protected by compaction.
|
|
644
722
|
static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext) {
|
|
645
723
|
// We must first check that we landed on the correct thread and can proceed.
|
|
646
724
|
// We must never touch the state before we confirm that we have landed on the thread that is holding the GVL on the main
|
|
647
725
|
// ractor as otherwise we may be concurrent with the profiler shutting down and removing its state.
|
|
648
726
|
if (
|
|
649
727
|
!ruby_native_thread_p() || // Not a Ruby thread
|
|
650
|
-
!
|
|
651
|
-
!ddtrace_rb_ractor_main_p() // We're not on the main Ractor; we currently don't support profiling non-main Ractors
|
|
728
|
+
!is_current_thread_in_main_ractor_and_holding_the_gvl() // Not safe to enqueue a sample from this thread
|
|
652
729
|
) return;
|
|
653
730
|
|
|
654
731
|
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
@@ -660,6 +737,8 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
660
737
|
// a) we get triggered using SIGPROF, and the docs state a second SIGPROF will not interrupt an existing one (see sigaction docs on sa_mask)
|
|
661
738
|
// b) we validate we are in the thread that has the global VM lock; if a different thread gets a signal, it will return early
|
|
662
739
|
// because it will not have the global VM lock
|
|
740
|
+
// c) `simulate_sampling_signal_delivery` calls us directly instead of via a real SIGPROF, and blocks SIGPROF delivery on its
|
|
741
|
+
// thread for the duration of that call, so it can't be nested into by a real SIGPROF either
|
|
663
742
|
|
|
664
743
|
state->stats.signal_handler_enqueued_sample++;
|
|
665
744
|
|
|
@@ -669,11 +748,20 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
669
748
|
!state->during_sample;
|
|
670
749
|
|
|
671
750
|
if (sample_from_signal_handler) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
751
|
+
if (rb_during_gc()) {
|
|
752
|
+
// During GC Ruby might be marking our buffer or compacting (moving) where iseqs live so we skip preparing the
|
|
753
|
+
// sample immediately, and instead defer preparation until GC_EXIT.
|
|
754
|
+
//
|
|
755
|
+
// When GC profiling is disabled, we just fall back to sampling the stack after GC finishes, e.g. it's the
|
|
756
|
+
// equivalent of disabling `sample_from_signal_handler` for samples that happen during GC.
|
|
757
|
+
state->prepare_sample_on_gc_finish = true;
|
|
758
|
+
} else {
|
|
759
|
+
// Buffer current stack trace. Note that this will not actually record the sample, for that we still need to wait
|
|
760
|
+
// until the postponed job below gets run.
|
|
761
|
+
bool prepared = thread_context_collector_prepare_sample_inside_signal_handler();
|
|
675
762
|
|
|
676
|
-
|
|
763
|
+
if (prepared) state->stats.signal_handler_prepared_sample++;
|
|
764
|
+
}
|
|
677
765
|
}
|
|
678
766
|
|
|
679
767
|
#ifndef NO_POSTPONED_TRIGGER // Ruby 3.3+
|
|
@@ -707,7 +795,8 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
707
795
|
#endif
|
|
708
796
|
}
|
|
709
797
|
|
|
710
|
-
//
|
|
798
|
+
// Runs without the GVL: neither this loop nor its callees may dereference Ruby objects until they reacquire it.
|
|
799
|
+
// GC compaction can protect Ruby heap pages while this loop runs, so even reading an object's header is unsafe.
|
|
711
800
|
static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
712
801
|
cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
|
|
713
802
|
|
|
@@ -727,7 +816,7 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
|
727
816
|
state->stats.trigger_simulated_signal_delivery_attempts++;
|
|
728
817
|
grab_gvl_and_sample(); // Note: Can raise exceptions
|
|
729
818
|
} else {
|
|
730
|
-
current_gvl_owner owner =
|
|
819
|
+
current_gvl_owner owner = main_ractor_gvl_owner();
|
|
731
820
|
if (owner.valid) {
|
|
732
821
|
// Note that reading the GVL owner and sending them a signal is a race -- the Ruby VM keeps on executing while
|
|
733
822
|
// we're doing this, so we may still not signal the correct thread from time to time, but our signal handler
|
|
@@ -751,7 +840,7 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
|
751
840
|
// for an uncontrolled amount of time. (This can still happen to the IdleSamplingHelper, but the
|
|
752
841
|
// CpuAndWallTimeWorker will still be free to interrupt the Ruby VM and keep sampling for the entire blocking period).
|
|
753
842
|
state->stats.trigger_simulated_signal_delivery_attempts++;
|
|
754
|
-
idle_sampling_helper_request_action(state->
|
|
843
|
+
idle_sampling_helper_request_action(state->idle_sampling_helper_state, grab_gvl_and_sample);
|
|
755
844
|
}
|
|
756
845
|
}
|
|
757
846
|
}
|
|
@@ -763,7 +852,7 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
|
|
|
763
852
|
// Note that we deliberately should NOT combine this sleep_for with the one above because the result of
|
|
764
853
|
// `dynamic_sampling_rate_get_sleep` may have changed while the above sleep was ongoing.
|
|
765
854
|
uint64_t extra_sleep =
|
|
766
|
-
dynamic_sampling_rate_get_sleep(&state->cpu_dynamic_sampling_rate, monotonic_wall_time_now_ns(
|
|
855
|
+
dynamic_sampling_rate_get_sleep(&state->cpu_dynamic_sampling_rate, monotonic_wall_time_now_ns());
|
|
767
856
|
if (state->dynamic_sampling_rate_enabled && extra_sleep > 0) {
|
|
768
857
|
state->stats.trigger_sample_extra_sleep++;
|
|
769
858
|
sleep_for(extra_sleep);
|
|
@@ -797,7 +886,7 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
797
886
|
during_sample_enter(state);
|
|
798
887
|
|
|
799
888
|
// Rescue against any exceptions that happen during sampling
|
|
800
|
-
safely_call(
|
|
889
|
+
VALUE needs_otel_span_key = safely_call(
|
|
801
890
|
rescued_sample_from_postponed_job,
|
|
802
891
|
state->self_instance,
|
|
803
892
|
state->self_instance,
|
|
@@ -805,28 +894,37 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
805
894
|
);
|
|
806
895
|
|
|
807
896
|
during_sample_exit(state);
|
|
897
|
+
|
|
898
|
+
// Extracting the otel span key can lose the GVL, so we move it outside `during_sample`
|
|
899
|
+
// (It can't raise: it rescues its own exceptions)
|
|
900
|
+
if (needs_otel_span_key == Qtrue) {
|
|
901
|
+
thread_context_collector_resolve_otel_span_key_may_lose_gvl(state->thread_context_collector_instance);
|
|
902
|
+
}
|
|
808
903
|
}
|
|
809
904
|
|
|
810
905
|
static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
811
906
|
cpu_and_wall_time_worker_state *state;
|
|
812
907
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
813
908
|
|
|
814
|
-
long wall_time_ns_before_sample = monotonic_wall_time_now_ns(
|
|
909
|
+
long wall_time_ns_before_sample = monotonic_wall_time_now_ns();
|
|
815
910
|
|
|
816
911
|
if (state->dynamic_sampling_rate_enabled && !dynamic_sampling_rate_should_sample(&state->cpu_dynamic_sampling_rate, wall_time_ns_before_sample)) {
|
|
817
912
|
state->stats.cpu_skipped++;
|
|
818
|
-
return
|
|
913
|
+
return Qfalse;
|
|
819
914
|
}
|
|
820
915
|
|
|
821
916
|
state->stats.cpu_sampled++;
|
|
822
917
|
|
|
823
|
-
|
|
918
|
+
bool needs_otel_span_key =
|
|
919
|
+
thread_context_collector_sample(state->thread_context_collector_instance, wall_time_ns_before_sample);
|
|
824
920
|
|
|
825
|
-
long wall_time_ns_after_sample = monotonic_wall_time_now_ns(
|
|
826
|
-
|
|
921
|
+
long wall_time_ns_after_sample = monotonic_wall_time_now_ns();
|
|
922
|
+
|
|
923
|
+
if (wall_time_ns_after_sample < wall_time_ns_before_sample) {
|
|
924
|
+
raise_error(rb_eRuntimeError, "BUG: Unexpected wall time going backwards when tracking overhead");
|
|
925
|
+
}
|
|
827
926
|
|
|
828
|
-
|
|
829
|
-
uint64_t sampling_time_ns = delta_ns < 0 ? 0 : delta_ns;
|
|
927
|
+
uint64_t sampling_time_ns = wall_time_ns_after_sample - wall_time_ns_before_sample;
|
|
830
928
|
|
|
831
929
|
state->stats.cpu_sampling_time_ns_min = uint64_min_of(sampling_time_ns, state->stats.cpu_sampling_time_ns_min);
|
|
832
930
|
state->stats.cpu_sampling_time_ns_max = uint64_max_of(sampling_time_ns, state->stats.cpu_sampling_time_ns_max);
|
|
@@ -834,8 +932,7 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
|
834
932
|
|
|
835
933
|
dynamic_sampling_rate_after_sample(&state->cpu_dynamic_sampling_rate, wall_time_ns_after_sample, sampling_time_ns);
|
|
836
934
|
|
|
837
|
-
|
|
838
|
-
return Qnil;
|
|
935
|
+
return needs_otel_span_key ? Qtrue : Qfalse;
|
|
839
936
|
}
|
|
840
937
|
|
|
841
938
|
// This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
|
|
@@ -861,7 +958,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
|
861
958
|
cpu_and_wall_time_worker_state *state;
|
|
862
959
|
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
863
960
|
|
|
864
|
-
// Final preparations: Setup signal handler and enable
|
|
961
|
+
// Final preparations: Setup signal handler and enable hooks. We run these here and not in `_native_sampling_loop`
|
|
865
962
|
// because they may raise exceptions.
|
|
866
963
|
install_sigprof_signal_handler(handle_sampling_signal, "handle_sampling_signal");
|
|
867
964
|
if (state->gc_profiling_enabled) rb_tracepoint_enable(state->gc_tracepoint);
|
|
@@ -900,7 +997,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
|
900
997
|
// If we stopped sampling due to an exception, re-raise it (now in the worker thread)
|
|
901
998
|
if (state->failure_exception != Qnil) rb_exc_raise(state->failure_exception);
|
|
902
999
|
|
|
903
|
-
|
|
1000
|
+
_native_profiler_internal_thread_done(instance);
|
|
904
1001
|
|
|
905
1002
|
return Qnil;
|
|
906
1003
|
}
|
|
@@ -983,9 +1080,20 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
|
|
|
983
1080
|
// and disabled before it is cleared, but just in case...
|
|
984
1081
|
if (state == NULL) return;
|
|
985
1082
|
|
|
1083
|
+
handle_gc_event(state, event);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
static void handle_gc_event(cpu_and_wall_time_worker_state *state, rb_event_flag_t event) {
|
|
986
1087
|
if (event == RUBY_INTERNAL_EVENT_GC_ENTER) {
|
|
1088
|
+
// A signal can arrive after GC_EXIT while `rb_during_gc` is still true; discard requests from the previous GC step.
|
|
1089
|
+
state->prepare_sample_on_gc_finish = false;
|
|
987
1090
|
thread_context_collector_on_gc_start(state->thread_context_collector_instance);
|
|
988
1091
|
} else if (event == RUBY_INTERNAL_EVENT_GC_EXIT) {
|
|
1092
|
+
if (state->prepare_sample_on_gc_finish && !state->during_sample) {
|
|
1093
|
+
during_sample_enter(state);
|
|
1094
|
+
thread_context_collector_prepare_sample_on_gc_finish();
|
|
1095
|
+
during_sample_exit(state);
|
|
1096
|
+
}
|
|
989
1097
|
bool should_flush = thread_context_collector_on_gc_finish(state->thread_context_collector_instance);
|
|
990
1098
|
|
|
991
1099
|
// We use rb_postponed_job_register_one to ask Ruby to run thread_context_collector_sample_after_gc when the
|
|
@@ -1000,6 +1108,31 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
|
|
|
1000
1108
|
}
|
|
1001
1109
|
}
|
|
1002
1110
|
|
|
1111
|
+
static VALUE _native_request_prepare_on_gc_finish(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
1112
|
+
cpu_and_wall_time_worker_state *state;
|
|
1113
|
+
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1114
|
+
state->prepare_sample_on_gc_finish = true;
|
|
1115
|
+
return Qnil;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
static VALUE _native_on_gc_event(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE event, VALUE during_sample) {
|
|
1119
|
+
cpu_and_wall_time_worker_state *state;
|
|
1120
|
+
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1121
|
+
ENFORCE_BOOLEAN(during_sample);
|
|
1122
|
+
rb_event_flag_t event_flag;
|
|
1123
|
+
if (event == ID2SYM(rb_intern("enter"))) event_flag = RUBY_INTERNAL_EVENT_GC_ENTER;
|
|
1124
|
+
else if (event == ID2SYM(rb_intern("exit"))) event_flag = RUBY_INTERNAL_EVENT_GC_EXIT;
|
|
1125
|
+
else rb_raise(rb_eArgError, "Expected :enter or :exit");
|
|
1126
|
+
|
|
1127
|
+
bool was_during_sample = state->during_sample;
|
|
1128
|
+
if (during_sample == Qtrue) during_sample_enter(state);
|
|
1129
|
+
debug_enter_unsafe_context();
|
|
1130
|
+
handle_gc_event(state, event_flag);
|
|
1131
|
+
debug_leave_unsafe_context();
|
|
1132
|
+
if (!was_during_sample) during_sample_exit(state);
|
|
1133
|
+
return Qnil;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1003
1136
|
static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
1004
1137
|
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1005
1138
|
|
|
@@ -1022,6 +1155,15 @@ static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
1022
1155
|
);
|
|
1023
1156
|
|
|
1024
1157
|
during_sample_exit(state);
|
|
1158
|
+
|
|
1159
|
+
// This part runs separately from above because it may lose the GVL and we don't want `during_sample` to be set in
|
|
1160
|
+
// such a situation
|
|
1161
|
+
safely_call(
|
|
1162
|
+
thread_context_collector_heap_update_may_lose_gvl,
|
|
1163
|
+
state->thread_context_collector_instance,
|
|
1164
|
+
state->self_instance,
|
|
1165
|
+
handle_sampling_failure_thread_context_collector_heap_update
|
|
1166
|
+
);
|
|
1025
1167
|
}
|
|
1026
1168
|
|
|
1027
1169
|
// Equivalent to Ruby begin/rescue call, where we call a C function and jump to the exception handler if an
|
|
@@ -1059,12 +1201,12 @@ static VALUE _native_simulate_sample_from_postponed_job(DDTRACE_UNUSED VALUE sel
|
|
|
1059
1201
|
|
|
1060
1202
|
// After the Ruby VM forks, this method gets called in the child process to clean up any leftover state from the parent.
|
|
1061
1203
|
//
|
|
1062
|
-
// Assumption: This method gets called BEFORE restarting profiling. Note that profiling-related
|
|
1204
|
+
// Assumption: This method gets called BEFORE restarting profiling. Note that profiling-related hooks may still
|
|
1063
1205
|
// be active, so we make sure to disable them before calling into anything else, so that there are no components
|
|
1064
1206
|
// attempting to trigger samples at the same time as the reset is done.
|
|
1065
1207
|
//
|
|
1066
|
-
// In the future, if we add more other components with
|
|
1067
|
-
//
|
|
1208
|
+
// In the future, if we add more other components with hooks, we will need to coordinate stopping all such
|
|
1209
|
+
// hooks before doing the other cleaning steps.
|
|
1068
1210
|
//
|
|
1069
1211
|
// Note that tests call this method directly in the same process without forking,
|
|
1070
1212
|
// and in such a case non-current Threads keep running.
|
|
@@ -1072,8 +1214,10 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE instance)
|
|
|
1072
1214
|
cpu_and_wall_time_worker_state *state;
|
|
1073
1215
|
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1074
1216
|
|
|
1075
|
-
// Disable all
|
|
1076
|
-
|
|
1217
|
+
// Disable all hooks, so that there are no more attempts to mutate the profile
|
|
1218
|
+
disable_hooks(state);
|
|
1219
|
+
|
|
1220
|
+
private_vm_api_access_self_test();
|
|
1077
1221
|
|
|
1078
1222
|
reset_stats_not_thread_safe(state);
|
|
1079
1223
|
|
|
@@ -1161,11 +1305,19 @@ void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
|
|
|
1161
1305
|
// This can potentially happen if the CpuAndWallTimeWorker was stopped while the IdleSamplingHelper was trying to execute this action
|
|
1162
1306
|
if (state == NULL) return NULL;
|
|
1163
1307
|
|
|
1308
|
+
// Since this is not a real signal firing, we need to block SIGPROF delivery on this thread to avoid an actual SIGPROF
|
|
1309
|
+
// signal coming in nested and interrupting us on this thread. Thus we respect the invariant of "no nesting" for `handle_sampling_signal`.
|
|
1310
|
+
//
|
|
1311
|
+
// Not needed when `no_signals_workaround_enabled` is set: no SIGPROFs are ever sent in that mode, so there's nothing to mask.
|
|
1312
|
+
if (!state->no_signals_workaround_enabled) block_sigprof_signal_handler_from_running_in_current_thread();
|
|
1313
|
+
|
|
1164
1314
|
state->stats.simulated_signal_delivery++;
|
|
1165
1315
|
|
|
1166
1316
|
// `handle_sampling_signal` does a few things extra on top of `sample_from_postponed_job` so that's why we don't shortcut here
|
|
1167
1317
|
handle_sampling_signal(0, NULL, NULL);
|
|
1168
1318
|
|
|
1319
|
+
if (!state->no_signals_workaround_enabled) unblock_sigprof_signal_handler_from_running_in_current_thread();
|
|
1320
|
+
|
|
1169
1321
|
return NULL; // Unused
|
|
1170
1322
|
}
|
|
1171
1323
|
|
|
@@ -1178,6 +1330,7 @@ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state) {
|
|
|
1178
1330
|
// * Included in the following stats window (writes after stats retrieval and reset).
|
|
1179
1331
|
// Given the expected infrequency of resetting (~once per 60s profile) and the auxiliary/non-critical nature of these stats
|
|
1180
1332
|
// this momentary loss of accuracy is deemed acceptable to keep overhead to a minimum.
|
|
1333
|
+
|
|
1181
1334
|
state->stats = (struct stats) {
|
|
1182
1335
|
// All these values are initialized to their highest value possible since we always take the min between existing and latest sample
|
|
1183
1336
|
.cpu_sampling_time_ns_min = UINT64_MAX,
|
|
@@ -1213,18 +1366,12 @@ static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
|
|
|
1213
1366
|
return are_allocations_being_tracked ? ULL2NUM(allocation_count) : Qnil;
|
|
1214
1367
|
}
|
|
1215
1368
|
|
|
1216
|
-
#define HANDLE_CLOCK_FAILURE(call) ({ \
|
|
1217
|
-
long _result = (call); \
|
|
1218
|
-
if (_result == 0) { \
|
|
1219
|
-
delayed_error_clock_failure(state); \
|
|
1220
|
-
return; \
|
|
1221
|
-
} \
|
|
1222
|
-
_result; \
|
|
1223
|
-
})
|
|
1224
|
-
|
|
1225
1369
|
// Implements memory-related profiling events. This function is called by Ruby via the `rb_add_event_hook2`
|
|
1226
1370
|
// when the RUBY_INTERNAL_EVENT_NEWOBJ event is triggered.
|
|
1227
1371
|
//
|
|
1372
|
+
// This function is called from the RUBY_INTERNAL_EVENT_NEWOBJ tracepoint so it should neither allocate in the
|
|
1373
|
+
// Ruby heap nor release the GVL (https://github.com/DataDog/dd-trace-rb/pull/4240).
|
|
1374
|
+
//
|
|
1228
1375
|
// When allocation sampling is enabled, this function gets called for almost all* objects allocated by the Ruby VM.
|
|
1229
1376
|
// (*In some weird cases the VM may skip this tracepoint.)
|
|
1230
1377
|
//
|
|
@@ -1284,16 +1431,13 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1284
1431
|
if (RB_LIKELY(state->dynamic_sampling_rate_enabled && !discrete_dynamic_sampler_should_sample(&state->allocation_sampler))) {
|
|
1285
1432
|
state->stats.allocation_skipped++;
|
|
1286
1433
|
|
|
1287
|
-
|
|
1288
|
-
HANDLE_CLOCK_FAILURE(now.timestamp_ns);
|
|
1289
|
-
|
|
1290
|
-
bool needs_readjust = discrete_dynamic_sampler_skipped_sample(&state->allocation_sampler, now);
|
|
1434
|
+
bool needs_readjust = discrete_dynamic_sampler_skipped_sample(&state->allocation_sampler, monotonic_coarse_wall_time_now_ns());
|
|
1291
1435
|
if (RB_UNLIKELY(needs_readjust)) {
|
|
1292
1436
|
// We rarely readjust, so this is a cold path
|
|
1293
1437
|
// Also, while above we used the cheaper monotonic_coarse, for this call we want the regular monotonic call,
|
|
1294
1438
|
// which is why we end up getting time "again".
|
|
1295
1439
|
discrete_dynamic_sampler_readjust(
|
|
1296
|
-
&state->allocation_sampler,
|
|
1440
|
+
&state->allocation_sampler, monotonic_wall_time_now_ns()
|
|
1297
1441
|
);
|
|
1298
1442
|
}
|
|
1299
1443
|
|
|
@@ -1303,7 +1447,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1303
1447
|
// From here on, we've decided to go ahead with the sample, which is way less common than skipping it
|
|
1304
1448
|
|
|
1305
1449
|
discrete_dynamic_sampler_before_sample(
|
|
1306
|
-
&state->allocation_sampler,
|
|
1450
|
+
&state->allocation_sampler, monotonic_wall_time_now_ns()
|
|
1307
1451
|
);
|
|
1308
1452
|
|
|
1309
1453
|
during_sample_enter(state);
|
|
@@ -1317,12 +1461,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1317
1461
|
);
|
|
1318
1462
|
|
|
1319
1463
|
if (state->dynamic_sampling_rate_enabled) {
|
|
1320
|
-
|
|
1321
|
-
if (now == 0) {
|
|
1322
|
-
delayed_error_clock_failure(state);
|
|
1323
|
-
// NOTE: Not short-circuiting here to make sure cleanup happens
|
|
1324
|
-
}
|
|
1325
|
-
uint64_t sampling_time_ns = discrete_dynamic_sampler_after_sample(&state->allocation_sampler, now);
|
|
1464
|
+
uint64_t sampling_time_ns = discrete_dynamic_sampler_after_sample(&state->allocation_sampler, monotonic_wall_time_now_ns());
|
|
1326
1465
|
// NOTE: To keep things lean when dynamic sampling rate is disabled we skip clock interactions which is
|
|
1327
1466
|
// why we're fine with having this inside this conditional.
|
|
1328
1467
|
state->stats.allocation_sampling_time_ns_min = uint64_min_of(sampling_time_ns, state->stats.allocation_sampling_time_ns_min);
|
|
@@ -1335,7 +1474,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1335
1474
|
during_sample_exit(state);
|
|
1336
1475
|
}
|
|
1337
1476
|
|
|
1338
|
-
static void
|
|
1477
|
+
static void disable_hooks(cpu_and_wall_time_worker_state *state) {
|
|
1339
1478
|
if (state->gc_tracepoint != Qnil) {
|
|
1340
1479
|
rb_tracepoint_disable(state->gc_tracepoint);
|
|
1341
1480
|
}
|
|
@@ -1383,18 +1522,18 @@ static VALUE rescued_sample_allocation(VALUE arg) {
|
|
|
1383
1522
|
// To control bias from sampling, we clamp the maximum weight attributed to a single allocation sample. This avoids
|
|
1384
1523
|
// assigning a very large number to a sample, if for instance the dynamic sampling mechanism chose a really big interval.
|
|
1385
1524
|
unsigned int weight = allocations_since_last_sample > MAX_ALLOC_WEIGHT ? MAX_ALLOC_WEIGHT : (unsigned int) allocations_since_last_sample;
|
|
1386
|
-
bool
|
|
1525
|
+
bool needs_commit = thread_context_collector_sample_allocation(state->thread_context_collector_instance, thread_context, weight, new_object);
|
|
1387
1526
|
// ...but we still represent the skipped samples in the profile, thus the data will account for all allocations.
|
|
1388
1527
|
if (weight < allocations_since_last_sample) {
|
|
1389
1528
|
uint32_t skipped_samples = (uint32_t) uint64_min_of(allocations_since_last_sample - weight, UINT32_MAX);
|
|
1390
1529
|
thread_context_collector_sample_skipped_allocation_samples(state->thread_context_collector_instance, skipped_samples);
|
|
1391
1530
|
}
|
|
1392
1531
|
|
|
1393
|
-
if (
|
|
1532
|
+
if (needs_commit) {
|
|
1394
1533
|
#ifndef NO_POSTPONED_TRIGGER
|
|
1395
|
-
rb_postponed_job_trigger(
|
|
1534
|
+
rb_postponed_job_trigger(commit_heap_recordings_from_postponed_job_may_lose_gvl_handle);
|
|
1396
1535
|
#else
|
|
1397
|
-
|
|
1536
|
+
rb_postponed_job_register_one(0, commit_heap_recordings_from_postponed_job_may_lose_gvl, NULL);
|
|
1398
1537
|
#endif
|
|
1399
1538
|
}
|
|
1400
1539
|
|
|
@@ -1407,11 +1546,6 @@ static void delayed_error(cpu_and_wall_time_worker_state *state, const char *err
|
|
|
1407
1546
|
stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error), "delayed_error");
|
|
1408
1547
|
}
|
|
1409
1548
|
|
|
1410
|
-
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state) {
|
|
1411
|
-
// If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
|
|
1412
|
-
stop_state(state, rb_exc_new_cstr(clock_failure_exception_class, "failed to get clock time"), "delayed_error_clock_failure");
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
1549
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg) {
|
|
1416
1550
|
ENFORCE_TYPE(error_msg, T_STRING);
|
|
1417
1551
|
|
|
@@ -1460,6 +1594,8 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1460
1594
|
VALUE target_thread = rb_thread_current();
|
|
1461
1595
|
#endif
|
|
1462
1596
|
|
|
1597
|
+
// TODO: `rb_internal_thread_specific_get` is documented as "async and native thread safe.",
|
|
1598
|
+
// unclear if that holds during GC compaction.
|
|
1463
1599
|
per_thread_context* thread_context = get_per_thread_context(target_thread);
|
|
1464
1600
|
if (!thread_context) return;
|
|
1465
1601
|
// If non-NULL the thread is profiled and from the main Ractor
|
|
@@ -1469,10 +1605,11 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1469
1605
|
} else if (event_id == RUBY_INTERNAL_THREAD_EVENT_READY) { /* waiting for gvl */
|
|
1470
1606
|
thread_context_collector_on_gvl_waiting(thread_context);
|
|
1471
1607
|
} else if (event_id == RUBY_INTERNAL_THREAD_EVENT_RESUMED) { /* running/runnable */
|
|
1472
|
-
//
|
|
1473
|
-
//
|
|
1474
|
-
// However,
|
|
1475
|
-
//
|
|
1608
|
+
// We must only use async-signal-safe functions here and not call arbitrary Ruby APIs and not allocate!
|
|
1609
|
+
// One might assume RUBY_INTERNAL_THREAD_EVENT_RESUMED means having the GVL and running that thread.
|
|
1610
|
+
// However, the reality is more complicated (https://bugs.ruby-lang.org/issues/22098),
|
|
1611
|
+
// it only "sort of" has the GVL but not fully, and it's called while holding the scheduler lock,
|
|
1612
|
+
// so we do as little work as possible here, and perform the sample in a postponed_job.
|
|
1476
1613
|
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1477
1614
|
if (state == NULL) return; // This should not happen, but just in case...
|
|
1478
1615
|
|
|
@@ -1484,7 +1621,8 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1484
1621
|
// that next.
|
|
1485
1622
|
during_sample_enter(state);
|
|
1486
1623
|
|
|
1487
|
-
on_gvl_running_result result =
|
|
1624
|
+
on_gvl_running_result result =
|
|
1625
|
+
thread_context_collector_on_gvl_running(target_thread, thread_context, state->waiting_for_gvl_threshold_ns);
|
|
1488
1626
|
|
|
1489
1627
|
during_sample_exit(state);
|
|
1490
1628
|
|
|
@@ -1529,14 +1667,15 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1529
1667
|
cpu_and_wall_time_worker_state *state;
|
|
1530
1668
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1531
1669
|
|
|
1532
|
-
long wall_time_ns_before_sample = monotonic_wall_time_now_ns(
|
|
1670
|
+
long wall_time_ns_before_sample = monotonic_wall_time_now_ns();
|
|
1533
1671
|
thread_context_collector_sample_after_gvl_running(state->thread_context_collector_instance, rb_thread_current(), wall_time_ns_before_sample);
|
|
1534
|
-
long wall_time_ns_after_sample = monotonic_wall_time_now_ns(
|
|
1672
|
+
long wall_time_ns_after_sample = monotonic_wall_time_now_ns();
|
|
1535
1673
|
|
|
1536
|
-
|
|
1674
|
+
if (wall_time_ns_after_sample < wall_time_ns_before_sample) {
|
|
1675
|
+
raise_error(rb_eRuntimeError, "BUG: Unexpected wall time going backwards when tracking overhead");
|
|
1676
|
+
}
|
|
1537
1677
|
|
|
1538
|
-
|
|
1539
|
-
uint64_t sampling_time_ns = delta_ns < 0 ? 0 : delta_ns;
|
|
1678
|
+
uint64_t sampling_time_ns = wall_time_ns_after_sample - wall_time_ns_before_sample;
|
|
1540
1679
|
|
|
1541
1680
|
state->stats.gvl_sampling_time_ns_min = uint64_min_of(sampling_time_ns, state->stats.gvl_sampling_time_ns_min);
|
|
1542
1681
|
state->stats.gvl_sampling_time_ns_max = uint64_max_of(sampling_time_ns, state->stats.gvl_sampling_time_ns_max);
|
|
@@ -1574,54 +1713,54 @@ static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VA
|
|
|
1574
1713
|
return Qnil;
|
|
1575
1714
|
}
|
|
1576
1715
|
|
|
1716
|
+
static VALUE handle_sampling_failure_thread_context_collector_heap_update(VALUE self_instance, VALUE exception) {
|
|
1717
|
+
stop(self_instance, exception, "thread_context_collector_heap_update_may_lose_gvl");
|
|
1718
|
+
return Qnil;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1577
1721
|
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception) {
|
|
1578
1722
|
stop(self_instance, exception, "rescued_sample_allocation");
|
|
1579
1723
|
return Qnil;
|
|
1580
1724
|
}
|
|
1581
1725
|
|
|
1582
|
-
static VALUE
|
|
1583
|
-
stop(self_instance, exception, "
|
|
1726
|
+
static VALUE handle_sampling_failure_rescued_commit_heap_recordings(VALUE self_instance, VALUE exception) {
|
|
1727
|
+
stop(self_instance, exception, "rescued_commit_heap_recordings_may_lose_gvl");
|
|
1584
1728
|
return Qnil;
|
|
1585
1729
|
}
|
|
1586
1730
|
|
|
1587
|
-
static VALUE
|
|
1731
|
+
static VALUE rescued_commit_heap_recordings_may_lose_gvl(VALUE self_instance) {
|
|
1588
1732
|
cpu_and_wall_time_worker_state *state;
|
|
1589
1733
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1590
1734
|
|
|
1591
|
-
|
|
1735
|
+
thread_context_collector_commit_heap_recordings_may_lose_gvl(state->thread_context_collector_instance);
|
|
1592
1736
|
|
|
1593
1737
|
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
|
1594
1738
|
return Qnil;
|
|
1595
1739
|
}
|
|
1596
1740
|
|
|
1597
|
-
// This postponed job callback is used to
|
|
1598
|
-
// During on_newobj_event,
|
|
1599
|
-
//
|
|
1600
|
-
|
|
1601
|
-
#pragma GCC diagnostic ignored "-Wunused-function" // This is only used for some Rubies, but we want to build on all to make it easier to dev
|
|
1602
|
-
static void after_allocation_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
1741
|
+
// This postponed job callback is used to commit heap allocation recordings.
|
|
1742
|
+
// During on_newobj_event, we can't take the weak reference the heap recorder needs to track the object, so we defer
|
|
1743
|
+
// that until after the event completes.
|
|
1744
|
+
static void commit_heap_recordings_from_postponed_job_may_lose_gvl(DDTRACE_UNUSED void *_unused) {
|
|
1603
1745
|
cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
|
|
1604
1746
|
|
|
1605
1747
|
if (state == NULL || !ddtrace_rb_ractor_main_p()) return;
|
|
1606
1748
|
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1749
|
+
if (state->during_sample) {
|
|
1750
|
+
delayed_error(state, "commit_heap_recordings_from_postponed_job_may_lose_gvl called during_sample");
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1611
1753
|
|
|
1612
1754
|
// NOTE: We're not updating the allocation_sampler here.
|
|
1613
1755
|
// This means work done in this function isn't accounted for as profiler overhead.
|
|
1614
1756
|
// This is acceptable as the amount of work done here is expected to be small.
|
|
1615
1757
|
safely_call(
|
|
1616
|
-
|
|
1758
|
+
rescued_commit_heap_recordings_may_lose_gvl,
|
|
1617
1759
|
state->self_instance,
|
|
1618
1760
|
state->self_instance,
|
|
1619
|
-
|
|
1761
|
+
handle_sampling_failure_rescued_commit_heap_recordings
|
|
1620
1762
|
);
|
|
1621
|
-
|
|
1622
|
-
during_sample_exit(state);
|
|
1623
1763
|
}
|
|
1624
|
-
#pragma GCC diagnostic pop
|
|
1625
1764
|
|
|
1626
1765
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state) {
|
|
1627
1766
|
// Tell the compiler it's not allowed to reorder the `during_sample` flag with anything that happens after.
|