datadog 2.30.0 → 2.45.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 +450 -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 +368 -151
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +2 -6
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +0 -2
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +29 -16
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +5 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -170
- data/ext/datadog_profiling_native_extension/collectors_stack.h +24 -5
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +909 -552
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +25 -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 +86 -104
- 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 +393 -279
- 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 +847 -510
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +38 -14
- data/ext/datadog_profiling_native_extension/profiling.c +65 -27
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +37 -107
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -7
- data/ext/datadog_profiling_native_extension/stack_recorder.c +130 -93
- data/ext/datadog_profiling_native_extension/stack_recorder.h +12 -4
- data/ext/datadog_profiling_native_extension/time_helpers.c +2 -4
- data/ext/datadog_profiling_native_extension/time_helpers.h +25 -19
- 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 +218 -0
- data/ext/libdatadog_api/extconf.rb +40 -26
- data/ext/libdatadog_api/feature_flags.c +34 -0
- data/ext/libdatadog_api/init.c +13 -2
- data/ext/libdatadog_api/otel_thread_context.c +268 -0
- data/ext/libdatadog_api/otel_thread_context.h +5 -0
- data/ext/libdatadog_api/trace_exporter.c +1998 -0
- data/ext/libdatadog_api/trace_exporter.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +63 -13
- data/lib/datadog/ai_guard/autoload.rb +10 -0
- data/lib/datadog/ai_guard/component.rb +24 -13
- data/lib/datadog/ai_guard/configuration/ext.rb +2 -0
- data/lib/datadog/ai_guard/configuration.rb +119 -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 +54 -23
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +1 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +135 -0
- data/lib/datadog/ai_guard/evaluation/client.rb +50 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +48 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -7
- data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +8 -6
- data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +8 -59
- data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +11 -16
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +15 -2
- data/lib/datadog/ai_guard/evaluation.rb +75 -17
- data/lib/datadog/ai_guard/ext.rb +16 -0
- data/lib/datadog/ai_guard/{api_client.rb → http_client.rb} +15 -11
- data/lib/datadog/ai_guard/metrics/telemetry.rb +43 -0
- data/lib/datadog/ai_guard/redaction/replacements.rb +97 -0
- data/lib/datadog/ai_guard/redaction/result.rb +29 -0
- data/lib/datadog/ai_guard/redaction.rb +80 -0
- data/lib/datadog/ai_guard.rb +70 -43
- 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 +151 -37
- 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 +133 -105
- data/lib/datadog/core/configuration/stable_config.rb +1 -1
- data/lib/datadog/core/configuration/supported_configurations.rb +33 -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 +77 -19
- data/lib/datadog/core/remote/client.rb +18 -18
- data/lib/datadog/core/remote/component.rb +66 -34
- 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 +13 -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 +83 -20
- 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/proc_responder.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/agentless/configuration_source.rb +246 -0
- data/lib/datadog/open_feature/agentless/parser.rb +43 -0
- data/lib/datadog/open_feature/agentless/response.rb +19 -0
- data/lib/datadog/open_feature/agentless/transport.rb +103 -0
- data/lib/datadog/open_feature/component.rb +118 -13
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +90 -0
- data/lib/datadog/open_feature/configuration/source/resolution.rb +22 -0
- data/lib/datadog/open_feature/configuration/source.rb +43 -0
- data/lib/datadog/open_feature/configuration.rb +140 -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 +43 -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 +8 -8
- 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 +57 -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 +45 -3
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +10 -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 +43 -37
- data/lib/datadog/profiling/exporter.rb +43 -16
- 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 +1092 -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 +41 -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 +53 -38
- data/lib/datadog/tracing/configuration/http.rb +2 -2
- data/lib/datadog/tracing/configuration/settings.rb +58 -17
- data/lib/datadog/tracing/context.rb +25 -3
- data/lib/datadog/tracing/context_provider.rb +11 -7
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_cable/event.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +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 +59 -29
- 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 +16 -13
- 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 +15 -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 +79 -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 +99 -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 +83 -29
- 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 +380 -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 +23 -13
- data/lib/datadog/tracing/transport/traces.rb +12 -32
- 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 +109 -23
- 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
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
#include "ruby_helpers.h"
|
|
4
4
|
#include "collectors_stack.h"
|
|
5
5
|
#include "libdatadog_helpers.h"
|
|
6
|
+
#include "private_vm_api_access.h"
|
|
6
7
|
#include "time_helpers.h"
|
|
7
8
|
|
|
8
|
-
//
|
|
9
|
+
// note on calloc vs ruby_xcalloc use:
|
|
9
10
|
// * Whenever we're allocating memory after being called by the Ruby VM in a "regular" situation (e.g. initializer)
|
|
10
11
|
// we should use `ruby_xcalloc` to give the VM visibility into what we're doing + give it a chance to manage GC
|
|
11
12
|
// * BUT, when we're being called during a sample, being in the middle of an object allocation is a very special
|
|
@@ -58,7 +59,7 @@ typedef struct {
|
|
|
58
59
|
heap_frame frames[];
|
|
59
60
|
} heap_record;
|
|
60
61
|
static heap_record* heap_record_new(heap_recorder*, ddog_prof_Slice_Location);
|
|
61
|
-
static void heap_record_free(heap_recorder*, heap_record
|
|
62
|
+
static void heap_record_free(heap_recorder*, heap_record*, bool should_unintern);
|
|
62
63
|
|
|
63
64
|
#if MAX_FRAMES_LIMIT > UINT16_MAX
|
|
64
65
|
#error Frames len type not compatible with MAX_FRAMES_LIMIT
|
|
@@ -68,24 +69,24 @@ static int heap_record_cmp_st(st_data_t, st_data_t);
|
|
|
68
69
|
static st_index_t heap_record_hash_st(st_data_t);
|
|
69
70
|
static const struct st_hash_type st_hash_type_heap_record = { .compare = heap_record_cmp_st, .hash = heap_record_hash_st };
|
|
70
71
|
|
|
71
|
-
//
|
|
72
|
+
// A pending recording is used to defer adding the object to the `weak_objects` map: doing so is a Ruby method
|
|
73
|
+
// call that allocates, and neither of those is safe to do during on_newobj_event
|
|
72
74
|
typedef struct {
|
|
73
|
-
|
|
75
|
+
VALUE object_ref;
|
|
76
|
+
long record_id; // Always in Fixnum range
|
|
74
77
|
heap_record *heap_record;
|
|
75
78
|
live_object_data object_data;
|
|
76
|
-
}
|
|
77
|
-
static object_record* object_record_new(long, heap_record*, live_object_data);
|
|
78
|
-
static void object_record_free(heap_recorder*, object_record*);
|
|
79
|
-
static VALUE object_record_inspect(heap_recorder*, object_record*);
|
|
80
|
-
static object_record SKIPPED_RECORD = {0};
|
|
79
|
+
} pending_recording;
|
|
81
80
|
|
|
82
|
-
//
|
|
83
|
-
// where calling rb_obj_id during on_newobj_event is unsafe.
|
|
81
|
+
// An object record is used for storing data about currently tracked live objects
|
|
84
82
|
typedef struct {
|
|
85
|
-
|
|
83
|
+
long record_id;
|
|
86
84
|
heap_record *heap_record;
|
|
87
85
|
live_object_data object_data;
|
|
88
|
-
}
|
|
86
|
+
} object_record;
|
|
87
|
+
static object_record* object_record_new(pending_recording pending);
|
|
88
|
+
static void object_record_free(heap_recorder*, object_record*, bool should_unintern);
|
|
89
|
+
static VALUE object_record_inspect(heap_recorder*, object_record*);
|
|
89
90
|
|
|
90
91
|
#define MAX_PENDING_RECORDINGS 256
|
|
91
92
|
|
|
@@ -106,7 +107,7 @@ struct heap_recorder {
|
|
|
106
107
|
// entire stacks for us, then we wouldn't need to do it on the Ruby side.
|
|
107
108
|
st_table *heap_records;
|
|
108
109
|
|
|
109
|
-
// Map[
|
|
110
|
+
// Map[record_id: long, record: object_record*]
|
|
110
111
|
// NOTE: This table is currently only protected by the GVL since we never interact with it
|
|
111
112
|
// outside the GVL.
|
|
112
113
|
// NOTE: This table has ownership of its object_records. The keys are longs and so are
|
|
@@ -114,18 +115,17 @@ struct heap_recorder {
|
|
|
114
115
|
//
|
|
115
116
|
// TODO: @ivoanjo We've evolved to actually never need to look up on object_records (we only insert and iterate),
|
|
116
117
|
// so right now this seems to be just a really really fancy self-resizing list/set.
|
|
117
|
-
//
|
|
118
|
-
// assumption of ids never reused + always increasing always holds. (This as an alternative to checking for duplicates)
|
|
118
|
+
// Tests do use it for lookup currently though.
|
|
119
119
|
st_table *object_records;
|
|
120
120
|
|
|
121
|
-
// Map[
|
|
121
|
+
// Map[record_id: long, record: object_record*]
|
|
122
122
|
// NOTE: This is a snapshot of object_records built ahead of a iteration. Outside of an
|
|
123
123
|
// iteration context, this table will be NULL. During an iteration, there will be no
|
|
124
124
|
// mutation of the data so iteration can occur without acquiring a lock.
|
|
125
125
|
// NOTE: Contrary to object_records, this table has no ownership of its data.
|
|
126
126
|
st_table *object_records_snapshot;
|
|
127
|
-
//
|
|
128
|
-
|
|
127
|
+
// "Lock" protecting the heap recorder bookkeeping; see "note on locking" below
|
|
128
|
+
uint8_t lock;
|
|
129
129
|
// The GC gen/epoch/count in which we are updating (or last updated if not currently updating).
|
|
130
130
|
//
|
|
131
131
|
// This enables us to calculate the age of objects considered in the update by comparing it
|
|
@@ -137,16 +137,18 @@ struct heap_recorder {
|
|
|
137
137
|
// When did we do the last update of heap recorder?
|
|
138
138
|
long last_update_ns;
|
|
139
139
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
//
|
|
140
|
+
// ObjectSpace::WeakMap[record_id: Integer (Fixnum) => object]
|
|
141
|
+
// Weak references to every object we're tracking.
|
|
142
|
+
// Looking a record_id up returns the object while it's alive, and nil once it's been garbage collected, which
|
|
143
|
+
// is how we determine liveness. See `ruby_weak_map_new` for details on why this gives us a weak reference.
|
|
144
|
+
VALUE weak_objects;
|
|
145
|
+
// Source for the ids used as keys in `object_records` and `weak_objects`. Ids are never reused.
|
|
146
|
+
long next_record_id;
|
|
147
|
+
|
|
148
|
+
// Recordings that are waiting to be committed after on_newobj_event completes.
|
|
149
|
+
// We can't add the object to `weak_objects` during the newobj event, so we store the
|
|
150
|
+
// VALUE reference here and commit it via a postponed job.
|
|
146
151
|
pending_recording pending_recordings[MAX_PENDING_RECORDINGS];
|
|
147
|
-
// Temporary storage for the recording in progress, used between start and end
|
|
148
|
-
VALUE active_deferred_object;
|
|
149
|
-
live_object_data active_deferred_object_data;
|
|
150
152
|
uint16_t pending_recordings_count;
|
|
151
153
|
|
|
152
154
|
// Reusable arrays, implementing a flyweight pattern for things like iteration
|
|
@@ -184,33 +186,144 @@ struct heap_recorder {
|
|
|
184
186
|
double ewma_objects_skipped;
|
|
185
187
|
|
|
186
188
|
unsigned long deferred_recordings_skipped_buffer_full;
|
|
187
|
-
unsigned long
|
|
189
|
+
unsigned long deferred_recordings_committed;
|
|
188
190
|
} stats_lifetime;
|
|
189
191
|
};
|
|
190
192
|
|
|
193
|
+
// note on locking:
|
|
194
|
+
//
|
|
195
|
+
// The state of the heap profiler (`pending_recordings`, `object_records`, `heap_records`, `weak_objects`) gets mutated from a
|
|
196
|
+
// few different places and, unlike most of the profiler, some of those operations lose the GVL while they work.
|
|
197
|
+
// Thus, unlike most of the profiler, relying only on knowing "we get called with the GVL" is not enough to keep them
|
|
198
|
+
// from stepping on each other, hence this extra "uint8_t lock".
|
|
199
|
+
//
|
|
200
|
+
// Yet, because we only ever touch while holding the GVL, and never lose the GVL between checking it and setting it, a
|
|
201
|
+
// plain field is enough -- no atomics needed. (Hence the "lock" and not a full actual lock)
|
|
202
|
+
//
|
|
203
|
+
// Operations that can be skipped use `heap_recorder_try_lock` and walk away when it's taken (which is almost all of them).
|
|
204
|
+
// The one operation that can't be skipped -- the full update that runs before serialization -- uses
|
|
205
|
+
// `heap_recorder_lock`, which waits.
|
|
206
|
+
//
|
|
207
|
+
// `heap_recorder_lock` is expected to be bounded because once `LOCK_WANTED` gets set, no `try_lock` will succeed, so
|
|
208
|
+
// the `heap_recorder_lock` will only need to wait for the previous user of the lock to finish it's work + Ruby to
|
|
209
|
+
// switch back to is thread.
|
|
210
|
+
#define HEAP_RECORDER_LOCK_HELD 0x1
|
|
211
|
+
#define HEAP_RECORDER_LOCK_WANTED 0x2
|
|
212
|
+
|
|
213
|
+
// Is someone in the middle of a locked operation? (Which, because they may lose the GVL, may be true even though we're
|
|
214
|
+
// the ones currently holding the GVL.)
|
|
215
|
+
static inline bool heap_recorder_is_locked(heap_recorder *heap_recorder) {
|
|
216
|
+
return (heap_recorder->lock & HEAP_RECORDER_LOCK_HELD) != 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Takes the lock, unless it's held or someone is waiting for it. Returns whether it was taken.
|
|
220
|
+
__attribute__((warn_unused_result))
|
|
221
|
+
static inline bool heap_recorder_try_lock(heap_recorder *heap_recorder) {
|
|
222
|
+
if (heap_recorder->lock != 0) return false;
|
|
223
|
+
|
|
224
|
+
heap_recorder->lock = HEAP_RECORDER_LOCK_HELD;
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Takes the lock, waiting for the current holder to finish if needed. See "note on locking" above for why this wait is
|
|
229
|
+
// expected to be bounded.
|
|
230
|
+
//
|
|
231
|
+
// WARN: Do not call this while already holding the lock -- it would wait forever.
|
|
232
|
+
static void heap_recorder_lock(heap_recorder *heap_recorder) {
|
|
233
|
+
while (heap_recorder_is_locked(heap_recorder)) {
|
|
234
|
+
heap_recorder->lock |= HEAP_RECORDER_LOCK_WANTED;
|
|
235
|
+
rb_thread_schedule();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Note that we go from observing the lock as free to taking it without ever losing the GVL, and thus without giving
|
|
239
|
+
// anyone else a chance to take it from under us
|
|
240
|
+
heap_recorder->lock = HEAP_RECORDER_LOCK_HELD;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
static inline void heap_recorder_unlock(heap_recorder *heap_recorder) {
|
|
244
|
+
// Deliberately preserves `HEAP_RECORDER_LOCK_WANTED` (rather than just zero-ing the lock)
|
|
245
|
+
heap_recorder->lock &= ~HEAP_RECORDER_LOCK_HELD;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Same as the above, in the shape `rb_ensure` wants
|
|
249
|
+
static VALUE heap_recorder_unlock_ensure(VALUE heap_recorder_as_value) {
|
|
250
|
+
heap_recorder_unlock((heap_recorder *) heap_recorder_as_value);
|
|
251
|
+
return Qnil;
|
|
252
|
+
}
|
|
253
|
+
|
|
191
254
|
typedef struct {
|
|
192
255
|
heap_recorder *heap_recorder;
|
|
193
|
-
|
|
194
|
-
}
|
|
256
|
+
bool full_update;
|
|
257
|
+
} heap_recorder_update_locked_args;
|
|
195
258
|
|
|
196
259
|
static heap_record* get_or_create_heap_record(heap_recorder*, ddog_prof_Slice_Location);
|
|
197
260
|
static void cleanup_heap_record_if_unused(heap_recorder*, heap_record*);
|
|
198
261
|
static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record);
|
|
199
|
-
static int
|
|
200
|
-
static int
|
|
262
|
+
static int st_heap_record_entry_free_no_unintern(st_data_t, st_data_t, st_data_t);
|
|
263
|
+
static int st_object_record_entry_free_no_unintern(st_data_t, st_data_t, st_data_t);
|
|
201
264
|
static int st_object_record_update(st_data_t, st_data_t, st_data_t);
|
|
202
265
|
static int st_object_records_iterate(st_data_t, st_data_t, st_data_t);
|
|
203
266
|
static int st_object_records_debug(st_data_t key, st_data_t value, st_data_t extra);
|
|
204
|
-
static int update_object_record_entry(st_data_t*, st_data_t*, st_data_t, int);
|
|
205
267
|
static void inc_tracked_objects_or_fail(heap_record *heap_record);
|
|
206
|
-
static void commit_recording(heap_recorder *,
|
|
207
|
-
static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args);
|
|
268
|
+
static void commit_recording(heap_recorder *, pending_recording);
|
|
208
269
|
static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update);
|
|
270
|
+
static VALUE heap_recorder_update_locked(VALUE heap_recorder_update_locked_args_as_value);
|
|
271
|
+
static VALUE heap_recorder_commit_recordings_may_lose_gvl_locked(VALUE heap_recorder_as_value);
|
|
209
272
|
static inline double ewma_stat(double previous, double current);
|
|
210
273
|
static void unintern_or_raise(heap_recorder *, ddog_prof_ManagedStringId);
|
|
211
274
|
static void unintern_all_or_raise(heap_recorder *recorder, ddog_prof_Slice_ManagedStringId ids);
|
|
212
275
|
static VALUE get_ruby_string_or_raise(heap_recorder*, ddog_prof_ManagedStringId);
|
|
213
|
-
|
|
276
|
+
|
|
277
|
+
// The following global variables are initialized at startup to save expensive lookups later.
|
|
278
|
+
// They are not expected to be mutated outside of init.
|
|
279
|
+
static VALUE class_weak_map = Qnil;
|
|
280
|
+
static ID aref_id = Qnil;
|
|
281
|
+
static ID aset_id = Qnil;
|
|
282
|
+
|
|
283
|
+
void collectors_heap_recorder_init(void) {
|
|
284
|
+
rb_global_variable(&class_weak_map);
|
|
285
|
+
|
|
286
|
+
VALUE module_object_space = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
|
|
287
|
+
class_weak_map = rb_const_get(module_object_space, rb_intern("WeakMap"));
|
|
288
|
+
aref_id = rb_intern("[]");
|
|
289
|
+
aset_id = rb_intern("[]=");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Native wrapper to create a new `ObjectSpace::WeakMap`.
|
|
293
|
+
//
|
|
294
|
+
// Because an `ObjectSpace::WeakMap` entry is dropped as soon as *either* its key or its value is garbage
|
|
295
|
+
// collected, pairing a key that can never be collected (such as a fixnum) with the object of interest as the
|
|
296
|
+
// value gives us a weak reference: reading the key back returns the object while it's alive, and nothing once
|
|
297
|
+
// it's been collected.
|
|
298
|
+
static VALUE ruby_weak_map_new(void) {
|
|
299
|
+
return rb_class_new_instance(0, NULL, class_weak_map);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Native wrapper to get an object from an `ObjectSpace::WeakMap`.
|
|
303
|
+
// Returns the object on success and nil if the entry is gone, meaning
|
|
304
|
+
// the object has been garbage collected.
|
|
305
|
+
// We never store nil as a value, see ruby_weak_map_set_may_lose_gvl_and_allocate_objects(), so nil unambiguously
|
|
306
|
+
// means "the value was garbage collected".
|
|
307
|
+
//
|
|
308
|
+
// Note: GVL can be released and other threads may get to run before this method returns
|
|
309
|
+
static VALUE ruby_weak_map_get_may_lose_gvl(VALUE weak_map, VALUE key) {
|
|
310
|
+
return rb_funcall(weak_map, aref_id, 1, key);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Native wrapper to add an entry to an `ObjectSpace::WeakMap`.
|
|
314
|
+
// Raises RuntimeError if passed nil as a value.
|
|
315
|
+
//
|
|
316
|
+
// Note: GVL can be released and other threads may get to run before this method returns.
|
|
317
|
+
//
|
|
318
|
+
// On Ruby < 3.3 this allocates Ruby objects (because underneath the weak map registers
|
|
319
|
+
// finalizers for the objects, which requires allocations). Later Rubies improved WeakMap to not need this.
|
|
320
|
+
// This we need to be careful not to recurse on the profiler (e.g. NEWOBJ tracepoint).
|
|
321
|
+
static void ruby_weak_map_set_may_lose_gvl_and_allocate_objects(VALUE weak_map, VALUE key, VALUE value) {
|
|
322
|
+
if (value == Qnil) {
|
|
323
|
+
raise_error(rb_eRuntimeError, "Can't use nil as the value in the WeakMap, otherwise #[] can't differentiate alive vs nil value");
|
|
324
|
+
}
|
|
325
|
+
rb_funcall(weak_map, aset_id, 2, key, value);
|
|
326
|
+
}
|
|
214
327
|
|
|
215
328
|
// ==========================
|
|
216
329
|
// Heap Recorder External API
|
|
@@ -230,11 +343,12 @@ heap_recorder* heap_recorder_new(ddog_prof_ManagedStringStorage string_storage)
|
|
|
230
343
|
recorder->reusable_locations = ruby_xcalloc(REUSABLE_LOCATIONS_SIZE, sizeof(ddog_prof_Location));
|
|
231
344
|
recorder->reusable_ids = ruby_xcalloc(REUSABLE_FRAME_DETAILS_SIZE, sizeof(ddog_prof_ManagedStringId));
|
|
232
345
|
recorder->reusable_char_slices = ruby_xcalloc(REUSABLE_FRAME_DETAILS_SIZE, sizeof(ddog_CharSlice));
|
|
233
|
-
recorder->active_recording = NULL;
|
|
234
346
|
recorder->size_enabled = true;
|
|
235
347
|
recorder->sample_rate = 1; // By default do no sampling on top of what allocation profiling already does
|
|
236
348
|
recorder->string_storage = string_storage;
|
|
237
|
-
recorder
|
|
349
|
+
// Note: This allocates, and thus can trigger a GC. That's fine: our caller only publishes the heap recorder on the
|
|
350
|
+
// stack recorder state after we return, so `heap_recorder_mark` will not observe a half-initialized recorder.
|
|
351
|
+
recorder->weak_objects = ruby_weak_map_new();
|
|
238
352
|
|
|
239
353
|
return recorder;
|
|
240
354
|
}
|
|
@@ -250,19 +364,21 @@ void heap_recorder_free(heap_recorder *heap_recorder) {
|
|
|
250
364
|
heap_recorder_finish_iteration(heap_recorder);
|
|
251
365
|
}
|
|
252
366
|
|
|
367
|
+
// NOTE: We don't unintern the strings referenced by the records we're about to free, thus we use
|
|
368
|
+
// `..._no_unintern` and `should_unintern: false`. This is intentional: `heap_recorder_free` is only ever called as part of
|
|
369
|
+
// tearing down the entire stack recorder, and the caller drops the whole managed string storage right after
|
|
370
|
+
// (see `stack_recorder_typed_data_free`), so there's no need to spend effort updating the managed string table.
|
|
371
|
+
// Crucially, this also keeps us from crashing: this code runs from the stack recorder's GC free callback, and
|
|
372
|
+
// because uninterning can fail, we can't raise exceptions in the middle of a dfree.
|
|
373
|
+
|
|
253
374
|
// Clean-up all object records
|
|
254
|
-
st_foreach(heap_recorder->object_records,
|
|
375
|
+
st_foreach(heap_recorder->object_records, st_object_record_entry_free_no_unintern, (st_data_t) heap_recorder);
|
|
255
376
|
st_free_table(heap_recorder->object_records);
|
|
256
377
|
|
|
257
378
|
// Clean-up all heap records (this includes those only referred to by queued_samples)
|
|
258
|
-
st_foreach(heap_recorder->heap_records,
|
|
379
|
+
st_foreach(heap_recorder->heap_records, st_heap_record_entry_free_no_unintern, (st_data_t) heap_recorder);
|
|
259
380
|
st_free_table(heap_recorder->heap_records);
|
|
260
381
|
|
|
261
|
-
if (heap_recorder->active_recording != NULL && heap_recorder->active_recording != &SKIPPED_RECORD) {
|
|
262
|
-
// If there's a partial object record, clean it up as well
|
|
263
|
-
object_record_free(heap_recorder, heap_recorder->active_recording);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
382
|
ruby_xfree(heap_recorder->reusable_locations);
|
|
267
383
|
ruby_xfree(heap_recorder->reusable_ids);
|
|
268
384
|
ruby_xfree(heap_recorder->reusable_char_slices);
|
|
@@ -306,7 +422,7 @@ void heap_recorder_after_fork(heap_recorder *heap_recorder) {
|
|
|
306
422
|
// simply be noticed on next heap_recorder_prepare_iteration.
|
|
307
423
|
//
|
|
308
424
|
// There is one small caveat though: fork only preserves one thread and in a Ruby app, that
|
|
309
|
-
// will be the thread holding
|
|
425
|
+
// will be the thread holding the GVL. Since we support iteration on the heap recorder
|
|
310
426
|
// outside of the GVL, any state specific to that interaction may be inconsistent after fork
|
|
311
427
|
// (e.g. an acquired lock for thread safety). Iteration operates on object_records_snapshot
|
|
312
428
|
// though and that one will be updated on next heap_recorder_prepare_iteration so we really
|
|
@@ -315,150 +431,95 @@ void heap_recorder_after_fork(heap_recorder *heap_recorder) {
|
|
|
315
431
|
heap_recorder_finish_iteration(heap_recorder);
|
|
316
432
|
}
|
|
317
433
|
|
|
434
|
+
// This could also be left over if fork happens in the middle of a locked operation
|
|
435
|
+
heap_recorder->lock = 0;
|
|
436
|
+
|
|
318
437
|
// Clear lifetime stats since this is essentially a new heap recorder
|
|
319
438
|
heap_recorder->stats_lifetime = (struct stats_lifetime) {0};
|
|
320
439
|
}
|
|
321
440
|
|
|
322
|
-
|
|
441
|
+
// This method gets called from inside the RUBY_INTERNAL_EVENT_NEWOBJ tracepoint so it should neither allocate in the
|
|
442
|
+
// Ruby heap nor release the GVL (https://github.com/DataDog/dd-trace-rb/pull/4240).
|
|
443
|
+
//
|
|
444
|
+
// See the header for details on the arguments and on `needs_commit`.
|
|
445
|
+
void heap_recorder_record_allocation(
|
|
446
|
+
heap_recorder *heap_recorder,
|
|
447
|
+
VALUE new_object,
|
|
448
|
+
unsigned int weight,
|
|
449
|
+
ddog_CharSlice alloc_class,
|
|
450
|
+
ddog_prof_Slice_Location locations,
|
|
451
|
+
bool *needs_commit
|
|
452
|
+
) {
|
|
323
453
|
if (heap_recorder == NULL) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (heap_recorder->active_recording != NULL) {
|
|
328
|
-
raise_error(rb_eRuntimeError, "Detected consecutive heap allocation recording starts without end.");
|
|
454
|
+
*needs_commit = false;
|
|
455
|
+
return;
|
|
329
456
|
}
|
|
330
457
|
|
|
331
|
-
if
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
458
|
+
// We always report `needs_commit` when there's anything pending, even if it's from a previous allocation.
|
|
459
|
+
//
|
|
460
|
+
// This can mean we "spam" a bit the postponed jobs mechanism (e.g. perhaps our postponed job hasn't run
|
|
461
|
+
// because there's a native extension doing Ruby object allocations in a row without giving Ruby the chance to
|
|
462
|
+
// run interrupts.
|
|
463
|
+
// That shouldn't be a problem because the allocation profiler has the dynamic sampling rate mechanism +
|
|
464
|
+
// triggering postponed jobs is cheap on current Rubies.
|
|
465
|
+
// (Note that asking for the same job multiple times de-duplicates -- Ruby will only run it once when it gets the chance)
|
|
466
|
+
*needs_commit = heap_recorder->pending_recordings_count > 0;
|
|
467
|
+
|
|
468
|
+
if (++heap_recorder->num_recordings_skipped < heap_recorder->sample_rate) return;
|
|
469
|
+
|
|
470
|
+
if (heap_recorder_is_locked(heap_recorder)) {
|
|
471
|
+
// If we got unlucky and an allocation showed up in the middle of a locked operation (because it triggered
|
|
472
|
+
// an allocation directly OR because that operation lost the GVL), let's skip this sample as well.
|
|
473
|
+
// (Note we don't take the lock ourselves: the current function never loses the GVL, and is thus already atomic.)
|
|
474
|
+
return;
|
|
345
475
|
}
|
|
346
476
|
|
|
347
|
-
|
|
477
|
+
// Do not sample internal objects in the heap profiler because they are added to a ObjectSpace::WeakMap, which would not be safe.
|
|
478
|
+
// This means we ignore internal VM objects samples for the heap profiler,
|
|
479
|
+
// which is a trade-off discussed in https://github.com/DataDog/dd-trace-rb/pull/6176#discussion_r3819776251
|
|
480
|
+
//
|
|
481
|
+
// Note this is checked after the sample rate above, as the sample rate is in number of allocation profiler samples,
|
|
482
|
+
// not in number of non-internal samples. Like the skips above, num_recordings_skipped is not reset here, so the
|
|
483
|
+
// next allocation sample still gets a chance to be tracked.
|
|
484
|
+
if (ddtrace_is_internal_object_p(new_object)) return;
|
|
348
485
|
|
|
349
|
-
|
|
350
|
-
// Skip if we've hit the pending recordings limit or if there's already a deferred object being recorded
|
|
486
|
+
// Skip if we've hit the pending recordings limit
|
|
351
487
|
if (heap_recorder->pending_recordings_count >= MAX_PENDING_RECORDINGS) {
|
|
352
488
|
heap_recorder->stats_lifetime.deferred_recordings_skipped_buffer_full++;
|
|
353
|
-
|
|
354
|
-
return true; // If the buffer is full, we keep asking for a callback (see `needs_after_allocation` below)
|
|
355
|
-
} else {
|
|
356
|
-
// The intuition here is: We start by asking for an `after_allocation` callback when the buffer is about to go
|
|
357
|
-
// from empty -> non-empty, because this is going to be mapped onto a postponed job, so after it gets queued once
|
|
358
|
-
// it doesn't seem worth it to keep spamming requests.
|
|
359
|
-
//
|
|
360
|
-
// Yet, if for some reason the postponed job doesn't flush the pending list (or if e.g. it ran with `during_sample == true` and thus
|
|
361
|
-
// was skipped) we need to have some mechanism to recover -- and so if the buffer starts accumulating too much we
|
|
362
|
-
// start always requesting the callback to happen so that we eventually flush the buffer.
|
|
363
|
-
needs_after_allocation =
|
|
364
|
-
heap_recorder->pending_recordings_count == 0 || heap_recorder->pending_recordings_count >= (MAX_PENDING_RECORDINGS / 2);
|
|
489
|
+
return; // `needs_commit` is already true: a full buffer definitely has something to commit
|
|
365
490
|
}
|
|
366
|
-
#endif
|
|
367
491
|
|
|
368
492
|
heap_recorder->num_recordings_skipped = 0;
|
|
369
493
|
|
|
370
|
-
|
|
494
|
+
// Note: Everything that can raise happens before we add the recording to `pending_recordings` below, so that a
|
|
495
|
+
// failure never leaves a half-built entry behind
|
|
496
|
+
live_object_data object_data = {
|
|
371
497
|
.weight = weight * heap_recorder->sample_rate,
|
|
372
498
|
.class = intern_or_raise(heap_recorder->string_storage, alloc_class),
|
|
373
499
|
.alloc_gen = rb_gc_count(),
|
|
374
500
|
};
|
|
375
501
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
#else
|
|
383
|
-
heap_recorder->active_recording = object_record_new(obj_id_or_fail(new_obj), NULL, object_data);
|
|
384
|
-
#endif
|
|
385
|
-
|
|
386
|
-
return needs_after_allocation;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// end_heap_allocation_recording_with_rb_protect gets called while the stack_recorder is holding one of the profile
|
|
390
|
-
// locks. To enable us to correctly unlock the profile on exception, we wrap the call to end_heap_allocation_recording
|
|
391
|
-
// with an rb_protect.
|
|
392
|
-
__attribute__((warn_unused_result))
|
|
393
|
-
int end_heap_allocation_recording_with_rb_protect(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
|
|
394
|
-
if (heap_recorder == NULL) {
|
|
395
|
-
return 0;
|
|
396
|
-
}
|
|
397
|
-
if (heap_recorder->active_recording == &SKIPPED_RECORD) {
|
|
398
|
-
// Short circuit, in this case there's nothing to be done
|
|
399
|
-
heap_recorder->active_recording = NULL;
|
|
400
|
-
return 0;
|
|
502
|
+
long record_id = ++heap_recorder->next_record_id;
|
|
503
|
+
if (record_id > RUBY_FIXNUM_MAX) {
|
|
504
|
+
// We rely on record_id always fitting in a FIXNUM to avoid extra overhead and
|
|
505
|
+
// allocation here. If we exhaust the record_id, we stop profiling.
|
|
506
|
+
// We don't expect this to happen in practice, as we don't heap sample every object, and RUBY_FIXNUM_MAX is (2**62 - 1)
|
|
507
|
+
raise_error(rb_eRuntimeError, "Heap profiling: Exhausted usable record_ids");
|
|
401
508
|
}
|
|
402
509
|
|
|
403
|
-
int exception_state;
|
|
404
|
-
end_heap_allocation_args args = {
|
|
405
|
-
.heap_recorder = heap_recorder,
|
|
406
|
-
.locations = locations,
|
|
407
|
-
};
|
|
408
|
-
rb_protect(end_heap_allocation_recording, (VALUE) &args, &exception_state);
|
|
409
|
-
return exception_state;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
static VALUE end_heap_allocation_recording(VALUE protect_args) {
|
|
413
|
-
end_heap_allocation_args *args = (end_heap_allocation_args *) protect_args;
|
|
414
|
-
|
|
415
|
-
heap_recorder *heap_recorder = args->heap_recorder;
|
|
416
|
-
ddog_prof_Slice_Location locations = args->locations;
|
|
417
|
-
|
|
418
|
-
#ifdef USE_DEFERRED_HEAP_ALLOCATION_RECORDING
|
|
419
|
-
if (heap_recorder->active_deferred_object == Qnil) {
|
|
420
|
-
// Recording ended without having been started?
|
|
421
|
-
raise_error(rb_eRuntimeError, "Ended a heap recording that was not started");
|
|
422
|
-
}
|
|
423
|
-
#else
|
|
424
|
-
object_record *active_recording = heap_recorder->active_recording;
|
|
425
|
-
|
|
426
|
-
if (active_recording == NULL) {
|
|
427
|
-
// Recording ended without having been started?
|
|
428
|
-
raise_error(rb_eRuntimeError, "Ended a heap recording that was not started");
|
|
429
|
-
}
|
|
430
|
-
// From now on, mark the global active recording as invalid so we can short-circuit at any point
|
|
431
|
-
// and not end up with a still active recording. the local active_recording still holds the
|
|
432
|
-
// data required for committing though.
|
|
433
|
-
heap_recorder->active_recording = NULL;
|
|
434
|
-
|
|
435
|
-
if (active_recording == &SKIPPED_RECORD) {
|
|
436
|
-
raise_error(
|
|
437
|
-
rb_eRuntimeError,
|
|
438
|
-
"BUG: end_heap_allocation_recording should never observe SKIPPED_RECORDING because " \
|
|
439
|
-
"end_heap_allocation_recording_with_rb_protect is supposed to test for it directly"
|
|
440
|
-
);
|
|
441
|
-
}
|
|
442
|
-
#endif
|
|
443
|
-
|
|
444
510
|
heap_record *heap_record = get_or_create_heap_record(heap_recorder, locations);
|
|
445
511
|
inc_tracked_objects_or_fail(heap_record);
|
|
446
512
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
heap_recorder->active_deferred_object_data = (live_object_data) {0};
|
|
456
|
-
#else
|
|
457
|
-
// And then commit the new allocation
|
|
458
|
-
commit_recording(heap_recorder, heap_record, active_recording);
|
|
459
|
-
#endif
|
|
513
|
+
// We can't add the object to `weak_objects` from inside the NEWOBJ tracepoint, so the recording stays pending until
|
|
514
|
+
// `heap_recorder_commit_recordings_may_lose_gvl` gets to it
|
|
515
|
+
heap_recorder->pending_recordings[heap_recorder->pending_recordings_count++] = (pending_recording) {
|
|
516
|
+
.object_ref = new_object,
|
|
517
|
+
.record_id = record_id,
|
|
518
|
+
.heap_record = heap_record,
|
|
519
|
+
.object_data = object_data,
|
|
520
|
+
};
|
|
460
521
|
|
|
461
|
-
|
|
522
|
+
*needs_commit = true; // We just added a recording
|
|
462
523
|
}
|
|
463
524
|
|
|
464
525
|
void heap_recorder_update_young_objects(heap_recorder *heap_recorder) {
|
|
@@ -469,46 +530,68 @@ void heap_recorder_update_young_objects(heap_recorder *heap_recorder) {
|
|
|
469
530
|
heap_recorder_update(heap_recorder, /* full_update: */ false);
|
|
470
531
|
}
|
|
471
532
|
|
|
472
|
-
void
|
|
533
|
+
void heap_recorder_commit_recordings_may_lose_gvl(heap_recorder *heap_recorder) {
|
|
473
534
|
if (heap_recorder == NULL) {
|
|
474
535
|
return; // Nothing to do
|
|
475
536
|
}
|
|
476
537
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
return;
|
|
538
|
+
if (!heap_recorder_try_lock(heap_recorder)) {
|
|
539
|
+
// Something else is busy; `heap_recorder_record_allocation` will ask for us to be called again later
|
|
540
|
+
return;
|
|
480
541
|
}
|
|
481
542
|
|
|
482
|
-
|
|
543
|
+
rb_ensure(
|
|
544
|
+
heap_recorder_commit_recordings_may_lose_gvl_locked,
|
|
545
|
+
(VALUE) heap_recorder,
|
|
546
|
+
heap_recorder_unlock_ensure,
|
|
547
|
+
(VALUE) heap_recorder
|
|
548
|
+
);
|
|
549
|
+
}
|
|
483
550
|
|
|
484
|
-
|
|
485
|
-
|
|
551
|
+
static VALUE heap_recorder_commit_recordings_may_lose_gvl_locked(VALUE heap_recorder_as_value) {
|
|
552
|
+
heap_recorder *heap_recorder = (struct heap_recorder *) heap_recorder_as_value;
|
|
486
553
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
554
|
+
// Note: We consume the buffer back-to-front, and only drop each entry once it's fully committed. That makes the
|
|
555
|
+
// "can lose the GVL" bit below safe to retry: if anything raises, or another thread unwinds us, the entry stays
|
|
556
|
+
// pending and a later commit picks it up -- and setting the same entry on the weak map again is harmless. It also
|
|
557
|
+
// means the entry we're working on stays marked (see `heap_recorder_mark`) across any GC that happens while we don't
|
|
558
|
+
// have the GVL.
|
|
559
|
+
//
|
|
560
|
+
// Note as well that `ruby_weak_map_set_may_lose_gvl_and_allocate_objects` below can lose the GVL (and, on older
|
|
561
|
+
// Rubies, allocate). This function gets called while holding the heap recorder lock so that no other heap recorder
|
|
562
|
+
// operation can concurrently execute with us in that window (including recording more allocations, which on older Rubies
|
|
563
|
+
// would otherwise add entries to the very buffer we're draining).
|
|
564
|
+
while (heap_recorder->pending_recordings_count > 0) {
|
|
565
|
+
pending_recording pending = heap_recorder->pending_recordings[heap_recorder->pending_recordings_count - 1];
|
|
566
|
+
|
|
567
|
+
ruby_weak_map_set_may_lose_gvl_and_allocate_objects(heap_recorder->weak_objects, LONG2FIX(pending.record_id), pending.object_ref);
|
|
490
568
|
|
|
491
|
-
//
|
|
492
|
-
object_record *record = object_record_new(obj_id, pending->heap_record, pending->object_data);
|
|
569
|
+
// After here, we can no longer lose the GVL until we loop around again, so these steps are "atomic"
|
|
493
570
|
|
|
494
|
-
commit_recording(heap_recorder, pending
|
|
571
|
+
commit_recording(heap_recorder, pending);
|
|
572
|
+
heap_recorder->pending_recordings_count--;
|
|
573
|
+
heap_recorder->stats_lifetime.deferred_recordings_committed++;
|
|
495
574
|
}
|
|
496
575
|
|
|
497
|
-
|
|
576
|
+
return Qnil;
|
|
498
577
|
}
|
|
499
578
|
|
|
500
|
-
// Mark
|
|
501
|
-
//
|
|
502
|
-
|
|
579
|
+
// Mark the Ruby objects the heap recorder holds on to.
|
|
580
|
+
//
|
|
581
|
+
// Note that the objects we track are deliberately **not** marked here: `weak_objects` holds only weak references
|
|
582
|
+
// to them, which is exactly what lets us detect that they've been garbage collected.
|
|
583
|
+
void heap_recorder_mark(heap_recorder *heap_recorder) {
|
|
503
584
|
if (heap_recorder == NULL) {
|
|
504
585
|
return;
|
|
505
586
|
}
|
|
506
587
|
|
|
588
|
+
// Mark pending recordings while they're waiting to be committed, otherwise it won't be safe to read them later.
|
|
589
|
+
// We would not mind if they are GC'd, but we would need to know that reliably and we can't.
|
|
507
590
|
for (uint i = 0; i < heap_recorder->pending_recordings_count; i++) {
|
|
508
591
|
rb_gc_mark(heap_recorder->pending_recordings[i].object_ref);
|
|
509
592
|
}
|
|
510
593
|
|
|
511
|
-
rb_gc_mark(heap_recorder->
|
|
594
|
+
rb_gc_mark(heap_recorder->weak_objects);
|
|
512
595
|
}
|
|
513
596
|
|
|
514
597
|
// NOTE: This function needs and assumes it gets called with the GVL being held.
|
|
@@ -516,36 +599,35 @@ void heap_recorder_mark_pending_recordings(heap_recorder *heap_recorder) {
|
|
|
516
599
|
// so we can't assume a single update happens in a single "atomic" step -- other threads may get some running time
|
|
517
600
|
// in the meanwhile.
|
|
518
601
|
static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update) {
|
|
519
|
-
if (
|
|
520
|
-
if
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
// and the scheduler thread decided now was a great time to serialize the profile.
|
|
527
|
-
//
|
|
528
|
-
// So, let's yield the time on the current thread until Ruby goes back to the other thread doing the update and
|
|
529
|
-
// it finishes cleanly.
|
|
530
|
-
while (heap_recorder->updating) { rb_thread_schedule(); }
|
|
531
|
-
} else {
|
|
532
|
-
// Non-full updates are optional, so let's walk away
|
|
533
|
-
heap_recorder->stats_lifetime.updates_skipped_concurrent++;
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
602
|
+
if (full_update) {
|
|
603
|
+
// A full update runs as part of serialization and can't be skipped, so we wait for our turn if needed
|
|
604
|
+
heap_recorder_lock(heap_recorder);
|
|
605
|
+
} else if (!heap_recorder_try_lock(heap_recorder)) {
|
|
606
|
+
// Non-full updates are optional, so let's walk away
|
|
607
|
+
heap_recorder->stats_lifetime.updates_skipped_concurrent++;
|
|
608
|
+
return;
|
|
536
609
|
}
|
|
537
610
|
|
|
611
|
+
heap_recorder_update_locked_args args = {.heap_recorder = heap_recorder, .full_update = full_update};
|
|
612
|
+
rb_ensure(heap_recorder_update_locked, (VALUE) &args, heap_recorder_unlock_ensure, (VALUE) heap_recorder);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
static VALUE heap_recorder_update_locked(VALUE heap_recorder_update_locked_args_as_value) {
|
|
616
|
+
heap_recorder_update_locked_args *args = (heap_recorder_update_locked_args *) heap_recorder_update_locked_args_as_value;
|
|
617
|
+
heap_recorder *heap_recorder = args->heap_recorder;
|
|
618
|
+
bool full_update = args->full_update;
|
|
619
|
+
|
|
538
620
|
if (heap_recorder->object_records_snapshot != NULL) {
|
|
539
621
|
// While serialization is happening, it runs without the GVL and uses the object_records_snapshot.
|
|
540
622
|
// Although we iterate on a snapshot of object_records, these records point to other data that has not been
|
|
541
623
|
// snapshotted for efficiency reasons (e.g. heap_records). Since updating may invalidate
|
|
542
624
|
// some of that non-snapshotted data, let's refrain from doing updates during iteration. This also enforces the
|
|
543
625
|
// semantic that iteration will operate as a point-in-time snapshot.
|
|
544
|
-
return;
|
|
626
|
+
return Qnil;
|
|
545
627
|
}
|
|
546
628
|
|
|
547
629
|
size_t current_gc_gen = rb_gc_count();
|
|
548
|
-
long now_ns = monotonic_wall_time_now_ns(
|
|
630
|
+
long now_ns = monotonic_wall_time_now_ns();
|
|
549
631
|
|
|
550
632
|
if (!full_update) {
|
|
551
633
|
if (current_gc_gen == heap_recorder->update_gen) {
|
|
@@ -556,17 +638,16 @@ static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update)
|
|
|
556
638
|
// object records to do an update, let's wait until all steps for a particular GC generation
|
|
557
639
|
// have finished to do so. We may revisit this once we have a better liveness checking mechanism.
|
|
558
640
|
heap_recorder->stats_lifetime.updates_skipped_gcgen++;
|
|
559
|
-
return;
|
|
641
|
+
return Qnil;
|
|
560
642
|
}
|
|
561
643
|
|
|
562
|
-
if (
|
|
644
|
+
if ((now_ns - heap_recorder->last_update_ns) < MIN_TIME_BETWEEN_HEAP_RECORDER_UPDATES_NS) {
|
|
563
645
|
// We did an update not too long ago. Let's skip this one to avoid over-taxing the system.
|
|
564
646
|
heap_recorder->stats_lifetime.updates_skipped_time++;
|
|
565
|
-
return;
|
|
647
|
+
return Qnil;
|
|
566
648
|
}
|
|
567
649
|
}
|
|
568
650
|
|
|
569
|
-
heap_recorder->updating = true;
|
|
570
651
|
// Reset last update stats, we'll be building them from scratch during the st_foreach call below
|
|
571
652
|
heap_recorder->stats_last_update = (struct stats_last_update) {0};
|
|
572
653
|
|
|
@@ -589,7 +670,7 @@ static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update)
|
|
|
589
670
|
heap_recorder->stats_lifetime.ewma_objects_skipped = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_skipped, heap_recorder->stats_last_update.objects_skipped);
|
|
590
671
|
}
|
|
591
672
|
|
|
592
|
-
|
|
673
|
+
return Qnil;
|
|
593
674
|
}
|
|
594
675
|
|
|
595
676
|
void heap_recorder_prepare_iteration(heap_recorder *heap_recorder) {
|
|
@@ -683,7 +764,7 @@ VALUE heap_recorder_state_snapshot(heap_recorder *heap_recorder) {
|
|
|
683
764
|
ID2SYM(rb_intern("lifetime_ewma_objects_skipped")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_skipped),
|
|
684
765
|
|
|
685
766
|
ID2SYM(rb_intern("lifetime_deferred_recordings_skipped_buffer_full")), /* => */ ULONG2NUM(heap_recorder->stats_lifetime.deferred_recordings_skipped_buffer_full),
|
|
686
|
-
ID2SYM(rb_intern("
|
|
767
|
+
ID2SYM(rb_intern("lifetime_deferred_recordings_committed")), /* => */ ULONG2NUM(heap_recorder->stats_lifetime.deferred_recordings_committed),
|
|
687
768
|
};
|
|
688
769
|
VALUE hash = rb_hash_new();
|
|
689
770
|
for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(hash, arguments[i], arguments[i+1]);
|
|
@@ -714,26 +795,26 @@ VALUE heap_recorder_testonly_debug(heap_recorder *heap_recorder) {
|
|
|
714
795
|
// ==========================
|
|
715
796
|
// Heap Recorder Internal API
|
|
716
797
|
// ==========================
|
|
717
|
-
|
|
798
|
+
// NOTE: Only expected to be used from heap_recorder_free, which will separately destroy the string table
|
|
799
|
+
static int st_heap_record_entry_free_no_unintern(st_data_t key, DDTRACE_UNUSED st_data_t value, st_data_t extra_arg) {
|
|
718
800
|
heap_recorder *recorder = (heap_recorder *) extra_arg;
|
|
719
|
-
heap_record_free(recorder, (heap_record *) key);
|
|
801
|
+
heap_record_free(recorder, (heap_record *) key, false);
|
|
720
802
|
return ST_DELETE;
|
|
721
803
|
}
|
|
722
804
|
|
|
723
|
-
|
|
805
|
+
// NOTE: Only expected to be used from heap_recorder_free, which will separately destroy the string table
|
|
806
|
+
static int st_object_record_entry_free_no_unintern(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra_arg) {
|
|
724
807
|
heap_recorder *recorder = (heap_recorder *) extra_arg;
|
|
725
|
-
object_record_free(recorder, (object_record *) value);
|
|
808
|
+
object_record_free(recorder, (object_record *) value, false);
|
|
726
809
|
return ST_DELETE;
|
|
727
810
|
}
|
|
728
811
|
|
|
729
812
|
// NOTE: Some operations inside this function can cause the GVL to be released! Plan accordingly.
|
|
730
813
|
static int st_object_record_update(st_data_t key, st_data_t value, st_data_t extra_arg) {
|
|
731
|
-
long
|
|
814
|
+
long record_id = (long) key;
|
|
732
815
|
object_record *record = (object_record*) value;
|
|
733
816
|
heap_recorder *recorder = (heap_recorder*) extra_arg;
|
|
734
817
|
|
|
735
|
-
VALUE ref;
|
|
736
|
-
|
|
737
818
|
size_t update_gen = recorder->update_gen;
|
|
738
819
|
size_t alloc_gen = record->object_data.alloc_gen;
|
|
739
820
|
// Guard against potential overflows given unsigned types here.
|
|
@@ -752,8 +833,10 @@ static int st_object_record_update(st_data_t key, st_data_t value, st_data_t ext
|
|
|
752
833
|
return ST_CONTINUE;
|
|
753
834
|
}
|
|
754
835
|
|
|
755
|
-
|
|
756
|
-
|
|
836
|
+
// Note: This function call can cause the GVL to be released
|
|
837
|
+
VALUE ref = ruby_weak_map_get_may_lose_gvl(recorder->weak_objects, LONG2FIX(record_id));
|
|
838
|
+
if (ref == Qnil) {
|
|
839
|
+
// The weak reference is gone, meaning the object was garbage collected. Need to delete this object record!
|
|
757
840
|
on_committed_object_record_cleanup(recorder, record);
|
|
758
841
|
recorder->stats_last_update.objects_dead++;
|
|
759
842
|
return ST_DELETE;
|
|
@@ -836,15 +919,6 @@ static int st_object_records_debug(DDTRACE_UNUSED st_data_t key, st_data_t value
|
|
|
836
919
|
return ST_CONTINUE;
|
|
837
920
|
}
|
|
838
921
|
|
|
839
|
-
static int update_object_record_entry(DDTRACE_UNUSED st_data_t *key, st_data_t *value, st_data_t new_object_record, int existing) {
|
|
840
|
-
if (!existing) {
|
|
841
|
-
(*value) = (st_data_t) new_object_record; // Expected to be a `object_record *`
|
|
842
|
-
} else {
|
|
843
|
-
// If key already existed, we don't touch the existing value, so it can be used for diagnostics
|
|
844
|
-
}
|
|
845
|
-
return ST_CONTINUE;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
922
|
static void inc_tracked_objects_or_fail(heap_record *heap_record) {
|
|
849
923
|
if (heap_record->num_tracked_objects == UINT32_MAX) {
|
|
850
924
|
raise_error(rb_eRuntimeError, "Reached maximum number of tracked objects for heap record");
|
|
@@ -852,21 +926,12 @@ static void inc_tracked_objects_or_fail(heap_record *heap_record) {
|
|
|
852
926
|
heap_record->num_tracked_objects++;
|
|
853
927
|
}
|
|
854
928
|
|
|
855
|
-
static void commit_recording(heap_recorder *heap_recorder,
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
if (existing_error) {
|
|
862
|
-
object_record *existing_record = NULL;
|
|
863
|
-
st_lookup(heap_recorder->object_records, active_recording->obj_id, (st_data_t *) &existing_record);
|
|
864
|
-
if (existing_record == NULL) raise_error(rb_eRuntimeError, "Unexpected NULL when reading existing record");
|
|
865
|
-
|
|
866
|
-
VALUE existing_inspect = object_record_inspect(heap_recorder, existing_record);
|
|
867
|
-
VALUE new_inspect = object_record_inspect(heap_recorder, active_recording);
|
|
868
|
-
raise_error(rb_eRuntimeError, "Object ids are supposed to be unique. We got 2 allocation recordings with "
|
|
869
|
-
"the same id. previous={%"PRIsVALUE"} new={%"PRIsVALUE"}", existing_inspect, new_inspect);
|
|
929
|
+
static void commit_recording(heap_recorder *heap_recorder, pending_recording pending) {
|
|
930
|
+
object_record *new_record = object_record_new(pending);
|
|
931
|
+
|
|
932
|
+
int existing = st_insert(heap_recorder->object_records, new_record->record_id, (st_data_t) new_record);
|
|
933
|
+
if (existing) {
|
|
934
|
+
raise_error(rb_eRuntimeError, "Unexpected record with the same record_id in heap_recorder->object_records");
|
|
870
935
|
}
|
|
871
936
|
}
|
|
872
937
|
|
|
@@ -886,9 +951,9 @@ static heap_record* get_or_create_heap_record(heap_recorder *heap_recorder, ddog
|
|
|
886
951
|
heap_record *stack = heap_record_new(heap_recorder, locations);
|
|
887
952
|
|
|
888
953
|
heap_record *new_or_existing_record = NULL; // Will be set inside update_heap_record_entry_with_new_allocation
|
|
889
|
-
|
|
954
|
+
int existing = st_update(heap_recorder->heap_records, (st_data_t) stack, update_heap_record_entry_with_new_allocation, (st_data_t) &new_or_existing_record);
|
|
890
955
|
if (existing) {
|
|
891
|
-
heap_record_free(heap_recorder, stack);
|
|
956
|
+
heap_record_free(heap_recorder, stack, true);
|
|
892
957
|
}
|
|
893
958
|
|
|
894
959
|
return new_or_existing_record;
|
|
@@ -903,7 +968,7 @@ static void cleanup_heap_record_if_unused(heap_recorder *heap_recorder, heap_rec
|
|
|
903
968
|
if (!st_delete(heap_recorder->heap_records, (st_data_t*) &heap_record, NULL)) {
|
|
904
969
|
raise_error(rb_eRuntimeError, "Attempted to cleanup an untracked heap_record");
|
|
905
970
|
};
|
|
906
|
-
heap_record_free(heap_recorder, heap_record);
|
|
971
|
+
heap_record_free(heap_recorder, heap_record, true);
|
|
907
972
|
}
|
|
908
973
|
|
|
909
974
|
static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record) {
|
|
@@ -925,32 +990,37 @@ static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, obj
|
|
|
925
990
|
// One less object using this heap record, it may have become unused...
|
|
926
991
|
cleanup_heap_record_if_unused(heap_recorder, heap_record);
|
|
927
992
|
|
|
928
|
-
object_record_free(heap_recorder, record);
|
|
993
|
+
object_record_free(heap_recorder, record, true);
|
|
929
994
|
}
|
|
930
995
|
|
|
931
996
|
// =================
|
|
932
997
|
// Object Record API
|
|
933
998
|
// =================
|
|
934
|
-
object_record* object_record_new(
|
|
999
|
+
static object_record* object_record_new(pending_recording pending) {
|
|
935
1000
|
object_record *record = calloc(1, sizeof(object_record)); // See "note on calloc vs ruby_xcalloc use" above
|
|
936
|
-
record->
|
|
937
|
-
record
|
|
938
|
-
record->
|
|
1001
|
+
record->record_id = pending.record_id;
|
|
1002
|
+
// Link the object record with the corresponding heap record
|
|
1003
|
+
record->heap_record = pending.heap_record;
|
|
1004
|
+
record->object_data = pending.object_data;
|
|
939
1005
|
return record;
|
|
940
1006
|
}
|
|
941
1007
|
|
|
942
|
-
void object_record_free(heap_recorder *recorder, object_record *record) {
|
|
943
|
-
|
|
1008
|
+
static void object_record_free(heap_recorder *recorder, object_record *record, bool should_unintern) {
|
|
1009
|
+
// When tearing down the whole recorder state, we skip uninterning as it's not needed (the managed
|
|
1010
|
+
// string table is going to be destroyed anyway) and if there's any failures we can't raise
|
|
1011
|
+
// in the middle of a dfree callback.
|
|
1012
|
+
if (should_unintern) unintern_or_raise(recorder, record->object_data.class);
|
|
1013
|
+
|
|
944
1014
|
free(record); // See "note on calloc vs ruby_xcalloc use" above
|
|
945
1015
|
}
|
|
946
1016
|
|
|
947
|
-
VALUE object_record_inspect(heap_recorder *recorder, object_record *record) {
|
|
1017
|
+
static VALUE object_record_inspect(heap_recorder *recorder, object_record *record) {
|
|
948
1018
|
heap_frame top_frame = record->heap_record->frames[0];
|
|
949
1019
|
VALUE filename = get_ruby_string_or_raise(recorder, top_frame.filename);
|
|
950
1020
|
live_object_data object_data = record->object_data;
|
|
951
1021
|
|
|
952
|
-
VALUE inspect = rb_sprintf("
|
|
953
|
-
record->
|
|
1022
|
+
VALUE inspect = rb_sprintf("record_id=%ld weight=%d size=%zu location=%"PRIsVALUE":%d alloc_gen=%zu gen_age=%zu frozen=%d ",
|
|
1023
|
+
record->record_id, object_data.weight, object_data.size, filename,
|
|
954
1024
|
(int) top_frame.line, object_data.alloc_gen, object_data.gen_age, object_data.is_frozen);
|
|
955
1025
|
|
|
956
1026
|
if (record->object_data.class.value > 0) {
|
|
@@ -958,9 +1028,9 @@ VALUE object_record_inspect(heap_recorder *recorder, object_record *record) {
|
|
|
958
1028
|
|
|
959
1029
|
rb_str_catf(inspect, "class=%"PRIsVALUE" ", class);
|
|
960
1030
|
}
|
|
961
|
-
VALUE ref;
|
|
962
1031
|
|
|
963
|
-
|
|
1032
|
+
VALUE ref = ruby_weak_map_get_may_lose_gvl(recorder->weak_objects, LONG2FIX(record->record_id));
|
|
1033
|
+
if (ref == Qnil) {
|
|
964
1034
|
rb_str_catf(inspect, "object=<invalid>");
|
|
965
1035
|
} else {
|
|
966
1036
|
rb_str_catf(inspect, "value=%p ", (void *) ref);
|
|
@@ -978,7 +1048,7 @@ VALUE object_record_inspect(heap_recorder *recorder, object_record *record) {
|
|
|
978
1048
|
// ==============
|
|
979
1049
|
// Heap Record API
|
|
980
1050
|
// ==============
|
|
981
|
-
heap_record* heap_record_new(heap_recorder *recorder, ddog_prof_Slice_Location locations) {
|
|
1051
|
+
static heap_record* heap_record_new(heap_recorder *recorder, ddog_prof_Slice_Location locations) {
|
|
982
1052
|
uint16_t frames_len = locations.len;
|
|
983
1053
|
if (frames_len > MAX_FRAMES_LIMIT) {
|
|
984
1054
|
// This is not expected as MAX_FRAMES_LIMIT is shared with the stacktrace construction mechanism
|
|
@@ -1012,22 +1082,27 @@ heap_record* heap_record_new(heap_recorder *recorder, ddog_prof_Slice_Location l
|
|
|
1012
1082
|
return stack;
|
|
1013
1083
|
}
|
|
1014
1084
|
|
|
1015
|
-
void heap_record_free(heap_recorder *recorder, heap_record *stack) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
//
|
|
1019
|
-
|
|
1020
|
-
ids
|
|
1021
|
-
|
|
1085
|
+
static void heap_record_free(heap_recorder *recorder, heap_record *stack, bool should_unintern) {
|
|
1086
|
+
// When tearing down the whole recorder state, we skip uninterning as it's not needed (the managed
|
|
1087
|
+
// string table is going to be destroyed anyway) and if there's any failures we can't raise
|
|
1088
|
+
// in the middle of a dfree callback.
|
|
1089
|
+
if (should_unintern) {
|
|
1090
|
+
ddog_prof_ManagedStringId *ids = recorder->reusable_ids;
|
|
1091
|
+
|
|
1092
|
+
// Put all the ids in the same array; doesn't really matter the order
|
|
1093
|
+
for (u_int16_t i = 0; i < stack->frames_len; i++) {
|
|
1094
|
+
ids[i] = stack->frames[i].filename;
|
|
1095
|
+
ids[i + stack->frames_len] = stack->frames[i].name;
|
|
1096
|
+
}
|
|
1097
|
+
unintern_all_or_raise(recorder, (ddog_prof_Slice_ManagedStringId) { .ptr = ids, .len = stack->frames_len * 2 });
|
|
1022
1098
|
}
|
|
1023
|
-
unintern_all_or_raise(recorder, (ddog_prof_Slice_ManagedStringId) { .ptr = ids, .len = stack->frames_len * 2 });
|
|
1024
1099
|
|
|
1025
1100
|
free(stack); // See "note on calloc vs ruby_xcalloc use" above
|
|
1026
1101
|
}
|
|
1027
1102
|
|
|
1028
1103
|
// The entire stack is represented by ids (name, filename) and lines (integers) so we can treat is as just
|
|
1029
1104
|
// a big string of bytes and compare it all in one go.
|
|
1030
|
-
int heap_record_cmp_st(st_data_t key1, st_data_t key2) {
|
|
1105
|
+
static int heap_record_cmp_st(st_data_t key1, st_data_t key2) {
|
|
1031
1106
|
heap_record *stack1 = (heap_record*) key1;
|
|
1032
1107
|
heap_record *stack2 = (heap_record*) key2;
|
|
1033
1108
|
|
|
@@ -1043,7 +1118,7 @@ int heap_record_cmp_st(st_data_t key1, st_data_t key2) {
|
|
|
1043
1118
|
|
|
1044
1119
|
// The entire stack is represented by ids (name, filename) and lines (integers) so we can treat is as just
|
|
1045
1120
|
// a big string of bytes and hash it all in one go.
|
|
1046
|
-
st_index_t heap_record_hash_st(st_data_t key) {
|
|
1121
|
+
static st_index_t heap_record_hash_st(st_data_t key) {
|
|
1047
1122
|
heap_record *stack = (heap_record*) key;
|
|
1048
1123
|
return st_hash(stack->frames, stack->frames_len * sizeof(heap_frame), FNV1_32A_INIT);
|
|
1049
1124
|
}
|
|
@@ -1075,29 +1150,68 @@ static VALUE get_ruby_string_or_raise(heap_recorder *recorder, ddog_prof_Managed
|
|
|
1075
1150
|
return ruby_string;
|
|
1076
1151
|
}
|
|
1077
1152
|
|
|
1078
|
-
static
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1153
|
+
static inline double ewma_stat(double previous, double current) {
|
|
1154
|
+
double alpha = 0.3;
|
|
1155
|
+
return (1 - alpha) * previous + alpha * current;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
VALUE heap_recorder_testonly_is_object_recorded(heap_recorder *heap_recorder, long record_id) {
|
|
1159
|
+
if (heap_recorder == NULL) {
|
|
1160
|
+
raise_error(rb_eArgError, "heap_recorder is NULL");
|
|
1084
1161
|
}
|
|
1085
1162
|
|
|
1086
|
-
|
|
1163
|
+
// Check if object records contains an object with this record_id
|
|
1164
|
+
return st_is_member(heap_recorder->object_records, record_id) ? Qtrue : Qfalse;
|
|
1087
1165
|
}
|
|
1088
1166
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1167
|
+
typedef struct {
|
|
1168
|
+
heap_recorder *recorder;
|
|
1169
|
+
VALUE target;
|
|
1170
|
+
VALUE result;
|
|
1171
|
+
} record_id_for_context;
|
|
1172
|
+
|
|
1173
|
+
static int st_object_record_id_for(st_data_t key, DDTRACE_UNUSED st_data_t value, st_data_t extra) {
|
|
1174
|
+
record_id_for_context *context = (record_id_for_context*) extra;
|
|
1175
|
+
long record_id = (long) key;
|
|
1176
|
+
|
|
1177
|
+
VALUE ref = ruby_weak_map_get_may_lose_gvl(context->recorder->weak_objects, LONG2FIX(record_id));
|
|
1178
|
+
if (ref != Qnil && ref == context->target) {
|
|
1179
|
+
context->result = LONG2FIX(record_id);
|
|
1180
|
+
return ST_STOP;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
return ST_CONTINUE;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
VALUE heap_recorder_testonly_record_id_for(heap_recorder *heap_recorder, VALUE obj) {
|
|
1187
|
+
// Heap profiling is disabled, so nothing is being tracked
|
|
1188
|
+
if (heap_recorder == NULL) return Qnil;
|
|
1189
|
+
|
|
1190
|
+
record_id_for_context context = (record_id_for_context) {.recorder = heap_recorder, .target = obj, .result = Qnil};
|
|
1191
|
+
st_foreach(heap_recorder->object_records, st_object_record_id_for, (st_data_t) &context);
|
|
1192
|
+
|
|
1193
|
+
return context.result;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
void heap_recorder_testonly_set_object_alloc_gen(heap_recorder *heap_recorder, long record_id, size_t alloc_gen) {
|
|
1197
|
+
if (heap_recorder == NULL) {
|
|
1198
|
+
raise_error(rb_eArgError, "heap_recorder is NULL");
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
object_record *record = NULL;
|
|
1202
|
+
if (!st_lookup(heap_recorder->object_records, (st_data_t) record_id, (st_data_t *) &record)) {
|
|
1203
|
+
raise_error(rb_eArgError, "record_id %ld is not being tracked", record_id);
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
record->object_data.alloc_gen = alloc_gen;
|
|
1092
1207
|
}
|
|
1093
1208
|
|
|
1094
|
-
|
|
1209
|
+
void heap_recorder_testonly_exhaust_record_ids(heap_recorder *heap_recorder) {
|
|
1095
1210
|
if (heap_recorder == NULL) {
|
|
1096
1211
|
raise_error(rb_eArgError, "heap_recorder is NULL");
|
|
1097
1212
|
}
|
|
1098
1213
|
|
|
1099
|
-
|
|
1100
|
-
return st_is_member(heap_recorder->object_records, FIX2LONG(obj_id)) ? Qtrue : Qfalse;
|
|
1214
|
+
heap_recorder->next_record_id = RUBY_FIXNUM_MAX;
|
|
1101
1215
|
}
|
|
1102
1216
|
|
|
1103
1217
|
void heap_recorder_testonly_reset_last_update(heap_recorder *heap_recorder) {
|