datadog 2.30.0 → 2.43.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 +382 -1
- 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/clock_id.h +9 -1
- data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +312 -99
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
- data/ext/datadog_profiling_native_extension/collectors_stack.c +256 -163
- data/ext/datadog_profiling_native_extension/collectors_stack.h +23 -4
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +833 -513
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +24 -9
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +5 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +44 -19
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +7 -12
- data/ext/datadog_profiling_native_extension/extconf.rb +83 -105
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
- data/ext/datadog_profiling_native_extension/heap_recorder.c +391 -277
- data/ext/datadog_profiling_native_extension/heap_recorder.h +50 -31
- data/ext/datadog_profiling_native_extension/http_transport.c +10 -5
- data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -27
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +750 -482
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +32 -12
- data/ext/datadog_profiling_native_extension/profiling.c +43 -4
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +34 -106
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +0 -7
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +2 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +139 -84
- data/ext/datadog_profiling_native_extension/stack_recorder.h +13 -4
- data/ext/datadog_profiling_native_extension/time_helpers.h +15 -8
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +4 -2
- data/ext/libdatadog_api/crashtracker.c +7 -8
- data/ext/libdatadog_api/datadog_ruby_common.c +44 -19
- data/ext/libdatadog_api/datadog_ruby_common.h +7 -12
- data/ext/libdatadog_api/di.c +213 -0
- data/ext/libdatadog_api/extconf.rb +40 -26
- data/ext/libdatadog_api/feature_flags.c +26 -0
- data/ext/libdatadog_api/init.c +11 -2
- data/ext/libdatadog_api/otel_thread_context.c +247 -0
- data/ext/libdatadog_api/otel_thread_context.h +5 -0
- data/ext/libdatadog_api/trace_exporter.c +1932 -0
- data/ext/libdatadog_api/trace_exporter.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +50 -5
- data/lib/datadog/ai_guard/api_client.rb +9 -7
- data/lib/datadog/ai_guard/autoload.rb +10 -0
- data/lib/datadog/ai_guard/component.rb +11 -9
- data/lib/datadog/ai_guard/configuration.rb +106 -2
- data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
- data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
- data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
- data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +41 -3
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation/request.rb +22 -17
- data/lib/datadog/ai_guard/evaluation/result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation.rb +51 -7
- data/lib/datadog/ai_guard/ext.rb +15 -0
- data/lib/datadog/ai_guard.rb +34 -8
- 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 +26 -14
- 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 +4 -4
- data/lib/datadog/appsec/component.rb +29 -22
- data/lib/datadog/appsec/compressed_json.rb +7 -7
- data/lib/datadog/appsec/configuration.rb +436 -1
- data/lib/datadog/appsec/context.rb +10 -8
- 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 +75 -0
- data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
- data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +146 -0
- 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 +14 -13
- 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 +76 -21
- 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 +72 -18
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +66 -21
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +7 -7
- data/lib/datadog/appsec/contrib/graphql/integration.rb +9 -8
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
- data/lib/datadog/appsec/contrib/rack/ext.rb +29 -29
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +56 -17
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +46 -30
- data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
- 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 +51 -61
- data/lib/datadog/appsec/contrib/rack/response_body.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/gateway/request.rb +43 -4
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +25 -9
- 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 +3 -3
- 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 +74 -21
- 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 +34 -13
- 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 +3 -3
- data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +2 -1
- data/lib/datadog/appsec/counter_sampler.rb +1 -1
- data/lib/datadog/appsec/default_header_tags.rb +52 -0
- data/lib/datadog/appsec/event.rb +14 -14
- data/lib/datadog/appsec/ext.rb +11 -10
- data/lib/datadog/appsec/extensions.rb +2 -2
- data/lib/datadog/appsec/instrumentation/gateway.rb +1 -14
- data/lib/datadog/appsec/metrics/collector.rb +18 -1
- data/lib/datadog/appsec/metrics/exporter.rb +17 -11
- data/lib/datadog/appsec/metrics/telemetry.rb +15 -3
- 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 +18 -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 +15 -9
- data/lib/datadog/appsec/response.rb +22 -22
- data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
- data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
- data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
- data/lib/datadog/appsec/route_normalizer.rb +80 -0
- data/lib/datadog/appsec/security_engine/engine.rb +40 -40
- data/lib/datadog/appsec/security_engine/runner.rb +3 -3
- data/lib/datadog/appsec/security_event.rb +2 -2
- data/lib/datadog/appsec/trace_keeper.rb +18 -6
- data/lib/datadog/appsec/utils/http/body.rb +11 -8
- data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
- data/lib/datadog/appsec/utils/http/media_range.rb +15 -15
- data/lib/datadog/appsec/utils/http/media_type.rb +5 -6
- data/lib/datadog/appsec/utils/http/url_encoded.rb +79 -24
- data/lib/datadog/appsec.rb +21 -24
- 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/agentless_settings_resolver.rb +2 -2
- data/lib/datadog/core/configuration/base.rb +19 -7
- data/lib/datadog/core/configuration/components.rb +142 -36
- data/lib/datadog/core/configuration/components_state.rb +6 -1
- data/lib/datadog/core/configuration/config_helper.rb +12 -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 +46 -21
- data/lib/datadog/core/configuration/option_definition.rb +43 -17
- data/lib/datadog/core/configuration/options.rb +42 -8
- data/lib/datadog/core/configuration/settings.rb +129 -104
- data/lib/datadog/core/configuration/stable_config.rb +1 -1
- data/lib/datadog/core/configuration/supported_configurations.rb +25 -1
- data/lib/datadog/core/configuration.rb +9 -9
- data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
- data/lib/datadog/core/contrib/rails/utils.rb +7 -3
- data/lib/datadog/core/crashtracking/component.rb +17 -13
- 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 +45 -8
- 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 +11 -11
- data/lib/datadog/core/environment/execution.rb +3 -3
- data/lib/datadog/core/environment/ext.rb +21 -15
- 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 +47 -11
- data/lib/datadog/core/environment/platform.rb +8 -8
- data/lib/datadog/core/environment/process.rb +54 -19
- data/lib/datadog/core/environment/socket.rb +15 -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 +11 -0
- data/lib/datadog/core/extensions.rb +1 -1
- data/lib/datadog/core/feature_flags.rb +3 -3
- data/lib/datadog/core/git/ext.rb +4 -4
- data/lib/datadog/core/knuth_sampler.rb +3 -1
- data/lib/datadog/core/logger.rb +3 -3
- data/lib/datadog/core/logging/ext.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +26 -26
- 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 +8 -8
- data/lib/datadog/core/rate_limiter.rb +1 -1
- data/lib/datadog/core/remote/client/capabilities.rb +67 -15
- data/lib/datadog/core/remote/client.rb +18 -18
- data/lib/datadog/core/remote/component.rb +57 -32
- 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/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 +10 -10
- 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 +5 -5
- data/lib/datadog/core/runtime/ext.rb +22 -22
- data/lib/datadog/core/runtime/metrics.rb +10 -10
- 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 +16 -13
- data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
- data/lib/datadog/core/telemetry/emitter.rb +5 -5
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +10 -9
- 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 +32 -0
- 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 +142 -193
- 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 -22
- data/lib/datadog/core/telemetry/ext.rb +11 -10
- 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 -8
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +16 -11
- 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 +26 -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 +6 -6
- 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 -7
- data/lib/datadog/core/transport/response.rb +1 -1
- 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 +23 -0
- data/lib/datadog/core/utils/duration.rb +1 -1
- data/lib/datadog/core/utils/{array.rb → enumerable_compat.rb} +2 -2
- data/lib/datadog/core/utils/forking.rb +3 -1
- data/lib/datadog/core/utils/hash.rb +0 -23
- 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.rb +1 -1
- 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 +68 -0
- data/lib/datadog/core/utils/time.rb +18 -52
- data/lib/datadog/core/utils/url.rb +1 -1
- data/lib/datadog/core/utils.rb +5 -5
- data/lib/datadog/core/workers/async.rb +2 -2
- data/lib/datadog/core/workers/polling.rb +2 -2
- data/lib/datadog/core/workers/runtime_metrics.rb +4 -4
- data/lib/datadog/core.rb +7 -5
- data/lib/datadog/data_streams/configuration.rb +40 -1
- 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 +28 -30
- data/lib/datadog/data_streams/processor.rb +93 -62
- 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 +16 -8
- data/lib/datadog/di/boot.rb +25 -24
- data/lib/datadog/di/capture_expression.rb +21 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
- data/lib/datadog/di/capture_limits.rb +41 -0
- data/lib/datadog/di/code_tracker.rb +218 -16
- data/lib/datadog/di/component.rb +123 -37
- data/lib/datadog/di/configuration.rb +241 -2
- data/lib/datadog/di/context.rb +9 -3
- data/lib/datadog/di/contrib/active_record.rb +6 -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 +114 -38
- 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/error.rb +10 -0
- data/lib/datadog/di/fatal_exceptions.rb +26 -0
- data/lib/datadog/di/instrumenter.rb +528 -184
- data/lib/datadog/di/logger.rb +3 -3
- data/lib/datadog/di/preload.rb +1 -1
- data/lib/datadog/di/probe.rb +69 -2
- data/lib/datadog/di/probe_builder.rb +98 -15
- data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +14 -9
- data/lib/datadog/di/probe_manager.rb +73 -15
- data/lib/datadog/di/probe_notification_builder.rb +178 -25
- data/lib/datadog/di/probe_notifier_worker.rb +57 -37
- data/lib/datadog/di/probe_repository.rb +1 -1
- data/lib/datadog/di/redactor.rb +16 -1
- data/lib/datadog/di/remote.rb +187 -26
- data/lib/datadog/di/serializer.rb +79 -35
- 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 +10 -10
- data/lib/datadog/di/transport/input.rb +18 -14
- data/lib/datadog/di/utils.rb +43 -15
- data/lib/datadog/di.rb +147 -3
- data/lib/datadog/error_tracking/collector.rb +3 -2
- data/lib/datadog/error_tracking/component.rb +12 -12
- data/lib/datadog/error_tracking/configuration.rb +55 -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 +91 -33
- data/lib/datadog/kit/appsec/events.rb +25 -25
- data/lib/datadog/kit/enable_core_dumps.rb +3 -3
- data/lib/datadog/kit/identity.rb +18 -18
- data/lib/datadog/kit/tracing/method_tracer.rb +9 -6
- data/lib/datadog/kit.rb +1 -1
- data/lib/datadog/open_feature/component.rb +62 -13
- data/lib/datadog/open_feature/configuration.rb +22 -1
- data/lib/datadog/open_feature/evaluation_engine.rb +38 -12
- 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 -6
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +442 -0
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +544 -0
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +105 -0
- data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +51 -0
- 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 +149 -0
- data/lib/datadog/open_feature/native_evaluator.rb +56 -7
- data/lib/datadog/open_feature/noop_evaluator.rb +8 -3
- data/lib/datadog/open_feature/provider.rb +115 -21
- data/lib/datadog/open_feature/remote.rb +3 -3
- data/lib/datadog/open_feature/resolution_details.rb +4 -2
- data/lib/datadog/open_feature/transport.rb +71 -12
- data/lib/datadog/open_feature.rb +2 -2
- 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 +95 -28
- data/lib/datadog/opentelemetry/ext.rb +9 -0
- data/lib/datadog/opentelemetry/logs.rb +98 -0
- data/lib/datadog/opentelemetry/metrics.rb +17 -44
- data/lib/datadog/opentelemetry/sdk/configurator.rb +46 -6
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
- data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +9 -16
- data/lib/datadog/opentelemetry/sdk/propagator.rb +17 -11
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +18 -15
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +32 -32
- data/lib/datadog/opentelemetry/sdk.rb +19 -0
- data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
- data/lib/datadog/opentelemetry/trace.rb +4 -1
- data/lib/datadog/opentelemetry.rb +8 -7
- data/lib/datadog/profiling/collectors/code_provenance.rb +36 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +40 -3
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +12 -4
- data/lib/datadog/profiling/collectors/info.rb +19 -10
- data/lib/datadog/profiling/collectors/thread_context.rb +16 -22
- data/lib/datadog/profiling/component.rb +41 -34
- data/lib/datadog/profiling/exporter.rb +38 -13
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +6 -5
- data/lib/datadog/profiling/ext.rb +0 -2
- data/lib/datadog/profiling/flush.rb +21 -12
- data/lib/datadog/profiling/http_transport.rb +13 -2
- data/lib/datadog/profiling/load_native_extension.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +13 -5
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/sequence_tracker.rb +1 -1
- data/lib/datadog/profiling/stack_recorder.rb +0 -8
- data/lib/datadog/profiling/tag_builder.rb +19 -19
- data/lib/datadog/profiling/tasks/exec.rb +9 -4
- data/lib/datadog/profiling/tasks/help.rb +1 -0
- data/lib/datadog/profiling/tasks/setup.rb +2 -2
- data/lib/datadog/profiling.rb +32 -29
- data/lib/datadog/ruby_version.rb +25 -0
- data/lib/datadog/single_step_instrument.rb +2 -2
- data/lib/datadog/symbol_database/component.rb +734 -0
- data/lib/datadog/symbol_database/configuration.rb +73 -0
- data/lib/datadog/symbol_database/extensions.rb +19 -0
- data/lib/datadog/symbol_database/extractor.rb +1110 -0
- data/lib/datadog/symbol_database/file_hash.rb +48 -0
- data/lib/datadog/symbol_database/logger.rb +43 -0
- data/lib/datadog/symbol_database/remote.rb +195 -0
- data/lib/datadog/symbol_database/scope.rb +102 -0
- data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
- data/lib/datadog/symbol_database/service_version.rb +66 -0
- data/lib/datadog/symbol_database/symbol.rb +69 -0
- data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
- data/lib/datadog/symbol_database/transport/http.rb +45 -0
- data/lib/datadog/symbol_database/transport.rb +54 -0
- data/lib/datadog/symbol_database/uploader.rb +230 -0
- data/lib/datadog/symbol_database.rb +71 -0
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +8 -8
- data/lib/datadog/tracing/client_ip.rb +4 -4
- data/lib/datadog/tracing/component.rb +39 -7
- 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 +52 -38
- data/lib/datadog/tracing/configuration/http.rb +2 -2
- data/lib/datadog/tracing/configuration/settings.rb +51 -17
- data/lib/datadog/tracing/context.rb +1 -1
- data/lib/datadog/tracing/context_provider.rb +2 -2
- 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 +9 -6
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +8 -5
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +9 -6
- 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 +8 -5
- 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 +7 -4
- 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 +15 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +31 -3
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +5 -3
- 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 +10 -7
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +11 -8
- 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 +62 -0
- data/lib/datadog/tracing/contrib/active_job/event.rb +3 -3
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +10 -7
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +10 -7
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +10 -7
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +10 -7
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +10 -7
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +10 -7
- 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 +17 -5
- 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 +7 -7
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +8 -9
- 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 +9 -9
- 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 +9 -9
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +12 -14
- 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 +4 -4
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +14 -17
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +5 -8
- 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 +3 -3
- 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 +7 -11
- 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/component.rb +1 -1
- 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 +20 -5
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
- 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 +6 -10
- 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 +3 -3
- 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 +7 -5
- data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
- 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 +12 -16
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +4 -4
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +9 -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 +4 -11
- 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 +10 -14
- data/lib/datadog/tracing/contrib/excon/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/ext.rb +20 -18
- data/lib/datadog/tracing/contrib/extensions.rb +11 -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 +10 -14
- 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 +28 -25
- 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 +38 -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 +11 -15
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +11 -15
- 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 +11 -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 +7 -6
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +4 -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 +4 -3
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +6 -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 +10 -8
- data/lib/datadog/tracing/contrib/http/ext.rb +11 -11
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +10 -14
- 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 +7 -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 +12 -12
- 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 +10 -14
- 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 +4 -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 +4 -4
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +6 -6
- 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 +11 -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 +9 -9
- data/lib/datadog/tracing/contrib/karafka.rb +7 -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 +9 -9
- data/lib/datadog/tracing/contrib/mongodb/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -21
- 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 +7 -11
- 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 +15 -19
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +5 -5
- 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 +19 -23
- 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 +8 -10
- 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 +19 -16
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +3 -3
- 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 +3 -2
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/event.rb +5 -9
- 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 +9 -3
- data/lib/datadog/tracing/contrib/rack/ext.rb +43 -16
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +24 -1
- data/lib/datadog/tracing/contrib/rack/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +28 -25
- data/lib/datadog/tracing/contrib/rack/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +4 -4
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +12 -10
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +124 -6
- 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/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +8 -9
- data/lib/datadog/tracing/contrib/rails/railtie.rb +4 -4
- data/lib/datadog/tracing/contrib/rails/runner.rb +4 -2
- 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 +9 -7
- 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 +40 -6
- data/lib/datadog/tracing/contrib/redis/tags.rb +6 -11
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +16 -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 +6 -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 +6 -10
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/roda/ext.rb +6 -5
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +8 -5
- 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 +7 -10
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +6 -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 +103 -16
- 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 +3 -2
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +9 -8
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +12 -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_internal_tracer/heartbeat.rb +2 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +15 -14
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +10 -10
- data/lib/datadog/tracing/contrib/sidekiq.rb +7 -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 +2 -2
- 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 +11 -10
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +9 -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 +5 -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 +4 -0
- 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 +4 -4
- 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 +5 -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 +7 -11
- 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.rb → hash_formatter.rb} +3 -3
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +10 -10
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +11 -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 +7 -6
- data/lib/datadog/tracing/contrib.rb +62 -54
- data/lib/datadog/tracing/correlation.rb +12 -12
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -12
- 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 +81 -28
- data/lib/datadog/tracing/distributed/datadog.rb +34 -32
- 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 +46 -11
- data/lib/datadog/tracing/distributed/propagation_policy.rb +5 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +29 -263
- 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 +2 -2
- data/lib/datadog/tracing/ext.rb +9 -0
- 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 +76 -66
- 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 +5 -5
- data/lib/datadog/tracing/metadata.rb +4 -4
- data/lib/datadog/tracing/otel_thread_context.rb +34 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/pipeline.rb +3 -3
- data/lib/datadog/tracing/remote.rb +227 -21
- data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/ext.rb +9 -7
- data/lib/datadog/tracing/sampling/matcher.rb +4 -4
- data/lib/datadog/tracing/sampling/priority_sampler.rb +17 -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 +5 -5
- data/lib/datadog/tracing/sampling/rule_sampler.rb +68 -37
- 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 +10 -10
- data/lib/datadog/tracing/span.rb +9 -9
- data/lib/datadog/tracing/span_event.rb +5 -5
- data/lib/datadog/tracing/span_operation.rb +39 -26
- data/lib/datadog/tracing/sync_writer.rb +12 -7
- data/lib/datadog/tracing/trace_digest.rb +29 -4
- data/lib/datadog/tracing/trace_operation.rb +112 -31
- data/lib/datadog/tracing/trace_segment.rb +10 -10
- data/lib/datadog/tracing/tracer.rb +68 -27
- 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/traces.rb +8 -8
- data/lib/datadog/tracing/transport/http.rb +10 -10
- data/lib/datadog/tracing/transport/io/client.rb +3 -3
- 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.rb +379 -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/trace_formatter.rb +10 -10
- data/lib/datadog/tracing/transport/traces.rb +11 -31
- data/lib/datadog/tracing/utils.rb +2 -2
- data/lib/datadog/tracing/workers.rb +4 -3
- 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 +15 -11
- metadata +92 -22
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
- data/lib/datadog/ai_guard/configuration/settings.rb +0 -113
- data/lib/datadog/appsec/configuration/settings.rb +0 -423
- data/lib/datadog/core/utils/base64.rb +0 -22
- data/lib/datadog/data_streams/configuration/settings.rb +0 -49
- data/lib/datadog/di/configuration/settings.rb +0 -243
- data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -82
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
#include "setup_signal_handler.h"
|
|
18
18
|
#include "time_helpers.h"
|
|
19
19
|
|
|
20
|
+
#ifdef __APPLE__
|
|
21
|
+
#include "macos_sampler_thread.h"
|
|
22
|
+
#endif
|
|
23
|
+
|
|
20
24
|
// Used to trigger the execution of Collectors::ThreadContext, which implements all of the sampling logic
|
|
21
25
|
// itself; this class only implements the "when to do it" part.
|
|
22
26
|
//
|
|
@@ -64,14 +68,24 @@
|
|
|
64
68
|
// 4. The Ruby VM calls our `sample_from_postponed_job` from a thread holding the global VM lock. A sample is recorded by
|
|
65
69
|
// calling `thread_context_collector_sample`.
|
|
66
70
|
//
|
|
67
|
-
//
|
|
71
|
+
//
|
|
72
|
+
// ### Hooks and TracePoints
|
|
73
|
+
//
|
|
74
|
+
// This class uses various hooks:
|
|
75
|
+
// * A RUBY_INTERNAL_EVENT_GC_ENTER & RUBY_INTERNAL_EVENT_GC_EXIT TracePoint
|
|
76
|
+
// * A RUBY_INTERNAL_EVENT_NEWOBJ "event hook"/internal tracepoint
|
|
77
|
+
// * A GVL thread event hook
|
|
78
|
+
//
|
|
79
|
+
// We refer to those collectively as "hooks".
|
|
80
|
+
//
|
|
81
|
+
// ### Hooks and Forking
|
|
68
82
|
//
|
|
69
83
|
// When the Ruby VM forks, the CPU/Wall-time profiling stops naturally because it's triggered by a background thread
|
|
70
84
|
// that doesn't get automatically restarted by the VM on the child process. (The profiler does trigger its restart at
|
|
71
85
|
// some point -- see `Profiling::Tasks::Setup` for details).
|
|
72
86
|
//
|
|
73
|
-
// But this doesn't apply to any
|
|
74
|
-
// always remember consider this case of -- the worker thread may not be alive but the
|
|
87
|
+
// But this doesn't apply to any hooks this class may use, which will continue to be active. Thus, we need to
|
|
88
|
+
// always remember consider this case of -- the worker thread may not be alive but the hooks can continue to
|
|
75
89
|
// trigger samples.
|
|
76
90
|
//
|
|
77
91
|
// ---
|
|
@@ -87,7 +101,7 @@ unsigned int MAX_ALLOC_WEIGHT = 10000;
|
|
|
87
101
|
static rb_postponed_job_handle_t sample_from_postponed_job_handle;
|
|
88
102
|
static rb_postponed_job_handle_t after_gc_from_postponed_job_handle;
|
|
89
103
|
static rb_postponed_job_handle_t after_gvl_running_from_postponed_job_handle;
|
|
90
|
-
static rb_postponed_job_handle_t
|
|
104
|
+
static rb_postponed_job_handle_t commit_heap_recordings_from_postponed_job_may_lose_gvl_handle;
|
|
91
105
|
#endif
|
|
92
106
|
|
|
93
107
|
// Contains state for a single CpuAndWallTimeWorker instance
|
|
@@ -103,6 +117,8 @@ typedef struct {
|
|
|
103
117
|
bool skip_idle_samples_for_testing;
|
|
104
118
|
bool sighandler_sampling_enabled;
|
|
105
119
|
uint32_t cpu_sampling_interval_ms;
|
|
120
|
+
// Minimum duration of a "Waiting for GVL" period to trigger a sample
|
|
121
|
+
uint32_t waiting_for_gvl_threshold_ns;
|
|
106
122
|
VALUE self_instance;
|
|
107
123
|
VALUE thread_context_collector_instance;
|
|
108
124
|
VALUE idle_sampling_helper_instance;
|
|
@@ -123,9 +139,20 @@ typedef struct {
|
|
|
123
139
|
|
|
124
140
|
// Others
|
|
125
141
|
|
|
126
|
-
// Used to detect/avoid nested sampling,
|
|
127
|
-
//
|
|
128
|
-
// sampling.
|
|
142
|
+
// Used to detect/avoid nested sampling, and intended to behave as a lock to ensure the profiler doesn't recurse on itself,
|
|
143
|
+
// e.g. when on_newobj_event gets triggered by a memory allocation that happens during another sample, or when the
|
|
144
|
+
// signal handler gets triggered while we're already in the middle of sampling.
|
|
145
|
+
//
|
|
146
|
+
// It's not an actual lock because we rely on the GVL for correct synchronization
|
|
147
|
+
// (and thus this flag is only valid when we know we have the GVL).
|
|
148
|
+
//
|
|
149
|
+
// Similar to a lock, it should not be held across long-running operations,
|
|
150
|
+
// **in particular it MUST NEVER be held during operations where we might lose the GVL**
|
|
151
|
+
// because effectively that would stop the profiler from working until control
|
|
152
|
+
// goes back to that special thread, which on a contended Ruby app, can take hundreds of ms (or more).
|
|
153
|
+
//
|
|
154
|
+
// Because what we want is "profiler doesn't recurse on itself" we want this to behave as a non-reentrant lock
|
|
155
|
+
// (FIXME: We should have checks for this)
|
|
129
156
|
//
|
|
130
157
|
// @ivoanjo: Right now we always sample inside `safely_call`; if that ever changes, this flag may need to become
|
|
131
158
|
// volatile/atomic/have some barriers to ensure it's visible during e.g. signal handlers.
|
|
@@ -150,8 +177,6 @@ typedef struct {
|
|
|
150
177
|
unsigned int signal_handler_enqueued_sample;
|
|
151
178
|
// How many times we prepared a sample (sampled directly) from the signal handler
|
|
152
179
|
unsigned int signal_handler_prepared_sample;
|
|
153
|
-
// How many times the signal handler was called from the wrong thread
|
|
154
|
-
unsigned int signal_handler_wrong_thread;
|
|
155
180
|
// How many times we actually tried to interrupt a thread for sampling
|
|
156
181
|
unsigned int interrupt_thread_attempts;
|
|
157
182
|
|
|
@@ -178,6 +203,11 @@ typedef struct {
|
|
|
178
203
|
unsigned int allocations_during_sample;
|
|
179
204
|
|
|
180
205
|
// # GVL profiling stats
|
|
206
|
+
// Note that this tracks two kind of samples from RESUMED:
|
|
207
|
+
// * samples when Waiting for GVL for more than the threshold
|
|
208
|
+
// * samples for the skip-samples-while-without-GVL optimization,
|
|
209
|
+
// which are needed to attribute the time without GVL to the correct Ruby stack
|
|
210
|
+
|
|
181
211
|
// How many times we triggered the after_gvl_running sampling
|
|
182
212
|
unsigned int after_gvl_running;
|
|
183
213
|
// How many times we skipped the after_gvl_running sampling
|
|
@@ -186,6 +216,11 @@ typedef struct {
|
|
|
186
216
|
uint64_t gvl_sampling_time_ns_min;
|
|
187
217
|
uint64_t gvl_sampling_time_ns_max;
|
|
188
218
|
uint64_t gvl_sampling_time_ns_total;
|
|
219
|
+
|
|
220
|
+
struct vm_metrics {
|
|
221
|
+
// Total time spent waiting for the GVL
|
|
222
|
+
uint64_t gvl_waiting_time_ns_total;
|
|
223
|
+
} vm_metrics;
|
|
189
224
|
} stats;
|
|
190
225
|
} cpu_and_wall_time_worker_state;
|
|
191
226
|
|
|
@@ -208,6 +243,7 @@ static VALUE _native_failure_exception_during_operation(DDTRACE_UNUSED VALUE sel
|
|
|
208
243
|
static void testing_signal_handler(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
|
|
209
244
|
static VALUE _native_install_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
210
245
|
static VALUE _native_remove_testing_signal_handler(DDTRACE_UNUSED VALUE self);
|
|
246
|
+
static VALUE _native_install_sigprof_handler_on_altstack(DDTRACE_UNUSED VALUE self);
|
|
211
247
|
static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self);
|
|
212
248
|
static VALUE _native_gc_tracepoint(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
213
249
|
static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused);
|
|
@@ -230,10 +266,10 @@ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state);
|
|
|
230
266
|
static void sleep_for(uint64_t time_ns);
|
|
231
267
|
static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self);
|
|
232
268
|
static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2);
|
|
233
|
-
static void
|
|
269
|
+
static void disable_hooks(cpu_and_wall_time_worker_state *state);
|
|
234
270
|
static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
|
|
235
271
|
static VALUE rescued_sample_allocation(VALUE tracepoint_data);
|
|
236
|
-
static VALUE
|
|
272
|
+
static VALUE rescued_commit_heap_recordings_may_lose_gvl(VALUE self_instance);
|
|
237
273
|
static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
|
|
238
274
|
static void delayed_error_clock_failure(cpu_and_wall_time_worker_state *state);
|
|
239
275
|
static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
|
|
@@ -248,11 +284,12 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
|
|
|
248
284
|
static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance);
|
|
249
285
|
static VALUE handle_sampling_failure_rescued_sample_from_postponed_job(VALUE self_instance, VALUE exception);
|
|
250
286
|
static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VALUE self_instance, VALUE exception);
|
|
287
|
+
static VALUE handle_sampling_failure_thread_context_collector_heap_update(VALUE self_instance, VALUE exception);
|
|
251
288
|
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception);
|
|
252
|
-
static VALUE
|
|
289
|
+
static VALUE handle_sampling_failure_rescued_commit_heap_recordings(VALUE self_instance, VALUE exception);
|
|
253
290
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state);
|
|
254
291
|
static inline void during_sample_exit(cpu_and_wall_time_worker_state* state);
|
|
255
|
-
static void
|
|
292
|
+
static void commit_heap_recordings_from_postponed_job_may_lose_gvl(DDTRACE_UNUSED void *_unused);
|
|
256
293
|
|
|
257
294
|
// We're using `on_newobj_event` function with `rb_add_event_hook2`, which requires in its public signature a function
|
|
258
295
|
// with signature `rb_event_hook_func_t` which doesn't match `on_newobj_event`.
|
|
@@ -280,6 +317,15 @@ static VALUE active_sampler_instance = Qnil;
|
|
|
280
317
|
static cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
|
|
281
318
|
static VALUE clock_failure_exception_class = Qnil;
|
|
282
319
|
|
|
320
|
+
// Stats that live outside of any particular `cpu_and_wall_time_worker_state`, so that they can always be safely
|
|
321
|
+
// touched, even when we're not sure it's safe to touch the state (e.g. signal handler, no GVL, etc).
|
|
322
|
+
typedef struct {
|
|
323
|
+
// How many times we skipped sampling because we were running on the alternate signal stack (e.g. nested inside
|
|
324
|
+
// another signal handler, presumably GC compaction).
|
|
325
|
+
unsigned int signal_handler_skipped_sample_on_altstack;
|
|
326
|
+
} global_stats_t;
|
|
327
|
+
static global_stats_t global_stats;
|
|
328
|
+
|
|
283
329
|
// See handle_sampling_signal for details on what this does
|
|
284
330
|
#ifdef NO_POSTPONED_TRIGGER
|
|
285
331
|
static void *gc_finalize_deferred_workaround;
|
|
@@ -300,13 +346,14 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
300
346
|
sample_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, sample_from_postponed_job, NULL);
|
|
301
347
|
after_gc_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gc_from_postponed_job, NULL);
|
|
302
348
|
after_gvl_running_from_postponed_job_handle = rb_postponed_job_preregister(unused_flags, after_gvl_running_from_postponed_job, NULL);
|
|
303
|
-
|
|
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);
|
|
304
351
|
|
|
305
352
|
if (
|
|
306
353
|
sample_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
307
354
|
after_gc_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
308
355
|
after_gvl_running_from_postponed_job_handle == POSTPONED_JOB_HANDLE_INVALID ||
|
|
309
|
-
|
|
356
|
+
commit_heap_recordings_from_postponed_job_may_lose_gvl_handle == POSTPONED_JOB_HANDLE_INVALID
|
|
310
357
|
) {
|
|
311
358
|
raise_error(rb_eRuntimeError, "Failed to register profiler postponed jobs (got POSTPONED_JOB_HANDLE_INVALID)");
|
|
312
359
|
}
|
|
@@ -345,6 +392,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
|
|
|
345
392
|
rb_define_singleton_method(collectors_cpu_and_wall_time_worker_class, "_native_resume_signals", _native_resume_signals, 0);
|
|
346
393
|
rb_define_singleton_method(testing_module, "_native_install_testing_signal_handler", _native_install_testing_signal_handler, 0);
|
|
347
394
|
rb_define_singleton_method(testing_module, "_native_remove_testing_signal_handler", _native_remove_testing_signal_handler, 0);
|
|
395
|
+
rb_define_singleton_method(testing_module, "_native_install_sigprof_handler_on_altstack", _native_install_sigprof_handler_on_altstack, 0);
|
|
348
396
|
rb_define_singleton_method(testing_module, "_native_trigger_sample", _native_trigger_sample, 0);
|
|
349
397
|
rb_define_singleton_method(testing_module, "_native_gc_tracepoint", _native_gc_tracepoint, 1);
|
|
350
398
|
rb_define_singleton_method(testing_module, "_native_simulate_handle_sampling_signal", _native_simulate_handle_sampling_signal, 0);
|
|
@@ -385,6 +433,7 @@ static VALUE _native_new(VALUE klass) {
|
|
|
385
433
|
state->skip_idle_samples_for_testing = false;
|
|
386
434
|
state->sighandler_sampling_enabled = false;
|
|
387
435
|
state->cpu_sampling_interval_ms = 10;
|
|
436
|
+
state->waiting_for_gvl_threshold_ns = 10 * 1000 * 1000;
|
|
388
437
|
state->thread_context_collector_instance = Qnil;
|
|
389
438
|
state->idle_sampling_helper_instance = Qnil;
|
|
390
439
|
state->owner_thread = Qnil;
|
|
@@ -430,6 +479,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
430
479
|
VALUE skip_idle_samples_for_testing = rb_hash_fetch(options, ID2SYM(rb_intern("skip_idle_samples_for_testing")));
|
|
431
480
|
VALUE sighandler_sampling_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("sighandler_sampling_enabled")));
|
|
432
481
|
VALUE cpu_sampling_interval_ms = rb_hash_fetch(options, ID2SYM(rb_intern("cpu_sampling_interval_ms")));
|
|
482
|
+
VALUE waiting_for_gvl_threshold_ns = rb_hash_fetch(options, ID2SYM(rb_intern("waiting_for_gvl_threshold_ns")));
|
|
433
483
|
|
|
434
484
|
ENFORCE_BOOLEAN(gc_profiling_enabled);
|
|
435
485
|
ENFORCE_BOOLEAN(no_signals_workaround_enabled);
|
|
@@ -441,6 +491,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
441
491
|
ENFORCE_BOOLEAN(skip_idle_samples_for_testing)
|
|
442
492
|
ENFORCE_BOOLEAN(sighandler_sampling_enabled)
|
|
443
493
|
ENFORCE_TYPE(cpu_sampling_interval_ms, T_FIXNUM);
|
|
494
|
+
ENFORCE_TYPE(waiting_for_gvl_threshold_ns, T_FIXNUM);
|
|
444
495
|
|
|
445
496
|
cpu_and_wall_time_worker_state *state;
|
|
446
497
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
@@ -454,6 +505,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
|
454
505
|
state->skip_idle_samples_for_testing = (skip_idle_samples_for_testing == Qtrue);
|
|
455
506
|
state->sighandler_sampling_enabled = (sighandler_sampling_enabled == Qtrue);
|
|
456
507
|
state->cpu_sampling_interval_ms = NUM2INT(cpu_sampling_interval_ms);
|
|
508
|
+
state->waiting_for_gvl_threshold_ns = NUM2UINT(waiting_for_gvl_threshold_ns);
|
|
457
509
|
|
|
458
510
|
double total_overhead_target_percentage = NUM2DBL(dynamic_sampling_rate_overhead_target_percentage);
|
|
459
511
|
if (!state->allocation_profiling_enabled) {
|
|
@@ -492,7 +544,7 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
492
544
|
|
|
493
545
|
// If we already got a delayed exception registered even before starting, raise before starting
|
|
494
546
|
if (state->failure_exception != Qnil) {
|
|
495
|
-
|
|
547
|
+
disable_hooks(state);
|
|
496
548
|
rb_exc_raise(state->failure_exception);
|
|
497
549
|
}
|
|
498
550
|
|
|
@@ -502,13 +554,13 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
502
554
|
raise_error(rb_eRuntimeError, "Could not start CpuAndWallTimeWorker: There's already another instance of CpuAndWallTimeWorker active in a different thread");
|
|
503
555
|
} else {
|
|
504
556
|
// The previously active thread seems to have died without cleaning up after itself.
|
|
505
|
-
// In this case, we can still go ahead and start the profiler BUT we make sure to disable any existing
|
|
557
|
+
// In this case, we can still go ahead and start the profiler BUT we make sure to disable any existing hooks
|
|
506
558
|
// first as:
|
|
507
|
-
// a) If this is a new instance of the CpuAndWallTimeWorker, we don't want the
|
|
559
|
+
// a) If this is a new instance of the CpuAndWallTimeWorker, we don't want the hooks from the old instance
|
|
508
560
|
// being kept around
|
|
509
561
|
// b) If this is the same instance of the CpuAndWallTimeWorker if we call enable on a tracepoint that is already
|
|
510
562
|
// enabled, it will start firing more than once, see https://bugs.ruby-lang.org/issues/19114 for details.
|
|
511
|
-
|
|
563
|
+
disable_hooks(old_state);
|
|
512
564
|
}
|
|
513
565
|
}
|
|
514
566
|
|
|
@@ -516,11 +568,20 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
516
568
|
// situation we stop immediately and never even start the sampling trigger loop.
|
|
517
569
|
if (state->stop_thread == rb_thread_current()) return Qnil;
|
|
518
570
|
|
|
571
|
+
thread_context_collector_profiler_internal_thread_started();
|
|
572
|
+
|
|
519
573
|
// Reset the dynamic sampling rate state, if any (reminder: the monotonic clock reference may change after a fork)
|
|
520
574
|
dynamic_sampling_rate_reset(&state->cpu_dynamic_sampling_rate);
|
|
521
575
|
long now = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
|
|
522
576
|
discrete_dynamic_sampler_reset(&state->allocation_sampler, now);
|
|
523
577
|
|
|
578
|
+
// Reset per-thread state, if any. This ensures there's no leftover state from a previous profiler run that would
|
|
579
|
+
// affect or be included in samples taken by this profiler about to run.
|
|
580
|
+
//
|
|
581
|
+
// NOTE: This needs to be called before we enable any hooks or anything that could trigger samples (e.g.
|
|
582
|
+
// reset cannot be concurrent with any sampling activity)
|
|
583
|
+
thread_context_collector_reset_all_per_thread_contexts(state->thread_context_collector_instance);
|
|
584
|
+
|
|
524
585
|
// This write to a global is thread-safe BECAUSE we're still holding on to the global VM lock at this point
|
|
525
586
|
active_sampler_instance_state = state;
|
|
526
587
|
active_sampler_instance = instance;
|
|
@@ -530,13 +591,21 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
530
591
|
|
|
531
592
|
block_sigprof_signal_handler_from_running_in_current_thread(); // We want to interrupt the thread with the global VM lock, never this one
|
|
532
593
|
|
|
594
|
+
#ifdef __APPLE__
|
|
595
|
+
// Promote the native thread that will run the sampling loop to a realtime scheduling policy so
|
|
596
|
+
// its periodic wake-ups are not subject to the default ~1-2ms timeshare wake latency. The matching
|
|
597
|
+
// demote happens below in this same function, alongside the SIGPROF unblock dance, so both per-thread
|
|
598
|
+
// policy changes are reverted before Ruby reuses this native thread for an unrelated Ruby thread.
|
|
599
|
+
promote_sampler_thread_to_realtime(MILLIS_AS_NS(state->cpu_sampling_interval_ms));
|
|
600
|
+
#endif
|
|
601
|
+
|
|
533
602
|
// Release GVL, get to the actual work!
|
|
534
603
|
int exception_state;
|
|
535
604
|
rb_protect(release_gvl_and_run_sampling_trigger_loop, instance, &exception_state);
|
|
536
605
|
|
|
537
606
|
// The sample trigger loop finished (either cleanly or with an error); let's clean up
|
|
538
607
|
|
|
539
|
-
|
|
608
|
+
disable_hooks(state);
|
|
540
609
|
|
|
541
610
|
active_sampler_instance_state = NULL;
|
|
542
611
|
active_sampler_instance = Qnil;
|
|
@@ -551,6 +620,14 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
|
|
|
551
620
|
// had SIGPROF delivery blocked. :hide_the_pain_harold:
|
|
552
621
|
unblock_sigprof_signal_handler_from_running_in_current_thread();
|
|
553
622
|
|
|
623
|
+
#ifdef __APPLE__
|
|
624
|
+
// Pairs with promote_sampler_thread_to_realtime above. Same reasoning as the SIGPROF unblock:
|
|
625
|
+
// Ruby may reuse this native thread for an unrelated Ruby thread that would otherwise inherit
|
|
626
|
+
// our scheduler policy. Doing it here also covers the exception path, since grab_gvl_and_sample
|
|
627
|
+
// can raise and unwind out of the sampling loop.
|
|
628
|
+
demote_sampler_thread_from_realtime();
|
|
629
|
+
#endif
|
|
630
|
+
|
|
554
631
|
// Why replace and not use remove the signal handler? We do this because when a process receives a SIGPROF without
|
|
555
632
|
// having an explicit signal handler set up, the process will instantly terminate with a confusing
|
|
556
633
|
// "Profiling timer expired" message left behind. (This message doesn't come from us -- it's the default message for
|
|
@@ -588,8 +665,8 @@ static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exc
|
|
|
588
665
|
state->failure_exception = optional_exception;
|
|
589
666
|
state->failure_exception_during_operation = optional_exception_during_operation;
|
|
590
667
|
|
|
591
|
-
// Disable the
|
|
592
|
-
|
|
668
|
+
// Disable the hooks as soon as possible, so the VM doesn't keep on calling them
|
|
669
|
+
disable_hooks(state);
|
|
593
670
|
}
|
|
594
671
|
|
|
595
672
|
static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *optional_exception_during_operation) {
|
|
@@ -601,28 +678,70 @@ static VALUE stop(VALUE self_instance, VALUE optional_exception, const char *opt
|
|
|
601
678
|
return Qtrue;
|
|
602
679
|
}
|
|
603
680
|
|
|
681
|
+
// Our SIGPROF handler is not installed with SA_ONSTACK (see `install_sigprof_signal_handler`).
|
|
682
|
+
// If we detect our signal handler is running on the alt stack, it means we interrupted another signal handler
|
|
683
|
+
// that IS running on the alt stack -- in practice, Ruby's GC compaction read-barrier handler.
|
|
684
|
+
#ifdef __APPLE__
|
|
685
|
+
// On macOS, `ucontext->uc_stack.ss_sp` reports the (live) stack pointer near the top of the alt stack rather than the
|
|
686
|
+
// alt-stack base like Linux does, and `ss_size` is the full alt-stack size. Thus the linux version of the check
|
|
687
|
+
// didn't work for macOS.
|
|
688
|
+
// As an alternative, we query `sigaltstack()`; we save/restore errno since `sigaltstack()` may clobber it.
|
|
689
|
+
static bool is_running_on_alternate_signal_stack(DDTRACE_UNUSED void *ucontext) {
|
|
690
|
+
int old_errno = errno;
|
|
691
|
+
stack_t current_alt_stack;
|
|
692
|
+
bool on_alt_stack = sigaltstack(NULL, ¤t_alt_stack) == 0 && (current_alt_stack.ss_flags & SS_ONSTACK) != 0;
|
|
693
|
+
errno = old_errno;
|
|
694
|
+
return on_alt_stack;
|
|
695
|
+
}
|
|
696
|
+
#else
|
|
697
|
+
// NOTE: On Linux we use the alt-stack bounds from the `ucontext` rather than `sigaltstack()`, allowing us to avoid one syscall.
|
|
698
|
+
static bool is_running_on_alternate_signal_stack(void *ucontext) {
|
|
699
|
+
if (ucontext == NULL) return false;
|
|
700
|
+
|
|
701
|
+
stack_t alt_stack = ((ucontext_t *) ucontext)->uc_stack;
|
|
702
|
+
if (alt_stack.ss_size == 0) return false; // No alternate signal stack registered on this thread
|
|
703
|
+
|
|
704
|
+
char stack_local;
|
|
705
|
+
uintptr_t current_sp = (uintptr_t) &stack_local;
|
|
706
|
+
uintptr_t alt_stack_start = (uintptr_t) alt_stack.ss_sp;
|
|
707
|
+
|
|
708
|
+
return current_sp >= alt_stack_start && current_sp < alt_stack_start + alt_stack.ss_size;
|
|
709
|
+
}
|
|
710
|
+
#endif
|
|
711
|
+
|
|
604
712
|
// NOTE: Remember that this will run in the thread and within the scope of user code, including user C code.
|
|
605
713
|
// 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
|
|
606
714
|
// we do here can set `errno`, then we must be careful to restore the old `errno` after the fact.
|
|
607
|
-
static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info,
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
//
|
|
611
|
-
|
|
715
|
+
static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, void *ucontext) {
|
|
716
|
+
// If we're running on the alternate signal stack, we've interrupted another signal handler that's running
|
|
717
|
+
// there -- in practice, Ruby's GC compaction read-barrier handler.
|
|
718
|
+
// During GC compaction, Ruby protects pages containing Ruby objects, so many of the checks we do below are unsafe
|
|
719
|
+
// since they can touch those pages, and thus we just bail out here in this situation to avoid crashes.
|
|
720
|
+
if (is_running_on_alternate_signal_stack(ucontext)) {
|
|
721
|
+
global_stats.signal_handler_skipped_sample_on_altstack++;
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
612
724
|
|
|
725
|
+
// We must first check that we landed on the correct thread and can proceed.
|
|
726
|
+
// We must never touch the state before we confirm that we have landed on the thread that is holding the GVL on the main
|
|
727
|
+
// ractor as otherwise we may be concurrent with the profiler shutting down and removing its state.
|
|
613
728
|
if (
|
|
614
729
|
!ruby_native_thread_p() || // Not a Ruby thread
|
|
615
730
|
!is_current_thread_holding_the_gvl() || // Not safe to enqueue a sample from this thread
|
|
616
731
|
!ddtrace_rb_ractor_main_p() // We're not on the main Ractor; we currently don't support profiling non-main Ractors
|
|
617
|
-
)
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
732
|
+
) return;
|
|
733
|
+
|
|
734
|
+
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
735
|
+
|
|
736
|
+
// This can potentially happen if the CpuAndWallTimeWorker was stopped while the signal delivery was happening; nothing to do
|
|
737
|
+
if (state == NULL) return;
|
|
621
738
|
|
|
622
739
|
// We assume there can be no concurrent nor nested calls to handle_sampling_signal because
|
|
623
740
|
// 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)
|
|
624
741
|
// 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
|
|
625
742
|
// because it will not have the global VM lock
|
|
743
|
+
// c) `simulate_sampling_signal_delivery` calls us directly instead of via a real SIGPROF, and blocks SIGPROF delivery on its
|
|
744
|
+
// thread for the duration of that call, so it can't be nested into by a real SIGPROF either
|
|
626
745
|
|
|
627
746
|
state->stats.signal_handler_enqueued_sample++;
|
|
628
747
|
|
|
@@ -634,7 +753,7 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
|
|
|
634
753
|
if (sample_from_signal_handler) {
|
|
635
754
|
// Buffer current stack trace. Note that this will not actually record the sample, for that we still need to wait
|
|
636
755
|
// until the postponed job below gets run.
|
|
637
|
-
bool prepared = thread_context_collector_prepare_sample_inside_signal_handler(
|
|
756
|
+
bool prepared = thread_context_collector_prepare_sample_inside_signal_handler();
|
|
638
757
|
|
|
639
758
|
if (prepared) state->stats.signal_handler_prepared_sample++;
|
|
640
759
|
}
|
|
@@ -760,7 +879,7 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
760
879
|
during_sample_enter(state);
|
|
761
880
|
|
|
762
881
|
// Rescue against any exceptions that happen during sampling
|
|
763
|
-
safely_call(
|
|
882
|
+
VALUE needs_otel_span_key = safely_call(
|
|
764
883
|
rescued_sample_from_postponed_job,
|
|
765
884
|
state->self_instance,
|
|
766
885
|
state->self_instance,
|
|
@@ -768,6 +887,12 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
768
887
|
);
|
|
769
888
|
|
|
770
889
|
during_sample_exit(state);
|
|
890
|
+
|
|
891
|
+
// Extracting the otel span key can lose the GVL, so we move it outside `during_sample`
|
|
892
|
+
// (It can't raise: it rescues its own exceptions)
|
|
893
|
+
if (needs_otel_span_key == Qtrue) {
|
|
894
|
+
thread_context_collector_resolve_otel_span_key_may_lose_gvl(state->thread_context_collector_instance);
|
|
895
|
+
}
|
|
771
896
|
}
|
|
772
897
|
|
|
773
898
|
static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
@@ -778,13 +903,13 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
|
778
903
|
|
|
779
904
|
if (state->dynamic_sampling_rate_enabled && !dynamic_sampling_rate_should_sample(&state->cpu_dynamic_sampling_rate, wall_time_ns_before_sample)) {
|
|
780
905
|
state->stats.cpu_skipped++;
|
|
781
|
-
return
|
|
906
|
+
return Qfalse;
|
|
782
907
|
}
|
|
783
908
|
|
|
784
909
|
state->stats.cpu_sampled++;
|
|
785
910
|
|
|
786
|
-
|
|
787
|
-
|
|
911
|
+
bool needs_otel_span_key =
|
|
912
|
+
thread_context_collector_sample(state->thread_context_collector_instance, wall_time_ns_before_sample);
|
|
788
913
|
|
|
789
914
|
long wall_time_ns_after_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
|
|
790
915
|
long delta_ns = wall_time_ns_after_sample - wall_time_ns_before_sample;
|
|
@@ -798,8 +923,7 @@ static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
|
|
|
798
923
|
|
|
799
924
|
dynamic_sampling_rate_after_sample(&state->cpu_dynamic_sampling_rate, wall_time_ns_after_sample, sampling_time_ns);
|
|
800
925
|
|
|
801
|
-
|
|
802
|
-
return Qnil;
|
|
926
|
+
return needs_otel_span_key ? Qtrue : Qfalse;
|
|
803
927
|
}
|
|
804
928
|
|
|
805
929
|
// This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
|
|
@@ -825,7 +949,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
|
825
949
|
cpu_and_wall_time_worker_state *state;
|
|
826
950
|
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
827
951
|
|
|
828
|
-
// Final preparations: Setup signal handler and enable
|
|
952
|
+
// Final preparations: Setup signal handler and enable hooks. We run these here and not in `_native_sampling_loop`
|
|
829
953
|
// because they may raise exceptions.
|
|
830
954
|
install_sigprof_signal_handler(handle_sampling_signal, "handle_sampling_signal");
|
|
831
955
|
if (state->gc_profiling_enabled) rb_tracepoint_enable(state->gc_tracepoint);
|
|
@@ -840,15 +964,12 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
|
840
964
|
|
|
841
965
|
if (state->gvl_profiling_enabled) {
|
|
842
966
|
#ifndef NO_GVL_INSTRUMENTATION
|
|
843
|
-
#ifdef USE_GVL_PROFILING_3_2_WORKAROUNDS
|
|
844
|
-
gvl_profiling_state_thread_tracking_workaround();
|
|
845
|
-
#endif
|
|
846
|
-
|
|
847
967
|
state->gvl_profiling_hook = rb_internal_thread_add_event_hook(
|
|
848
968
|
on_gvl_event,
|
|
849
969
|
(
|
|
850
970
|
// For now we're only asking for these events, even though there's more
|
|
851
971
|
// (e.g. check docs or gvl-tracing gem)
|
|
972
|
+
RUBY_INTERNAL_THREAD_EVENT_SUSPENDED | /* released gvl */
|
|
852
973
|
RUBY_INTERNAL_THREAD_EVENT_READY /* waiting for gvl */ |
|
|
853
974
|
RUBY_INTERNAL_THREAD_EVENT_RESUMED /* running/runnable */
|
|
854
975
|
),
|
|
@@ -867,6 +988,8 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
|
|
|
867
988
|
// If we stopped sampling due to an exception, re-raise it (now in the worker thread)
|
|
868
989
|
if (state->failure_exception != Qnil) rb_exc_raise(state->failure_exception);
|
|
869
990
|
|
|
991
|
+
thread_context_collector_profiler_internal_thread_done(state->thread_context_collector_instance);
|
|
992
|
+
|
|
870
993
|
return Qnil;
|
|
871
994
|
}
|
|
872
995
|
|
|
@@ -905,6 +1028,28 @@ static VALUE _native_remove_testing_signal_handler(DDTRACE_UNUSED VALUE self) {
|
|
|
905
1028
|
return Qtrue;
|
|
906
1029
|
}
|
|
907
1030
|
|
|
1031
|
+
// Reproduces a profiler sample being taken in the middle of GC compaction: during compaction a SIGPROF can be
|
|
1032
|
+
// delivered while nested inside Ruby's read-barrier signal handler, which runs on the alternate signal stack. We
|
|
1033
|
+
// simulate that here by re-installing the production `handle_sampling_signal` with the `SA_ONSTACK` flag, so it runs
|
|
1034
|
+
// on the alternate signal stack just like it would in that scenario.
|
|
1035
|
+
//
|
|
1036
|
+
// The `SA_ONSTACK` will be undone by any next `replace_sigprof_signal_handler_with_empty_handler` /
|
|
1037
|
+
// `install_sigprof_signal_handler_internal` / `remove_sigprof_signal_handle` so this doesn't need a specific, symmetric
|
|
1038
|
+
// `uninstall` to undo this.
|
|
1039
|
+
static VALUE _native_install_sigprof_handler_on_altstack(DDTRACE_UNUSED VALUE self) {
|
|
1040
|
+
struct sigaction signal_handler_config = {
|
|
1041
|
+
.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK,
|
|
1042
|
+
.sa_sigaction = handle_sampling_signal,
|
|
1043
|
+
};
|
|
1044
|
+
sigemptyset(&signal_handler_config.sa_mask);
|
|
1045
|
+
|
|
1046
|
+
if (sigaction(SIGPROF, &signal_handler_config, NULL) != 0) {
|
|
1047
|
+
rb_sys_fail("Failed to install SA_ONSTACK SIGPROF signal handler for testing");
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
return Qtrue;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
908
1053
|
// This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
|
|
909
1054
|
// It SHOULD NOT be used for other purposes.
|
|
910
1055
|
static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self) {
|
|
@@ -987,6 +1132,15 @@ static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
|
987
1132
|
);
|
|
988
1133
|
|
|
989
1134
|
during_sample_exit(state);
|
|
1135
|
+
|
|
1136
|
+
// This part runs separately from above because it may lose the GVL and we don't want `during_sample` to be set in
|
|
1137
|
+
// such a situation
|
|
1138
|
+
safely_call(
|
|
1139
|
+
thread_context_collector_heap_update_may_lose_gvl,
|
|
1140
|
+
state->thread_context_collector_instance,
|
|
1141
|
+
state->self_instance,
|
|
1142
|
+
handle_sampling_failure_thread_context_collector_heap_update
|
|
1143
|
+
);
|
|
990
1144
|
}
|
|
991
1145
|
|
|
992
1146
|
// Equivalent to Ruby begin/rescue call, where we call a C function and jump to the exception handler if an
|
|
@@ -1024,18 +1178,21 @@ static VALUE _native_simulate_sample_from_postponed_job(DDTRACE_UNUSED VALUE sel
|
|
|
1024
1178
|
|
|
1025
1179
|
// After the Ruby VM forks, this method gets called in the child process to clean up any leftover state from the parent.
|
|
1026
1180
|
//
|
|
1027
|
-
// Assumption: This method gets called BEFORE restarting profiling. Note that profiling-related
|
|
1181
|
+
// Assumption: This method gets called BEFORE restarting profiling. Note that profiling-related hooks may still
|
|
1028
1182
|
// be active, so we make sure to disable them before calling into anything else, so that there are no components
|
|
1029
1183
|
// attempting to trigger samples at the same time as the reset is done.
|
|
1030
1184
|
//
|
|
1031
|
-
// In the future, if we add more other components with
|
|
1032
|
-
//
|
|
1185
|
+
// In the future, if we add more other components with hooks, we will need to coordinate stopping all such
|
|
1186
|
+
// hooks before doing the other cleaning steps.
|
|
1187
|
+
//
|
|
1188
|
+
// Note that tests call this method directly in the same process without forking,
|
|
1189
|
+
// and in such a case non-current Threads keep running.
|
|
1033
1190
|
static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
1034
1191
|
cpu_and_wall_time_worker_state *state;
|
|
1035
1192
|
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1036
1193
|
|
|
1037
|
-
// Disable all
|
|
1038
|
-
|
|
1194
|
+
// Disable all hooks, so that there are no more attempts to mutate the profile
|
|
1195
|
+
disable_hooks(state);
|
|
1039
1196
|
|
|
1040
1197
|
reset_stats_not_thread_safe(state);
|
|
1041
1198
|
|
|
@@ -1071,7 +1228,7 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
|
1071
1228
|
ID2SYM(rb_intern("simulated_signal_delivery")), /* => */ UINT2NUM(state->stats.simulated_signal_delivery),
|
|
1072
1229
|
ID2SYM(rb_intern("signal_handler_enqueued_sample")), /* => */ UINT2NUM(state->stats.signal_handler_enqueued_sample),
|
|
1073
1230
|
ID2SYM(rb_intern("signal_handler_prepared_sample")), /* => */ UINT2NUM(state->stats.signal_handler_prepared_sample),
|
|
1074
|
-
ID2SYM(rb_intern("
|
|
1231
|
+
ID2SYM(rb_intern("signal_handler_skipped_sample_on_altstack")), /* => */ UINT2NUM(global_stats.signal_handler_skipped_sample_on_altstack),
|
|
1075
1232
|
ID2SYM(rb_intern("interrupt_thread_attempts")), /* => */ UINT2NUM(state->stats.interrupt_thread_attempts),
|
|
1076
1233
|
|
|
1077
1234
|
// CPU Stats
|
|
@@ -1101,8 +1258,12 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
|
|
|
1101
1258
|
ID2SYM(rb_intern("gvl_sampling_time_ns_max")), /* => */ RUBY_NUM_OR_NIL(state->stats.gvl_sampling_time_ns_max, > 0, ULL2NUM),
|
|
1102
1259
|
ID2SYM(rb_intern("gvl_sampling_time_ns_total")), /* => */ RUBY_NUM_OR_NIL(state->stats.gvl_sampling_time_ns_total, > 0, ULL2NUM),
|
|
1103
1260
|
ID2SYM(rb_intern("gvl_sampling_time_ns_avg")), /* => */ RUBY_AVG_OR_NIL(state->stats.gvl_sampling_time_ns_total, state->stats.after_gvl_running),
|
|
1261
|
+
ID2SYM(rb_intern("gvl_waiting_time_ns_total")), /* => */ state->gvl_profiling_enabled ? ULL2NUM(state->stats.vm_metrics.gvl_waiting_time_ns_total) : Qnil,
|
|
1104
1262
|
};
|
|
1105
1263
|
for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(stats_as_hash, arguments[i], arguments[i+1]);
|
|
1264
|
+
|
|
1265
|
+
thread_context_collector_stats(state->thread_context_collector_instance, stats_as_hash);
|
|
1266
|
+
|
|
1106
1267
|
return stats_as_hash;
|
|
1107
1268
|
}
|
|
1108
1269
|
|
|
@@ -1110,6 +1271,7 @@ static VALUE _native_stats_reset_not_thread_safe(DDTRACE_UNUSED VALUE self, VALU
|
|
|
1110
1271
|
cpu_and_wall_time_worker_state *state;
|
|
1111
1272
|
TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1112
1273
|
reset_stats_not_thread_safe(state);
|
|
1274
|
+
thread_context_collector_stats_reset_not_thread_safe(state->thread_context_collector_instance);
|
|
1113
1275
|
return Qnil;
|
|
1114
1276
|
}
|
|
1115
1277
|
|
|
@@ -1119,11 +1281,19 @@ void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
|
|
|
1119
1281
|
// This can potentially happen if the CpuAndWallTimeWorker was stopped while the IdleSamplingHelper was trying to execute this action
|
|
1120
1282
|
if (state == NULL) return NULL;
|
|
1121
1283
|
|
|
1284
|
+
// Since this is not a real signal firing, we need to block SIGPROF delivery on this thread to avoid an actual SIGPROF
|
|
1285
|
+
// signal coming in nested and interrupting us on this thread. Thus we respect the invariant of "no nesting" for `handle_sampling_signal`.
|
|
1286
|
+
//
|
|
1287
|
+
// Not needed when `no_signals_workaround_enabled` is set: no SIGPROFs are ever sent in that mode, so there's nothing to mask.
|
|
1288
|
+
if (!state->no_signals_workaround_enabled) block_sigprof_signal_handler_from_running_in_current_thread();
|
|
1289
|
+
|
|
1122
1290
|
state->stats.simulated_signal_delivery++;
|
|
1123
1291
|
|
|
1124
1292
|
// `handle_sampling_signal` does a few things extra on top of `sample_from_postponed_job` so that's why we don't shortcut here
|
|
1125
1293
|
handle_sampling_signal(0, NULL, NULL);
|
|
1126
1294
|
|
|
1295
|
+
if (!state->no_signals_workaround_enabled) unblock_sigprof_signal_handler_from_running_in_current_thread();
|
|
1296
|
+
|
|
1127
1297
|
return NULL; // Unused
|
|
1128
1298
|
}
|
|
1129
1299
|
|
|
@@ -1136,12 +1306,15 @@ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state) {
|
|
|
1136
1306
|
// * Included in the following stats window (writes after stats retrieval and reset).
|
|
1137
1307
|
// Given the expected infrequency of resetting (~once per 60s profile) and the auxiliary/non-critical nature of these stats
|
|
1138
1308
|
// this momentary loss of accuracy is deemed acceptable to keep overhead to a minimum.
|
|
1309
|
+
|
|
1139
1310
|
state->stats = (struct stats) {
|
|
1140
1311
|
// All these values are initialized to their highest value possible since we always take the min between existing and latest sample
|
|
1141
1312
|
.cpu_sampling_time_ns_min = UINT64_MAX,
|
|
1142
1313
|
.allocation_sampling_time_ns_min = UINT64_MAX,
|
|
1143
1314
|
.gvl_sampling_time_ns_min = UINT64_MAX,
|
|
1315
|
+
// Other fields are reset to 0
|
|
1144
1316
|
};
|
|
1317
|
+
global_stats = (global_stats_t) {0};
|
|
1145
1318
|
}
|
|
1146
1319
|
|
|
1147
1320
|
static void sleep_for(uint64_t time_ns) {
|
|
@@ -1182,6 +1355,9 @@ static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
|
|
|
1182
1355
|
// Implements memory-related profiling events. This function is called by Ruby via the `rb_add_event_hook2`
|
|
1183
1356
|
// when the RUBY_INTERNAL_EVENT_NEWOBJ event is triggered.
|
|
1184
1357
|
//
|
|
1358
|
+
// This function is called from the RUBY_INTERNAL_EVENT_NEWOBJ tracepoint so it should neither allocate in the
|
|
1359
|
+
// Ruby heap nor release the GVL (https://github.com/DataDog/dd-trace-rb/pull/4240).
|
|
1360
|
+
//
|
|
1185
1361
|
// When allocation sampling is enabled, this function gets called for almost all* objects allocated by the Ruby VM.
|
|
1186
1362
|
// (*In some weird cases the VM may skip this tracepoint.)
|
|
1187
1363
|
//
|
|
@@ -1218,13 +1394,22 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1218
1394
|
return;
|
|
1219
1395
|
}
|
|
1220
1396
|
|
|
1397
|
+
VALUE current_thread = rb_thread_current();
|
|
1398
|
+
|
|
1221
1399
|
// If Ruby is in the middle of raising an exception, we don't want to try to sample. This is because if we accidentally
|
|
1222
1400
|
// trigger an exception inside the profiler code, bad things will happen (specifically, Ruby will try to kill off the
|
|
1223
1401
|
// thread even though we may try to catch the exception).
|
|
1224
1402
|
//
|
|
1225
1403
|
// Note that "in the middle of raising an exception" means the exception itself has already been allocated.
|
|
1226
1404
|
// What's getting allocated now is probably the backtrace objects (@ivoanjo or at least that's what I've observed)
|
|
1227
|
-
if (is_raised_flag_set(
|
|
1405
|
+
if (is_raised_flag_set(current_thread)) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
per_thread_context *thread_context = get_per_thread_context(current_thread);
|
|
1410
|
+
if (!thread_context) {
|
|
1411
|
+
// Context is created eagerly via on_thread_begin_event, so this should not normally be NULL.
|
|
1412
|
+
// We keep the guard since we can't allocate here (inside on_newobj_event).
|
|
1228
1413
|
return;
|
|
1229
1414
|
}
|
|
1230
1415
|
|
|
@@ -1259,7 +1444,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1259
1444
|
// Rescue against any exceptions that happen during sampling
|
|
1260
1445
|
safely_call(
|
|
1261
1446
|
rescued_sample_allocation,
|
|
1262
|
-
|
|
1447
|
+
(VALUE) thread_context,
|
|
1263
1448
|
state->self_instance,
|
|
1264
1449
|
handle_sampling_failure_rescued_sample_allocation
|
|
1265
1450
|
);
|
|
@@ -1283,7 +1468,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
|
|
|
1283
1468
|
during_sample_exit(state);
|
|
1284
1469
|
}
|
|
1285
1470
|
|
|
1286
|
-
static void
|
|
1471
|
+
static void disable_hooks(cpu_and_wall_time_worker_state *state) {
|
|
1287
1472
|
if (state->gc_tracepoint != Qnil) {
|
|
1288
1473
|
rb_tracepoint_disable(state->gc_tracepoint);
|
|
1289
1474
|
}
|
|
@@ -1311,7 +1496,8 @@ static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self) {
|
|
|
1311
1496
|
}
|
|
1312
1497
|
}
|
|
1313
1498
|
|
|
1314
|
-
static VALUE rescued_sample_allocation(
|
|
1499
|
+
static VALUE rescued_sample_allocation(VALUE arg) {
|
|
1500
|
+
per_thread_context *thread_context = (per_thread_context*) arg;
|
|
1315
1501
|
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1316
1502
|
|
|
1317
1503
|
// This should not happen in a normal situation because on_newobj_event already checked for this, but just in case...
|
|
@@ -1330,18 +1516,18 @@ static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
|
|
|
1330
1516
|
// To control bias from sampling, we clamp the maximum weight attributed to a single allocation sample. This avoids
|
|
1331
1517
|
// assigning a very large number to a sample, if for instance the dynamic sampling mechanism chose a really big interval.
|
|
1332
1518
|
unsigned int weight = allocations_since_last_sample > MAX_ALLOC_WEIGHT ? MAX_ALLOC_WEIGHT : (unsigned int) allocations_since_last_sample;
|
|
1333
|
-
bool
|
|
1519
|
+
bool needs_commit = thread_context_collector_sample_allocation(state->thread_context_collector_instance, thread_context, weight, new_object);
|
|
1334
1520
|
// ...but we still represent the skipped samples in the profile, thus the data will account for all allocations.
|
|
1335
1521
|
if (weight < allocations_since_last_sample) {
|
|
1336
1522
|
uint32_t skipped_samples = (uint32_t) uint64_min_of(allocations_since_last_sample - weight, UINT32_MAX);
|
|
1337
1523
|
thread_context_collector_sample_skipped_allocation_samples(state->thread_context_collector_instance, skipped_samples);
|
|
1338
1524
|
}
|
|
1339
1525
|
|
|
1340
|
-
if (
|
|
1526
|
+
if (needs_commit) {
|
|
1341
1527
|
#ifndef NO_POSTPONED_TRIGGER
|
|
1342
|
-
rb_postponed_job_trigger(
|
|
1528
|
+
rb_postponed_job_trigger(commit_heap_recordings_from_postponed_job_may_lose_gvl_handle);
|
|
1343
1529
|
#else
|
|
1344
|
-
|
|
1530
|
+
rb_postponed_job_register_one(0, commit_heap_recordings_from_postponed_job_may_lose_gvl, NULL);
|
|
1345
1531
|
#endif
|
|
1346
1532
|
}
|
|
1347
1533
|
|
|
@@ -1387,44 +1573,71 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
|
|
|
1387
1573
|
#ifndef NO_GVL_INSTRUMENTATION
|
|
1388
1574
|
static void on_gvl_event(rb_event_flag_t event_id, const rb_internal_thread_event_data_t *event_data, DDTRACE_UNUSED void *_unused) {
|
|
1389
1575
|
// Be very careful about touching the `state` here or doing anything at all:
|
|
1390
|
-
// This function gets called without the GVL, and potentially from
|
|
1576
|
+
// This function gets called without the GVL, and potentially from non-main Ractors!
|
|
1391
1577
|
//
|
|
1392
|
-
//
|
|
1393
|
-
//
|
|
1394
|
-
|
|
1578
|
+
// Note, even though these events can get called without the GVL, they synchronize-with enabling/disabling of
|
|
1579
|
+
// the hook that calls us using a read-write lock. Thus, disabling the hook cannot be concurrent with calling this function,
|
|
1580
|
+
// and once the disable finishes there can't be "late" calls into this function.
|
|
1581
|
+
|
|
1582
|
+
// The thread that this event is about may not be the current thread
|
|
1583
|
+
// (as documented on rb_internal_thread_add_event_hook(), and this is notably the case for READY on Ruby 4.0),
|
|
1584
|
+
// so be careful with native thread locals that are not directly tied to the thread object and the like.
|
|
1585
|
+
|
|
1586
|
+
#ifdef HAVE_RUBY_THREAD_STORAGE_API
|
|
1587
|
+
VALUE target_thread = event_data->thread;
|
|
1588
|
+
#else
|
|
1589
|
+
// On Ruby 3.2 the event does not carry the thread, but all events fire on the thread itself.
|
|
1590
|
+
// However, during early thread startup rb_thread_current() can crash because the execution context (Fiber) isn't
|
|
1591
|
+
// stored in TLS yet; ruby_native_thread_p() guards against this.
|
|
1592
|
+
if (!ruby_native_thread_p()) return;
|
|
1593
|
+
VALUE target_thread = rb_thread_current();
|
|
1594
|
+
#endif
|
|
1395
1595
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1596
|
+
per_thread_context* thread_context = get_per_thread_context(target_thread);
|
|
1597
|
+
if (!thread_context) return;
|
|
1598
|
+
// If non-NULL the thread is profiled and from the main Ractor
|
|
1599
|
+
|
|
1600
|
+
if (event_id == RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) { /* released gvl */
|
|
1601
|
+
thread_context_collector_on_gvl_released(thread_context);
|
|
1602
|
+
} else if (event_id == RUBY_INTERNAL_THREAD_EVENT_READY) { /* waiting for gvl */
|
|
1603
|
+
thread_context_collector_on_gvl_waiting(thread_context);
|
|
1398
1604
|
} else if (event_id == RUBY_INTERNAL_THREAD_EVENT_RESUMED) { /* running/runnable */
|
|
1399
|
-
//
|
|
1400
|
-
//
|
|
1605
|
+
// We must only use async-signal-safe functions here and not call arbitrary Ruby APIs and not allocate!
|
|
1606
|
+
// One might assume RUBY_INTERNAL_THREAD_EVENT_RESUMED means having the GVL and running that thread.
|
|
1607
|
+
// However, the reality is more complicated (https://bugs.ruby-lang.org/issues/22098),
|
|
1608
|
+
// it only "sort of" has the GVL but not fully, and it's called while holding the scheduler lock,
|
|
1609
|
+
// so we do as little work as possible here, and perform the sample in a postponed_job.
|
|
1610
|
+
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1611
|
+
if (state == NULL) return; // This should not happen, but just in case...
|
|
1612
|
+
|
|
1613
|
+
// on_gvl_running prepares a stack sample so we need to gate it with `during_sample_enter` to avoid a
|
|
1614
|
+
// SIGPROF signal coming in during that function and potentially causing a corrupted final state.
|
|
1401
1615
|
//
|
|
1402
|
-
//
|
|
1403
|
-
//
|
|
1404
|
-
//
|
|
1616
|
+
// TODO: Currently, the sample prepared in on_gvl_running can still be clobbered if the signal handler runs
|
|
1617
|
+
// after `during_sample_exit` but before `after_gvl_running_from_postponed_job` gets to run. We'll need to fix
|
|
1618
|
+
// that next.
|
|
1619
|
+
during_sample_enter(state);
|
|
1405
1620
|
|
|
1406
|
-
|
|
1407
|
-
target_thread
|
|
1408
|
-
|
|
1621
|
+
on_gvl_running_result result =
|
|
1622
|
+
thread_context_collector_on_gvl_running(target_thread, thread_context, state->waiting_for_gvl_threshold_ns);
|
|
1623
|
+
|
|
1624
|
+
during_sample_exit(state);
|
|
1409
1625
|
|
|
1410
|
-
|
|
1626
|
+
if (result.waiting_for_gvl_duration_ns > 0) {
|
|
1627
|
+
state->stats.vm_metrics.gvl_waiting_time_ns_total += (uint64_t) result.waiting_for_gvl_duration_ns;
|
|
1628
|
+
}
|
|
1411
1629
|
|
|
1412
|
-
if (result == ON_GVL_RUNNING_SAMPLE) {
|
|
1630
|
+
if (result.action == ON_GVL_RUNNING_SAMPLE) {
|
|
1413
1631
|
#ifndef NO_POSTPONED_TRIGGER
|
|
1414
1632
|
rb_postponed_job_trigger(after_gvl_running_from_postponed_job_handle);
|
|
1415
1633
|
#else
|
|
1416
1634
|
rb_postponed_job_register_one(0, after_gvl_running_from_postponed_job, NULL);
|
|
1417
1635
|
#endif
|
|
1418
|
-
} else if (result == ON_GVL_RUNNING_DONT_SAMPLE) {
|
|
1419
|
-
cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
|
|
1420
|
-
|
|
1421
|
-
if (state == NULL) return; // This should not happen, but just in case...
|
|
1422
|
-
|
|
1636
|
+
} else if (result.action == ON_GVL_RUNNING_DONT_SAMPLE) {
|
|
1423
1637
|
state->stats.gvl_dont_sample++;
|
|
1424
1638
|
}
|
|
1425
1639
|
} else {
|
|
1426
|
-
|
|
1427
|
-
fprintf(stderr, "[ddtrace] Unexpected value in on_gvl_event (%d)\n", event_id);
|
|
1640
|
+
rb_bug("[ddtrace] Unexpected value in on_gvl_event (%d)\n", event_id);
|
|
1428
1641
|
}
|
|
1429
1642
|
}
|
|
1430
1643
|
|
|
@@ -1496,54 +1709,54 @@ static VALUE handle_sampling_failure_thread_context_collector_sample_after_gc(VA
|
|
|
1496
1709
|
return Qnil;
|
|
1497
1710
|
}
|
|
1498
1711
|
|
|
1712
|
+
static VALUE handle_sampling_failure_thread_context_collector_heap_update(VALUE self_instance, VALUE exception) {
|
|
1713
|
+
stop(self_instance, exception, "thread_context_collector_heap_update_may_lose_gvl");
|
|
1714
|
+
return Qnil;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1499
1717
|
static VALUE handle_sampling_failure_rescued_sample_allocation(VALUE self_instance, VALUE exception) {
|
|
1500
1718
|
stop(self_instance, exception, "rescued_sample_allocation");
|
|
1501
1719
|
return Qnil;
|
|
1502
1720
|
}
|
|
1503
1721
|
|
|
1504
|
-
static VALUE
|
|
1505
|
-
stop(self_instance, exception, "
|
|
1722
|
+
static VALUE handle_sampling_failure_rescued_commit_heap_recordings(VALUE self_instance, VALUE exception) {
|
|
1723
|
+
stop(self_instance, exception, "rescued_commit_heap_recordings_may_lose_gvl");
|
|
1506
1724
|
return Qnil;
|
|
1507
1725
|
}
|
|
1508
1726
|
|
|
1509
|
-
static VALUE
|
|
1727
|
+
static VALUE rescued_commit_heap_recordings_may_lose_gvl(VALUE self_instance) {
|
|
1510
1728
|
cpu_and_wall_time_worker_state *state;
|
|
1511
1729
|
TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
|
|
1512
1730
|
|
|
1513
|
-
|
|
1731
|
+
thread_context_collector_commit_heap_recordings_may_lose_gvl(state->thread_context_collector_instance);
|
|
1514
1732
|
|
|
1515
1733
|
// Return a dummy VALUE because we're called from rb_rescue2 which requires it
|
|
1516
1734
|
return Qnil;
|
|
1517
1735
|
}
|
|
1518
1736
|
|
|
1519
|
-
// This postponed job callback is used to
|
|
1520
|
-
// During on_newobj_event,
|
|
1521
|
-
//
|
|
1522
|
-
|
|
1523
|
-
#pragma GCC diagnostic ignored "-Wunused-function" // This is only used for some Rubies, but we want to build on all to make it easier to dev
|
|
1524
|
-
static void after_allocation_from_postponed_job(DDTRACE_UNUSED void *_unused) {
|
|
1737
|
+
// This postponed job callback is used to commit heap allocation recordings.
|
|
1738
|
+
// During on_newobj_event, we can't take the weak reference the heap recorder needs to track the object, so we defer
|
|
1739
|
+
// that until after the event completes.
|
|
1740
|
+
static void commit_heap_recordings_from_postponed_job_may_lose_gvl(DDTRACE_UNUSED void *_unused) {
|
|
1525
1741
|
cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
|
|
1526
1742
|
|
|
1527
1743
|
if (state == NULL || !ddtrace_rb_ractor_main_p()) return;
|
|
1528
1744
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1745
|
+
if (state->during_sample) {
|
|
1746
|
+
delayed_error(state, "commit_heap_recordings_from_postponed_job_may_lose_gvl called during_sample");
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1533
1749
|
|
|
1534
1750
|
// NOTE: We're not updating the allocation_sampler here.
|
|
1535
1751
|
// This means work done in this function isn't accounted for as profiler overhead.
|
|
1536
1752
|
// This is acceptable as the amount of work done here is expected to be small.
|
|
1537
1753
|
safely_call(
|
|
1538
|
-
|
|
1754
|
+
rescued_commit_heap_recordings_may_lose_gvl,
|
|
1539
1755
|
state->self_instance,
|
|
1540
1756
|
state->self_instance,
|
|
1541
|
-
|
|
1757
|
+
handle_sampling_failure_rescued_commit_heap_recordings
|
|
1542
1758
|
);
|
|
1543
|
-
|
|
1544
|
-
during_sample_exit(state);
|
|
1545
1759
|
}
|
|
1546
|
-
#pragma GCC diagnostic pop
|
|
1547
1760
|
|
|
1548
1761
|
static inline void during_sample_enter(cpu_and_wall_time_worker_state* state) {
|
|
1549
1762
|
// Tell the compiler it's not allowed to reorder the `during_sample` flag with anything that happens after.
|