datadog 2.17.0 → 2.37.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 +686 -1
- data/README.md +0 -1
- data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
- 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 +3 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +344 -126
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -4
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
- data/ext/datadog_profiling_native_extension/collectors_stack.c +314 -91
- data/ext/datadog_profiling_native_extension/collectors_stack.h +26 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +680 -352
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +18 -5
- data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +65 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +40 -1
- data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +48 -34
- 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 +455 -430
- data/ext/datadog_profiling_native_extension/heap_recorder.h +16 -7
- data/ext/datadog_profiling_native_extension/http_transport.c +66 -68
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +18 -15
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -10
- data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +73 -69
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +10 -4
- data/ext/datadog_profiling_native_extension/profiling.c +65 -19
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +64 -59
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +20 -16
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +32 -10
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
- data/ext/datadog_profiling_native_extension/stack_recorder.c +253 -131
- data/ext/datadog_profiling_native_extension/stack_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +9 -4
- data/ext/libdatadog_api/crashtracker.c +16 -15
- data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +65 -1
- data/ext/libdatadog_api/datadog_ruby_common.h +40 -1
- data/ext/libdatadog_api/ddsketch.c +102 -0
- data/ext/libdatadog_api/di.c +203 -0
- data/ext/libdatadog_api/extconf.rb +21 -25
- data/ext/libdatadog_api/feature_flags.c +554 -0
- data/ext/libdatadog_api/feature_flags.h +5 -0
- data/ext/libdatadog_api/helpers.h +27 -0
- data/ext/libdatadog_api/init.c +13 -1
- data/ext/libdatadog_api/library_config.c +88 -37
- data/ext/libdatadog_api/library_config.h +6 -0
- data/ext/libdatadog_api/process_discovery.c +25 -24
- data/ext/libdatadog_extconf_helpers.rb +107 -14
- data/lib/datadog/ai_guard/api_client.rb +84 -0
- data/lib/datadog/ai_guard/autoload.rb +10 -0
- data/lib/datadog/ai_guard/component.rb +44 -0
- data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
- data/lib/datadog/ai_guard/configuration.rb +115 -0
- data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
- data/lib/datadog/ai_guard/contrib/integration.rb +37 -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 +80 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/request.rb +86 -0
- data/lib/datadog/ai_guard/evaluation/result.rb +45 -0
- data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
- data/lib/datadog/ai_guard/evaluation.rb +108 -0
- data/lib/datadog/ai_guard/ext.rb +29 -0
- data/lib/datadog/ai_guard.rb +181 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
- data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +104 -0
- data/lib/datadog/appsec/api_security/sampler.rb +62 -0
- data/lib/datadog/appsec/api_security.rb +14 -0
- data/lib/datadog/appsec/assets/blocked.html +10 -1
- data/lib/datadog/appsec/assets/blocked.json +1 -1
- data/lib/datadog/appsec/assets/blocked.text +3 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +601 -74
- data/lib/datadog/appsec/assets/waf_rules/strict.json +48 -75
- data/lib/datadog/appsec/assets.rb +1 -1
- data/lib/datadog/appsec/autoload.rb +2 -2
- data/lib/datadog/appsec/component.rb +37 -64
- data/lib/datadog/appsec/compressed_json.rb +3 -3
- data/lib/datadog/appsec/configuration.rb +427 -1
- data/lib/datadog/appsec/context.rb +77 -16
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
- data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -1
- 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 +144 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +4 -2
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +2 -1
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/patcher.rb +3 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +152 -13
- data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +138 -13
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +74 -24
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +4 -2
- data/lib/datadog/appsec/contrib/graphql/integration.rb +2 -1
- data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
- data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +47 -13
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +40 -19
- data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +80 -62
- data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
- data/lib/datadog/appsec/contrib/rails/gateway/request.rb +35 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +47 -5
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +52 -26
- data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +29 -0
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +3 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +167 -12
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +63 -10
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +11 -21
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
- data/lib/datadog/appsec/counter_sampler.rb +25 -0
- data/lib/datadog/appsec/default_header_tags.rb +52 -0
- data/lib/datadog/appsec/event.rb +14 -47
- data/lib/datadog/appsec/ext.rb +3 -0
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +17 -1
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
- data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
- data/lib/datadog/appsec/metrics/collector.rb +47 -5
- data/lib/datadog/appsec/metrics/exporter.rb +16 -3
- data/lib/datadog/appsec/metrics/telemetry.rb +21 -4
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +47 -0
- data/lib/datadog/appsec/metrics.rb +5 -4
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -6
- data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
- data/lib/datadog/appsec/remote.rb +51 -76
- data/lib/datadog/appsec/response.rb +18 -4
- 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 +197 -0
- data/lib/datadog/appsec/security_engine/result.rb +45 -9
- data/lib/datadog/appsec/security_engine/runner.rb +44 -21
- data/lib/datadog/appsec/security_event.rb +5 -7
- data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
- data/lib/datadog/appsec/trace_keeper.rb +36 -0
- data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
- data/lib/datadog/appsec/utils/http/body.rb +38 -0
- data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
- data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
- data/lib/datadog/appsec/utils/http/media_type.rb +32 -26
- data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
- data/lib/datadog/appsec.rb +10 -17
- data/lib/datadog/auto_instrument_base.rb +2 -1
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -47
- data/lib/datadog/core/configuration/base.rb +17 -5
- data/lib/datadog/core/configuration/components.rb +192 -20
- data/lib/datadog/core/configuration/components_state.rb +6 -1
- data/lib/datadog/core/configuration/config_helper.rb +109 -0
- data/lib/datadog/core/configuration/deprecations.rb +36 -0
- data/lib/datadog/core/configuration/ext.rb +0 -1
- data/lib/datadog/core/configuration/option.rb +95 -65
- data/lib/datadog/core/configuration/option_definition.rb +42 -23
- data/lib/datadog/core/configuration/options.rb +57 -18
- data/lib/datadog/core/configuration/settings.rb +160 -25
- data/lib/datadog/core/configuration/stable_config.rb +11 -2
- data/lib/datadog/core/configuration/supported_configurations.rb +413 -0
- data/lib/datadog/core/configuration.rb +4 -4
- 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 +73 -21
- data/lib/datadog/core/crashtracking/tag_builder.rb +9 -21
- data/lib/datadog/core/ddsketch.rb +19 -0
- data/lib/datadog/core/deprecations.rb +2 -2
- data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/core/environment/agent_info.rb +65 -1
- data/lib/datadog/core/environment/cgroup.rb +52 -25
- data/lib/datadog/core/environment/container.rb +140 -46
- data/lib/datadog/core/environment/ext.rb +13 -2
- data/lib/datadog/core/environment/git.rb +2 -2
- data/lib/datadog/core/environment/identity.rb +40 -4
- data/lib/datadog/core/environment/process.rb +122 -0
- data/lib/datadog/core/environment/socket.rb +13 -0
- data/lib/datadog/core/environment/variable_helpers.rb +3 -3
- data/lib/datadog/core/environment/yjit.rb +2 -1
- data/lib/datadog/core/error.rb +6 -6
- data/lib/datadog/core/evp.rb +11 -0
- data/lib/datadog/core/feature_flags.rb +61 -0
- data/lib/datadog/core/knuth_sampler.rb +57 -0
- data/lib/datadog/core/logger.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +7 -7
- data/lib/datadog/core/metrics/logging.rb +1 -1
- data/lib/datadog/core/pin.rb +8 -8
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
- data/lib/datadog/core/process_discovery.rb +51 -21
- data/lib/datadog/core/rate_limiter.rb +11 -1
- data/lib/datadog/core/remote/client/capabilities.rb +49 -6
- data/lib/datadog/core/remote/client.rb +15 -7
- data/lib/datadog/core/remote/component.rb +64 -36
- data/lib/datadog/core/remote/configuration/content.rb +15 -2
- data/lib/datadog/core/remote/configuration/digest.rb +14 -7
- data/lib/datadog/core/remote/configuration/repository.rb +13 -1
- data/lib/datadog/core/remote/configuration/target.rb +13 -6
- data/lib/datadog/core/remote/transport/config.rb +9 -36
- data/lib/datadog/core/remote/transport/http/config.rb +15 -55
- data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
- data/lib/datadog/core/remote/transport/http.rb +15 -24
- data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
- data/lib/datadog/core/remote/worker.rb +25 -37
- data/lib/datadog/core/runtime/ext.rb +0 -1
- data/lib/datadog/core/runtime/metrics.rb +11 -2
- data/lib/datadog/core/semaphore.rb +1 -4
- data/lib/datadog/core/tag_builder.rb +52 -0
- data/lib/datadog/core/tag_normalizer.rb +84 -0
- data/lib/datadog/core/telemetry/component.rb +65 -17
- data/lib/datadog/core/telemetry/emitter.rb +6 -6
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -3
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
- data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +203 -89
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
- data/lib/datadog/core/telemetry/event.rb +2 -7
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/logger.rb +5 -2
- data/lib/datadog/core/telemetry/logging.rb +22 -4
- data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
- data/lib/datadog/core/telemetry/request.rb +17 -5
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +8 -34
- data/lib/datadog/core/telemetry/transport/http.rb +21 -16
- data/lib/datadog/core/telemetry/transport/telemetry.rb +8 -17
- data/lib/datadog/core/telemetry/worker.rb +108 -32
- data/lib/datadog/core/transport/ext.rb +3 -0
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
- data/lib/datadog/core/transport/http/api/instance.rb +4 -21
- data/lib/datadog/core/transport/http/builder.rb +11 -7
- data/lib/datadog/core/transport/http/client.rb +80 -0
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/transport/http/response.rb +4 -0
- data/lib/datadog/core/transport/http.rb +24 -19
- data/lib/datadog/core/transport/parcel.rb +61 -9
- data/lib/datadog/core/transport/response.rb +16 -2
- data/lib/datadog/core/transport/transport.rb +90 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +1 -1
- data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +4 -3
- data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
- data/lib/datadog/core/utils/fnv.rb +26 -0
- data/lib/datadog/core/utils/forking.rb +3 -1
- data/lib/datadog/core/utils/hash.rb +0 -23
- data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -14
- data/lib/datadog/core/utils/network.rb +22 -1
- data/lib/datadog/core/utils/only_once.rb +1 -1
- data/lib/datadog/core/utils/only_once_successful.rb +8 -2
- data/lib/datadog/core/utils/safe_dup.rb +2 -2
- data/lib/datadog/core/utils/sequence.rb +2 -0
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
- data/lib/datadog/core/utils/time.rb +1 -1
- data/lib/datadog/core/utils.rb +10 -1
- data/lib/datadog/core/workers/async.rb +11 -2
- data/lib/datadog/core/workers/interval_loop.rb +51 -3
- data/lib/datadog/core/workers/polling.rb +2 -0
- data/lib/datadog/core/workers/queue.rb +96 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
- data/lib/datadog/core.rb +11 -2
- data/lib/datadog/data_streams/configuration.rb +50 -0
- data/lib/datadog/data_streams/ext.rb +11 -0
- data/lib/datadog/data_streams/extensions.rb +16 -0
- data/lib/datadog/data_streams/pathway_context.rb +169 -0
- data/lib/datadog/data_streams/processor.rb +511 -0
- data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
- data/lib/datadog/data_streams/transport/http.rb +36 -0
- data/lib/datadog/data_streams/transport/stats.rb +39 -0
- data/lib/datadog/data_streams.rb +100 -0
- data/lib/datadog/di/base.rb +15 -7
- data/lib/datadog/di/boot.rb +11 -1
- data/lib/datadog/di/code_tracker.rb +217 -15
- data/lib/datadog/di/component.rb +143 -48
- data/lib/datadog/di/configuration.rb +235 -2
- data/lib/datadog/di/context.rb +76 -0
- data/lib/datadog/di/contrib/active_record.rb +34 -5
- data/lib/datadog/di/el/compiler.rb +168 -0
- data/lib/datadog/di/el/evaluator.rb +159 -0
- data/lib/datadog/di/el/expression.rb +42 -0
- data/lib/datadog/di/el.rb +5 -0
- data/lib/datadog/di/error.rb +44 -0
- data/lib/datadog/di/fatal_exceptions.rb +26 -0
- data/lib/datadog/di/instrumenter.rb +620 -132
- data/lib/datadog/di/logger.rb +2 -2
- data/lib/datadog/di/probe.rb +78 -15
- data/lib/datadog/di/probe_builder.rb +42 -3
- data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
- data/lib/datadog/di/probe_file_loader.rb +87 -0
- data/lib/datadog/di/probe_manager.rb +195 -100
- data/lib/datadog/di/probe_notification_builder.rb +285 -100
- data/lib/datadog/di/probe_notifier_worker.rb +120 -36
- data/lib/datadog/di/probe_repository.rb +198 -0
- data/lib/datadog/di/proc_responder.rb +36 -0
- data/lib/datadog/di/redactor.rb +24 -2
- data/lib/datadog/di/remote.rb +258 -95
- data/lib/datadog/di/serializer.rb +297 -20
- data/lib/datadog/di/transport/diagnostics.rb +12 -42
- data/lib/datadog/di/transport/http/diagnostics.rb +4 -34
- data/lib/datadog/di/transport/http/input.rb +12 -34
- data/lib/datadog/di/transport/http.rb +43 -19
- data/lib/datadog/di/transport/input.rb +121 -39
- data/lib/datadog/di/utils.rb +42 -14
- data/lib/datadog/di.rb +203 -10
- data/lib/datadog/error_tracking/collector.rb +2 -1
- data/lib/datadog/error_tracking/component.rb +2 -2
- data/lib/datadog/error_tracking/configuration.rb +55 -2
- data/lib/datadog/error_tracking/filters.rb +2 -2
- data/lib/datadog/kit/appsec/events/v2.rb +253 -0
- data/lib/datadog/kit/appsec/events.rb +11 -10
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/kit/identity.rb +17 -11
- data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
- data/lib/datadog/open_feature/component.rb +100 -0
- data/lib/datadog/open_feature/configuration.rb +37 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
- data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
- data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
- data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
- data/lib/datadog/open_feature/exposures/event.rb +60 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
- data/lib/datadog/open_feature/exposures/worker.rb +116 -0
- data/lib/datadog/open_feature/ext.rb +16 -0
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
- data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +49 -0
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
- data/lib/datadog/open_feature/native_evaluator.rb +60 -0
- data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
- data/lib/datadog/open_feature/provider.rb +191 -0
- data/lib/datadog/open_feature/remote.rb +67 -0
- data/lib/datadog/open_feature/resolution_details.rb +35 -0
- data/lib/datadog/open_feature/transport.rb +121 -0
- data/lib/datadog/open_feature.rb +19 -0
- data/lib/datadog/opentelemetry/api/baggage.rb +3 -3
- data/lib/datadog/opentelemetry/api/context.rb +10 -9
- data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
- data/lib/datadog/opentelemetry/ext.rb +9 -0
- data/lib/datadog/opentelemetry/logs.rb +98 -0
- data/lib/datadog/opentelemetry/metrics.rb +90 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +66 -2
- 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 +28 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +13 -7
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +12 -9
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +14 -10
- data/lib/datadog/opentelemetry/sdk.rb +19 -0
- data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
- data/lib/datadog/opentelemetry/trace.rb +4 -4
- data/lib/datadog/opentelemetry.rb +4 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +83 -15
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +52 -3
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +13 -4
- data/lib/datadog/profiling/collectors/info.rb +59 -4
- data/lib/datadog/profiling/collectors/thread_context.rb +17 -5
- data/lib/datadog/profiling/component.rb +73 -49
- data/lib/datadog/profiling/exporter.rb +48 -13
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
- data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
- data/lib/datadog/profiling/ext.rb +2 -15
- data/lib/datadog/profiling/flush.rb +23 -11
- data/lib/datadog/profiling/http_transport.rb +24 -11
- data/lib/datadog/profiling/load_native_extension.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +31 -12
- data/lib/datadog/profiling/scheduler.rb +12 -10
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +5 -13
- data/lib/datadog/profiling/tag_builder.rb +42 -38
- data/lib/datadog/profiling/tasks/exec.rb +10 -5
- data/lib/datadog/profiling/tasks/help.rb +1 -0
- data/lib/datadog/profiling/tasks/setup.rb +4 -2
- data/lib/datadog/profiling.rb +8 -11
- data/lib/datadog/ruby_version.rb +25 -0
- data/lib/datadog/single_step_instrument.rb +10 -1
- data/lib/datadog/symbol_database/component.rb +734 -0
- data/lib/datadog/symbol_database/configuration.rb +73 -0
- data/lib/datadog/symbol_database/extensions.rb +19 -0
- data/lib/datadog/symbol_database/extractor.rb +1110 -0
- data/lib/datadog/symbol_database/file_hash.rb +48 -0
- data/lib/datadog/symbol_database/logger.rb +43 -0
- data/lib/datadog/symbol_database/remote.rb +180 -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 +10 -10
- data/lib/datadog/tracing/component.rb +17 -17
- data/lib/datadog/tracing/configuration/dynamic.rb +6 -8
- data/lib/datadog/tracing/configuration/ext.rb +25 -5
- data/lib/datadog/tracing/configuration/settings.rb +125 -11
- data/lib/datadog/tracing/context.rb +2 -2
- data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +29 -11
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +47 -12
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/event.rb +8 -8
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +6 -3
- data/lib/datadog/tracing/contrib/active_job/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +2 -2
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +4 -4
- data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +1 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +3 -3
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +7 -10
- data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +16 -16
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +15 -12
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +2 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +8 -10
- data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +8 -10
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +3 -1
- data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/service/base.rb +2 -1
- data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/service/s3.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/service/sns.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/service/sqs.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/service/states.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/services.rb +7 -7
- data/lib/datadog/tracing/contrib/component.rb +3 -3
- data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/configurable.rb +22 -7
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
- data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +4 -4
- data/lib/datadog/tracing/contrib/dalli/ext.rb +3 -2
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/dalli/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/delayed_job/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
- data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +3 -2
- data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +47 -53
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +7 -7
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +7 -8
- data/lib/datadog/tracing/contrib/ethon/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/ethon/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +16 -5
- data/lib/datadog/tracing/contrib/excon/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/excon/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -9
- data/lib/datadog/tracing/contrib/ext.rb +6 -4
- data/lib/datadog/tracing/contrib/extensions.rb +28 -11
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +16 -9
- data/lib/datadog/tracing/contrib/faraday/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/faraday/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +7 -9
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +18 -15
- data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
- data/lib/datadog/tracing/contrib/grape/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +105 -63
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +11 -15
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +6 -10
- data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
- data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/grpc/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc.rb +1 -0
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
- data/lib/datadog/tracing/contrib/hanami/ext.rb +2 -2
- data/lib/datadog/tracing/contrib/hanami/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +2 -1
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +10 -11
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +16 -5
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +4 -4
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
- data/lib/datadog/tracing/contrib/http/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +9 -13
- data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
- data/lib/datadog/tracing/contrib/http.rb +1 -0
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +16 -5
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -10
- data/lib/datadog/tracing/contrib/httpclient/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +16 -5
- data/lib/datadog/tracing/contrib/httprb/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/httprb/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/event.rb +2 -1
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
- data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +24 -13
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +39 -8
- data/lib/datadog/tracing/contrib/karafka.rb +1 -0
- data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +6 -6
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +11 -14
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/mysql2/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +3 -2
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +1 -2
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +64 -70
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +7 -7
- data/lib/datadog/tracing/contrib/patcher.rb +7 -9
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +3 -6
- data/lib/datadog/tracing/contrib/pg/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +9 -11
- data/lib/datadog/tracing/contrib/presto/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +1 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +13 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +6 -2
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +25 -1
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/que/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
- data/lib/datadog/tracing/contrib/racecar/event.rb +2 -6
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/events/consume.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +11 -1
- data/lib/datadog/tracing/contrib/rack/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +55 -32
- data/lib/datadog/tracing/contrib/rack/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +83 -44
- data/lib/datadog/tracing/contrib/rack/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +4 -3
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +126 -2
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +6 -3
- data/lib/datadog/tracing/contrib/rails/ext.rb +3 -1
- data/lib/datadog/tracing/contrib/rails/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +3 -3
- data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/rails/runner.rb +64 -40
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +10 -8
- data/lib/datadog/tracing/contrib/rake/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/ext.rb +3 -2
- data/lib/datadog/tracing/contrib/redis/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/redis/quantize.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/tags.rb +2 -7
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +6 -4
- data/lib/datadog/tracing/contrib/registerable.rb +11 -0
- data/lib/datadog/tracing/contrib/registry.rb +1 -1
- data/lib/datadog/tracing/contrib/resque/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/resque/resque_job.rb +2 -1
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +8 -9
- data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +8 -3
- data/lib/datadog/tracing/contrib/roda/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/database.rb +6 -5
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +2 -1
- data/lib/datadog/tracing/contrib/sequel/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -6
- data/lib/datadog/tracing/contrib/shoryuken/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/sidekiq/integration.rb +1 -1
- 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 +8 -4
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +40 -39
- data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
- data/lib/datadog/tracing/contrib/stripe/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/stripe/request.rb +2 -2
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
- data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/trilogy/ext.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -6
- data/lib/datadog/tracing/contrib/trilogy/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +15 -13
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +6 -6
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
- data/lib/datadog/tracing/contrib.rb +9 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +12 -4
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +133 -12
- data/lib/datadog/tracing/distributed/datadog.rb +17 -16
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +11 -26
- data/lib/datadog/tracing/distributed/helpers.rb +1 -1
- data/lib/datadog/tracing/distributed/none.rb +4 -2
- data/lib/datadog/tracing/distributed/propagation.rb +39 -4
- data/lib/datadog/tracing/distributed/propagation_policy.rb +1 -1
- data/lib/datadog/tracing/distributed/trace_context.rb +107 -78
- data/lib/datadog/tracing/event.rb +5 -7
- data/lib/datadog/tracing/ext.rb +9 -0
- data/lib/datadog/tracing/flush.rb +1 -1
- data/lib/datadog/tracing/metadata/analytics.rb +1 -1
- data/lib/datadog/tracing/metadata/ext.rb +23 -1
- data/lib/datadog/tracing/metadata/tagging.rb +6 -6
- data/lib/datadog/tracing/pipeline/span_filter.rb +3 -1
- data/lib/datadog/tracing/pipeline/span_processor.rb +3 -1
- data/lib/datadog/tracing/pipeline.rb +2 -2
- data/lib/datadog/tracing/remote.rb +36 -13
- data/lib/datadog/tracing/sampling/ext.rb +2 -2
- data/lib/datadog/tracing/sampling/priority_sampler.rb +16 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +77 -48
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +3 -3
- data/lib/datadog/tracing/sampling/span/sampler.rb +0 -7
- data/lib/datadog/tracing/span.rb +2 -2
- data/lib/datadog/tracing/span_event.rb +12 -12
- data/lib/datadog/tracing/span_link.rb +12 -12
- data/lib/datadog/tracing/span_operation.rb +63 -19
- data/lib/datadog/tracing/sync_writer.rb +1 -2
- data/lib/datadog/tracing/trace_digest.rb +28 -23
- data/lib/datadog/tracing/trace_operation.rb +209 -98
- data/lib/datadog/tracing/trace_segment.rb +2 -2
- data/lib/datadog/tracing/tracer.rb +113 -52
- data/lib/datadog/tracing/transport/http/client.rb +12 -26
- data/lib/datadog/tracing/transport/http/traces.rb +4 -52
- data/lib/datadog/tracing/transport/http.rb +15 -9
- data/lib/datadog/tracing/transport/io/client.rb +11 -14
- data/lib/datadog/tracing/transport/io/traces.rb +28 -34
- data/lib/datadog/tracing/transport/statistics.rb +1 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +22 -0
- data/lib/datadog/tracing/transport/traces.rb +14 -82
- data/lib/datadog/tracing/workers.rb +4 -3
- data/lib/datadog/tracing/writer.rb +1 -1
- data/lib/datadog/tracing.rb +2 -2
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +14 -0
- metadata +201 -40
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
- data/ext/libdatadog_api/macos_development.md +0 -26
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
- data/lib/datadog/appsec/configuration/settings.rb +0 -342
- data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
- data/lib/datadog/appsec/processor.rb +0 -107
- data/lib/datadog/core/remote/transport/http/api.rb +0 -53
- data/lib/datadog/core/remote/transport/http/client.rb +0 -49
- data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
- data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
- data/lib/datadog/core/transport/http/api/spec.rb +0 -36
- data/lib/datadog/di/configuration/settings.rb +0 -212
- data/lib/datadog/di/transport/http/api.rb +0 -42
- data/lib/datadog/di/transport/http/client.rb +0 -47
- data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
- data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
- data/lib/datadog/tracing/transport/http/api.rb +0 -44
- data/lib/datadog/tracing/workers/trace_writer.rb +0 -199
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../symbol_database'
|
|
4
|
+
require_relative 'extractor'
|
|
5
|
+
require_relative 'logger'
|
|
6
|
+
require_relative 'scope_batcher'
|
|
7
|
+
require_relative 'uploader'
|
|
8
|
+
require_relative '../core/utils/time'
|
|
9
|
+
require_relative '../di/fatal_exceptions'
|
|
10
|
+
|
|
11
|
+
module Datadog
|
|
12
|
+
module SymbolDatabase
|
|
13
|
+
# Main coordinator for symbol database upload functionality.
|
|
14
|
+
#
|
|
15
|
+
# Responsibilities:
|
|
16
|
+
# - Lifecycle management: Initialization, shutdown, upload triggering
|
|
17
|
+
# - Coordination: Connects Extractor → ScopeBatcher → Uploader
|
|
18
|
+
# - Remote config handling: start_upload called by Remote module on config changes
|
|
19
|
+
# - Debounce: extraction is deferred by EXTRACT_DEBOUNCE_INTERVAL seconds so
|
|
20
|
+
# reconfigurations during boot coalesce into a single extraction on the
|
|
21
|
+
# final Component instance.
|
|
22
|
+
# - Hot-load coverage: TracePoint :class hook captures classes loaded after
|
|
23
|
+
# initial extraction, enqueues them on a per-instance buffer; the scheduler
|
|
24
|
+
# drains the buffer on debounce and extracts each one via Extractor#extract,
|
|
25
|
+
# matching Java/Python/.NET continuous coverage.
|
|
26
|
+
#
|
|
27
|
+
# Upload flow:
|
|
28
|
+
# 1. Remote config sends upload_symbols: true (or force_upload mode)
|
|
29
|
+
# 2. start_upload called — schedules extraction EXTRACT_DEBOUNCE_INTERVAL
|
|
30
|
+
# seconds in the future on a per-instance scheduler thread, and lazily
|
|
31
|
+
# installs the TracePoint :class hook if not already installed.
|
|
32
|
+
# 3. When the timer fires (no further start_upload calls reset it),
|
|
33
|
+
# extract_and_upload runs. On the first call: ObjectSpace iteration →
|
|
34
|
+
# Extractor#extract_all. On subsequent calls: drain the hot-load buffer →
|
|
35
|
+
# Extractor#extract per module.
|
|
36
|
+
# 4. ScopeBatcher batches and triggers Uploader.
|
|
37
|
+
# 5. As new classes load throughout the process lifetime, the TracePoint hook
|
|
38
|
+
# fires and signals the scheduler — the next debounce window produces an
|
|
39
|
+
# incremental upload of just the new classes.
|
|
40
|
+
#
|
|
41
|
+
# Created by: Components#initialize (in Core::Configuration::Components)
|
|
42
|
+
# Accessed by: Remote config receiver via Datadog.send(:components).symbol_database
|
|
43
|
+
# Requires: Remote config enabled (unless force mode)
|
|
44
|
+
#
|
|
45
|
+
# @api private
|
|
46
|
+
class Component
|
|
47
|
+
# Debounce window for extraction. Multiple start_upload calls within this
|
|
48
|
+
# window coalesce; the timer fires once after the window of inactivity.
|
|
49
|
+
# Long enough to absorb reconfiguration cascades during Rails boot.
|
|
50
|
+
EXTRACT_DEBOUNCE_INTERVAL = 5 # seconds
|
|
51
|
+
|
|
52
|
+
# Cached unbound Module#singleton_class? — dispatched explicitly inside the
|
|
53
|
+
# hot-load TracePoint so user code that overrides `singleton_class?` (e.g.
|
|
54
|
+
# `def self.singleton_class?(arg)`) cannot raise inside the :class hook and
|
|
55
|
+
# abort the user's class definition. Mirrors the cache in Extractor.
|
|
56
|
+
MODULE_SINGLETON_CLASS_PRED = Module.instance_method(:singleton_class?)
|
|
57
|
+
private_constant :MODULE_SINGLETON_CLASS_PRED
|
|
58
|
+
|
|
59
|
+
# Build a new Component if the runtime supports it and dependencies are met.
|
|
60
|
+
# The caller (Core::Configuration::Components) decides whether the feature is
|
|
61
|
+
# enabled and only invokes build when it is, so a disabled component is never
|
|
62
|
+
# constructed. This method gates only on symbol database's own requirements
|
|
63
|
+
# (supported platform, remote config availability).
|
|
64
|
+
# @param settings [Configuration::Settings] Tracer settings
|
|
65
|
+
# @param agent_settings [Configuration::AgentSettings] Agent configuration
|
|
66
|
+
# @param logger [Logger] Logger instance
|
|
67
|
+
# @param telemetry [Core::Telemetry::Component, nil] Telemetry component for error reporting
|
|
68
|
+
# @param di_active [Proc, nil] Predicate returning whether Dynamic
|
|
69
|
+
# Instrumentation is currently active (started). Gates remote-config
|
|
70
|
+
# uploads in the nil-default case; nil means "no gate" (standalone
|
|
71
|
+
# force_upload contexts).
|
|
72
|
+
# @return [Component, nil] Component instance or nil if requirements not met
|
|
73
|
+
def self.build(settings, agent_settings, logger, telemetry: nil, di_active: nil)
|
|
74
|
+
symdb_logger = SymbolDatabase::Logger.new(settings, logger)
|
|
75
|
+
|
|
76
|
+
# Symbol database requires MRI Ruby 2.7+.
|
|
77
|
+
# Configuration accessors (settings.symbol_database.*) remain available on all
|
|
78
|
+
# platforms — only the component (upload) is disabled on unsupported engines/versions.
|
|
79
|
+
# environment_supported? logs the specific reason (engine or version) internally.
|
|
80
|
+
return nil unless environment_supported?(symdb_logger)
|
|
81
|
+
|
|
82
|
+
# Requires remote config (unless force mode)
|
|
83
|
+
if !settings.remote&.enabled && !settings.symbol_database.internal.force_upload
|
|
84
|
+
symdb_logger.debug("symdb: remote config not available and force_upload not set, skipping")
|
|
85
|
+
return nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
new(settings, agent_settings, symdb_logger, telemetry: telemetry, di_active: di_active).tap do |component|
|
|
89
|
+
# Defer extraction if force upload mode — wait for app boot to complete
|
|
90
|
+
component.schedule_deferred_upload if settings.symbol_database.internal.force_upload
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
attr_reader :settings, :logger, :last_upload_time, :last_upload_scope_count, :upload_in_progress
|
|
95
|
+
|
|
96
|
+
# Initialize component.
|
|
97
|
+
# @param settings [Configuration::Settings] Tracer settings
|
|
98
|
+
# @param agent_settings [Configuration::AgentSettings] Agent configuration
|
|
99
|
+
# @param logger [Logger] Logger instance
|
|
100
|
+
# @param telemetry [Core::Telemetry::Component, nil] Telemetry component for error reporting
|
|
101
|
+
# @param di_active [Proc, nil] Predicate returning whether Dynamic Instrumentation is currently active
|
|
102
|
+
def initialize(settings, agent_settings, logger, telemetry: nil, di_active: nil)
|
|
103
|
+
@settings = settings
|
|
104
|
+
@agent_settings = agent_settings
|
|
105
|
+
@logger = logger
|
|
106
|
+
@telemetry = telemetry
|
|
107
|
+
@di_active = di_active
|
|
108
|
+
|
|
109
|
+
@extractor = Extractor.new(logger: logger, settings: settings)
|
|
110
|
+
@uploader = Uploader.new(settings: settings, agent_settings: agent_settings, logger: logger, telemetry: telemetry)
|
|
111
|
+
@scope_batcher = ScopeBatcher.new(@uploader, logger: logger)
|
|
112
|
+
|
|
113
|
+
@last_upload_time = nil
|
|
114
|
+
@last_upload_scope_count = nil
|
|
115
|
+
@mutex = Mutex.new
|
|
116
|
+
@upload_in_progress = false
|
|
117
|
+
@upload_in_progress_cv = ConditionVariable.new
|
|
118
|
+
@shutdown = false
|
|
119
|
+
# PID at construction time. Compared against Process.pid in shutdown!
|
|
120
|
+
# to detect forked-child callers, whose inherited @upload_in_progress
|
|
121
|
+
# snapshot is stale: the scheduler thread that would clear it lives
|
|
122
|
+
# only in the parent. See shutdown! for details.
|
|
123
|
+
@owner_pid = Process.pid
|
|
124
|
+
|
|
125
|
+
# Signalled when @last_upload_time advances. wait_for_idle blocks on this
|
|
126
|
+
# so short-lived scripts that trigger an upload can wait for an upload
|
|
127
|
+
# attempt to complete without depending on a one-shot flag.
|
|
128
|
+
@last_upload_time_cv = ConditionVariable.new
|
|
129
|
+
|
|
130
|
+
# Per-instance scheduler state. The scheduler thread is started lazily
|
|
131
|
+
# on the first start_upload call.
|
|
132
|
+
@scheduler_mutex = Mutex.new
|
|
133
|
+
@scheduler_cv = ConditionVariable.new
|
|
134
|
+
@scheduled_at = nil
|
|
135
|
+
@scheduler_signaled = false
|
|
136
|
+
@scheduler_thread = nil
|
|
137
|
+
|
|
138
|
+
# Hot-load coverage state. TracePoint :class hook is installed lazily on
|
|
139
|
+
# the first start_upload call; classes defined after that point are
|
|
140
|
+
# enqueued here and drained by the scheduler on debounce. Distinguishes
|
|
141
|
+
# initial extraction (extract_all) from incremental (per-module extract).
|
|
142
|
+
@hot_load_buffer = []
|
|
143
|
+
@hot_load_buffer_mutex = Mutex.new
|
|
144
|
+
@hot_load_tracepoint = nil
|
|
145
|
+
@initial_extraction_done = false
|
|
146
|
+
|
|
147
|
+
# Sticky record of "remote config (or force mode) wants symbols
|
|
148
|
+
# uploaded", independent of whether DI is currently active. Set when an
|
|
149
|
+
# upload is requested and either allowed or deferred by the DI gate;
|
|
150
|
+
# cleared only when RC explicitly disables uploads (stop_upload). It
|
|
151
|
+
# survives stop_for_di_disable's scheduler teardown, so
|
|
152
|
+
# resume_pending_upload can restart uploads after a DI disable->re-enable
|
|
153
|
+
# cycle even though RC does not re-dispatch the unchanged symbol-database
|
|
154
|
+
# config.
|
|
155
|
+
@upload_requested = false
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Schedule a deferred upload that waits for app boot to complete.
|
|
159
|
+
#
|
|
160
|
+
# In Rails: registers ActiveSupport.on_load(:after_initialize). When the
|
|
161
|
+
# hook has already fired (e.g., this Component was built by a reconfigure
|
|
162
|
+
# after Rails finished initializing), the callback runs immediately.
|
|
163
|
+
#
|
|
164
|
+
# In non-Rails: triggers start_upload immediately.
|
|
165
|
+
#
|
|
166
|
+
# Each Component registers its own callback. Old Components that have
|
|
167
|
+
# been shut down short-circuit in start_upload via @shutdown. The hot-load
|
|
168
|
+
# hook handles classes loaded after this initial trigger, so under
|
|
169
|
+
# eager_load=false an under-extracted initial upload self-corrects as the
|
|
170
|
+
# app exercises code.
|
|
171
|
+
#
|
|
172
|
+
# @return [void]
|
|
173
|
+
def schedule_deferred_upload
|
|
174
|
+
if defined?(::ActiveSupport) && defined?(::Rails::Railtie)
|
|
175
|
+
# Capture self — on_load runs the block via instance_exec on the
|
|
176
|
+
# loaded object (Rails::Application), so a bare `start_upload`
|
|
177
|
+
# would resolve against it.
|
|
178
|
+
component = self
|
|
179
|
+
::ActiveSupport.on_load(:after_initialize) do
|
|
180
|
+
component.start_upload
|
|
181
|
+
end
|
|
182
|
+
else
|
|
183
|
+
start_upload
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Whether this component has been shut down.
|
|
188
|
+
# @return [Boolean]
|
|
189
|
+
def shutdown?
|
|
190
|
+
@scheduler_mutex.synchronize { @shutdown }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Schedule symbol upload (triggered by remote config or force mode).
|
|
194
|
+
# The actual extraction is debounced by EXTRACT_DEBOUNCE_INTERVAL seconds —
|
|
195
|
+
# subsequent calls within the window restart the timer.
|
|
196
|
+
# Thread-safe: can be called concurrently from multiple remote config updates.
|
|
197
|
+
# @return [void]
|
|
198
|
+
def start_upload
|
|
199
|
+
@scheduler_mutex.synchronize do
|
|
200
|
+
return if @shutdown
|
|
201
|
+
|
|
202
|
+
unless upload_allowed?
|
|
203
|
+
if deferred_by_di_gate?
|
|
204
|
+
# nil-default case: Symbol Database mirrors Dynamic Instrumentation
|
|
205
|
+
# and DI is not active. Record the desire and defer; resume_pending_upload
|
|
206
|
+
# re-attempts when DI is enabled. Without this gate the tracer would
|
|
207
|
+
# extract and upload symbols for applications that never enabled DI.
|
|
208
|
+
@upload_requested = true
|
|
209
|
+
@logger.debug("symdb: upload requested but Dynamic Instrumentation is not active; deferring until DI is enabled")
|
|
210
|
+
else
|
|
211
|
+
# Explicit symbol_database.enabled = false: the feature is disabled,
|
|
212
|
+
# not merely waiting on DI. Clear the desire so resume_pending_upload
|
|
213
|
+
# does not retry a disabled feature.
|
|
214
|
+
@upload_requested = false
|
|
215
|
+
@logger.debug("symdb: upload requested but symbol database upload is disabled; skipping")
|
|
216
|
+
end
|
|
217
|
+
return
|
|
218
|
+
end
|
|
219
|
+
@upload_requested = true
|
|
220
|
+
|
|
221
|
+
if @owner_pid != Process.pid
|
|
222
|
+
# Forked child: claim ownership and clear inherited
|
|
223
|
+
# @upload_in_progress. The inherited flag was the parent's
|
|
224
|
+
# snapshot; the parent's scheduler thread does not exist in this
|
|
225
|
+
# process. Any upload starting now is child-owned and must be
|
|
226
|
+
# waited on in shutdown! via the PID-match branch.
|
|
227
|
+
@owner_pid = Process.pid
|
|
228
|
+
@mutex.synchronize { @upload_in_progress = false }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
install_hot_load_hook
|
|
232
|
+
@scheduled_at = Datadog::Core::Utils::Time.get_time + EXTRACT_DEBOUNCE_INTERVAL
|
|
233
|
+
@scheduler_signaled = true
|
|
234
|
+
@scheduler_cv.signal
|
|
235
|
+
ensure_scheduler_thread
|
|
236
|
+
end
|
|
237
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
|
238
|
+
Datadog::DI.reraise_if_fatal(e)
|
|
239
|
+
@logger.debug { "symdb: error scheduling upload: #{e.class}: #{e.message}" }
|
|
240
|
+
@telemetry&.report(e, description: 'symdb: error scheduling upload')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Stop symbol upload in response to remote config sending
|
|
244
|
+
# upload_symbols: false or deleting the config: the customer no longer wants
|
|
245
|
+
# uploads, so clear the sticky @upload_requested desire (a later
|
|
246
|
+
# resume_pending_upload must not restart it) and tear down the scheduler and
|
|
247
|
+
# hot-load hook.
|
|
248
|
+
# Thread-safe: can be called concurrently from multiple remote config updates.
|
|
249
|
+
# @return [void]
|
|
250
|
+
def stop_upload
|
|
251
|
+
@scheduler_mutex.synchronize { @upload_requested = false }
|
|
252
|
+
suspend_scheduling
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Re-attempt a symbol upload that remote config requested but that is not
|
|
256
|
+
# currently running because Dynamic Instrumentation was inactive — either
|
|
257
|
+
# deferred at request time, or suspended by stop_for_di_disable when DI was
|
|
258
|
+
# turned off. Called from the orchestration layer (Tracing::Remote) when DI
|
|
259
|
+
# is enabled via remote configuration (implicit enablement). No-op unless an
|
|
260
|
+
# upload was requested and not since disabled. Mirrors DI's
|
|
261
|
+
# replay_current_probes: RC does not re-dispatch the unchanged
|
|
262
|
+
# symbol-database config on DI re-enable, so the tracer restarts the upload
|
|
263
|
+
# from its own retained desire.
|
|
264
|
+
# @return [void]
|
|
265
|
+
def resume_pending_upload
|
|
266
|
+
requested = @scheduler_mutex.synchronize { @upload_requested }
|
|
267
|
+
start_upload if requested
|
|
268
|
+
nil
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Stop uploading when Dynamic Instrumentation is disabled via remote
|
|
272
|
+
# configuration. Only the nil-default (follows-DI) case stops; an explicit
|
|
273
|
+
# symbol_database.enabled = true and force_upload are independent of DI and
|
|
274
|
+
# keep running. Called from the orchestration layer (Tracing::Remote) so
|
|
275
|
+
# Symbol Database's TracePoint and scheduler don't keep uploading after DI
|
|
276
|
+
# is turned off. No-op if uploads were never started.
|
|
277
|
+
# @return [void]
|
|
278
|
+
def stop_for_di_disable
|
|
279
|
+
return if @settings.symbol_database.internal.force_upload
|
|
280
|
+
return unless @settings.symbol_database.enabled.nil?
|
|
281
|
+
|
|
282
|
+
# Suspend, don't stop: preserve @upload_requested so resume_pending_upload
|
|
283
|
+
# restarts the upload when DI is re-enabled and RC never re-sends the
|
|
284
|
+
# (unchanged) symbol-database config.
|
|
285
|
+
suspend_scheduling
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Block until this Component finishes an extract+upload after this call,
|
|
289
|
+
# or until the timeout elapses. Used by short-lived scripts that trigger
|
|
290
|
+
# an upload via force_upload and need to wait before exiting.
|
|
291
|
+
# Tracks @last_upload_time advance — returns true once any upload attempt
|
|
292
|
+
# completes (success or failure), false on timeout.
|
|
293
|
+
# @param timeout [Numeric] Maximum seconds to wait
|
|
294
|
+
# @return [Boolean] true if an upload completed; false on timeout
|
|
295
|
+
def wait_for_idle(timeout: 30)
|
|
296
|
+
deadline = Datadog::Core::Utils::Time.get_time + timeout
|
|
297
|
+
@mutex.synchronize do
|
|
298
|
+
start_time = @last_upload_time
|
|
299
|
+
while @last_upload_time == start_time
|
|
300
|
+
remaining = deadline - Datadog::Core::Utils::Time.get_time
|
|
301
|
+
return false if remaining <= 0
|
|
302
|
+
@last_upload_time_cv.wait(@mutex, remaining)
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
true
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Shutdown component and cleanup resources.
|
|
309
|
+
# Disables the hot-load TracePoint so no events queue for a dead
|
|
310
|
+
# scheduler. Cancels the per-instance scheduler so any pending debounced
|
|
311
|
+
# extraction is dropped. Waits for an in-flight extraction to complete
|
|
312
|
+
# before returning. Does not touch any sibling Components, so a sibling
|
|
313
|
+
# Component built after shutdown can still upload.
|
|
314
|
+
# The TracePoint teardown sits inside the same @scheduler_mutex critical
|
|
315
|
+
# section as the @shutdown flag flip, so it is atomic against a concurrent
|
|
316
|
+
# start_upload (which installs the TracePoint under @scheduler_mutex). Without
|
|
317
|
+
# that, a shutdown interleaved with a start could leave an enabled TracePoint
|
|
318
|
+
# rooted by the VM — class loads would keep growing @hot_load_buffer for the
|
|
319
|
+
# rest of the process lifetime (enqueue_hot_load's @shutdown check skips
|
|
320
|
+
# re-scheduling but only after the buffer push).
|
|
321
|
+
# @return [void]
|
|
322
|
+
def shutdown!
|
|
323
|
+
@scheduler_mutex.synchronize do
|
|
324
|
+
@hot_load_tracepoint&.disable
|
|
325
|
+
@hot_load_tracepoint = nil
|
|
326
|
+
@shutdown = true
|
|
327
|
+
@scheduler_signaled = true
|
|
328
|
+
@scheduler_cv.signal
|
|
329
|
+
end
|
|
330
|
+
@scheduler_thread&.join(5)
|
|
331
|
+
@scheduler_thread = nil
|
|
332
|
+
|
|
333
|
+
@mutex.synchronize do
|
|
334
|
+
if @upload_in_progress
|
|
335
|
+
if Process.pid == @owner_pid
|
|
336
|
+
@upload_in_progress_cv.wait(@mutex, 5)
|
|
337
|
+
else
|
|
338
|
+
# We are in a forked child that inherited this Component but
|
|
339
|
+
# never called start_upload here. The scheduler thread (the
|
|
340
|
+
# only writer that clears @upload_in_progress and signals the
|
|
341
|
+
# cv) lives only in the parent — fork carries only the calling
|
|
342
|
+
# thread, so nothing in this process can ever signal us.
|
|
343
|
+
# Waiting would burn the full 5s timeout for no benefit. Treat
|
|
344
|
+
# the inherited @upload_in_progress as a stale snapshot and
|
|
345
|
+
# proceed; the parent's shutdown! (running in the parent) is
|
|
346
|
+
# authoritative. Child-owned uploads (where start_upload was
|
|
347
|
+
# called in this process) take the PID-match branch above,
|
|
348
|
+
# because start_upload claims @owner_pid for the current
|
|
349
|
+
# process.
|
|
350
|
+
@upload_in_progress = false
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
@scope_batcher.shutdown
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Reinitialize per-instance state in a forked child process.
|
|
359
|
+
#
|
|
360
|
+
# `Process.fork` copies the parent's memory but only the forking thread
|
|
361
|
+
# survives in the child. Background threads (`@scheduler_thread`) are
|
|
362
|
+
# dead, mutexes and condition variables are copied without owner
|
|
363
|
+
# tracking (orphan-lock risk if the parent held a mutex at the fork
|
|
364
|
+
# instant), and the TracePoint hook is bound to the dead scheduler.
|
|
365
|
+
#
|
|
366
|
+
# State reset (the child does its own initial extraction, then hot-load
|
|
367
|
+
# continues from there):
|
|
368
|
+
# - Hot-load buffer cleared — the child will rediscover via extract_all.
|
|
369
|
+
# - `@initial_extraction_done = false` — child has not extracted yet.
|
|
370
|
+
# - `@hot_load_tracepoint = nil` — `start_upload` reinstalls a fresh one
|
|
371
|
+
# bound to the child's component.
|
|
372
|
+
# - `@scheduler_thread = nil`, `@scheduled_at = nil`,
|
|
373
|
+
# `@scheduler_signaled = false` — scheduler restarts on next
|
|
374
|
+
# `start_upload`.
|
|
375
|
+
# - `@upload_in_progress = false` — parent may have been mid-upload at
|
|
376
|
+
# the fork instant; the child has no upload in flight.
|
|
377
|
+
# - `@scope_batcher` replaced with a fresh instance. The inherited batcher
|
|
378
|
+
# carries the parent's `@uploaded_modules` set, which `add_scope` uses
|
|
379
|
+
# to dedup by scope name. Without a fresh batcher, the child's
|
|
380
|
+
# re-extraction silently drops every scope whose name the parent
|
|
381
|
+
# already uploaded — under `preload_app!` that's most of the app.
|
|
382
|
+
#
|
|
383
|
+
# Mutex/CV reinit (orphan-lock guard):
|
|
384
|
+
# - `@scheduler_mutex`, `@scheduler_cv`, `@mutex`,
|
|
385
|
+
# `@upload_in_progress_cv`, `@last_upload_time_cv`,
|
|
386
|
+
# `@hot_load_buffer_mutex`.
|
|
387
|
+
#
|
|
388
|
+
# Force-upload mode: the parent's scheduled extraction is dead in the
|
|
389
|
+
# child, so re-register the deferred-upload callback. In Rails the
|
|
390
|
+
# `:after_initialize` hook has already fired (initialization happened
|
|
391
|
+
# in the parent), so the on_load block runs immediately and the child
|
|
392
|
+
# schedules its own upload. In non-Rails, this calls `start_upload`
|
|
393
|
+
# directly.
|
|
394
|
+
#
|
|
395
|
+
# Cross-process upload deduplication is intentionally not handled here.
|
|
396
|
+
# Each forked Component does its own initial extraction. Workers in
|
|
397
|
+
# `preload_app! + eager_load=true` deployments hold identical code to
|
|
398
|
+
# the parent — backend dedup of identical-content uploads is the
|
|
399
|
+
# backend's responsibility, not the tracer's.
|
|
400
|
+
#
|
|
401
|
+
# @return [void]
|
|
402
|
+
def after_fork!
|
|
403
|
+
# Disable the inherited TracePoint before dropping the reference: fork
|
|
404
|
+
# copies the enabled TP into the child, where it remains rooted by the
|
|
405
|
+
# VM. Without an explicit disable, every subsequent class load in the
|
|
406
|
+
# child would enqueue through the inherited hook in addition to the
|
|
407
|
+
# fresh hook that start_upload installs.
|
|
408
|
+
@hot_load_tracepoint&.disable
|
|
409
|
+
@hot_load_buffer = []
|
|
410
|
+
@hot_load_buffer_mutex = Mutex.new
|
|
411
|
+
@hot_load_tracepoint = nil
|
|
412
|
+
@initial_extraction_done = false
|
|
413
|
+
|
|
414
|
+
@scheduler_mutex = Mutex.new
|
|
415
|
+
@scheduler_cv = ConditionVariable.new
|
|
416
|
+
@scheduled_at = nil
|
|
417
|
+
@scheduler_signaled = false
|
|
418
|
+
@scheduler_thread = nil
|
|
419
|
+
|
|
420
|
+
@mutex = Mutex.new
|
|
421
|
+
@upload_in_progress = false
|
|
422
|
+
@upload_in_progress_cv = ConditionVariable.new
|
|
423
|
+
@last_upload_time_cv = ConditionVariable.new
|
|
424
|
+
|
|
425
|
+
# Fresh ScopeBatcher: the inherited one carries the parent's
|
|
426
|
+
# @uploaded_modules set, against which add_scope dedups by name.
|
|
427
|
+
@scope_batcher = ScopeBatcher.new(@uploader, logger: @logger)
|
|
428
|
+
|
|
429
|
+
schedule_deferred_upload if @settings.symbol_database.internal.force_upload
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
private
|
|
433
|
+
|
|
434
|
+
# Tear down the scheduler and hot-load hook without clearing the sticky
|
|
435
|
+
# @upload_requested desire, so resume_pending_upload can restart uploads
|
|
436
|
+
# that RC still wants. Disables the TracePoint :class hook so post-stop
|
|
437
|
+
# class loads don't re-arm the scheduler, clears the hot-load buffer, and
|
|
438
|
+
# resets @initial_extraction_done so a future resume performs a fresh
|
|
439
|
+
# extract_all instead of draining an empty buffer.
|
|
440
|
+
# The TracePoint teardown sits inside the same @scheduler_mutex critical
|
|
441
|
+
# section as the @scheduled_at reset, so it is atomic against a concurrent
|
|
442
|
+
# start_upload (which installs the TracePoint under @scheduler_mutex). Without
|
|
443
|
+
# that, a stop interleaved with a start could leave an enabled TracePoint
|
|
444
|
+
# rooted by the VM after this returned.
|
|
445
|
+
# @return [void]
|
|
446
|
+
def suspend_scheduling
|
|
447
|
+
@scheduler_mutex.synchronize do
|
|
448
|
+
@hot_load_tracepoint&.disable
|
|
449
|
+
@hot_load_tracepoint = nil
|
|
450
|
+
@scheduled_at = nil
|
|
451
|
+
@scheduler_signaled = true
|
|
452
|
+
@scheduler_cv.signal
|
|
453
|
+
end
|
|
454
|
+
@hot_load_buffer_mutex.synchronize { @hot_load_buffer.clear }
|
|
455
|
+
@initial_extraction_done = false
|
|
456
|
+
nil
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# Whether a remote-config-triggered upload may proceed now.
|
|
460
|
+
#
|
|
461
|
+
# force_upload and an explicit `symbol_database.enabled = true` both mean
|
|
462
|
+
# "upload regardless of Dynamic Instrumentation". Only the nil-default case
|
|
463
|
+
# — where Symbol Database mirrors DI — is gated on DI actually being active,
|
|
464
|
+
# so the tracer never extracts symbols for an application that never
|
|
465
|
+
# enabled Dynamic Instrumentation.
|
|
466
|
+
# @return [bool]
|
|
467
|
+
def upload_allowed?
|
|
468
|
+
return true if @settings.symbol_database.internal.force_upload
|
|
469
|
+
|
|
470
|
+
case @settings.symbol_database.enabled
|
|
471
|
+
when true then true
|
|
472
|
+
when false then false
|
|
473
|
+
# steep:ignore NoMethod — Steep does not narrow @di_active to non-nil after the .nil? check
|
|
474
|
+
else @di_active.nil? || @di_active.call # steep:ignore NoMethod
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# Whether upload is currently blocked specifically by the nil-default
|
|
479
|
+
# DI-active gate — the only case that defers and retries via
|
|
480
|
+
# resume_pending_upload. An explicit symbol_database.enabled = false is a
|
|
481
|
+
# disabled feature, not a deferral, so it clears @upload_requested and is
|
|
482
|
+
# not retried. force_upload and explicit true are never gated, so they are
|
|
483
|
+
# never deferred.
|
|
484
|
+
# @return [bool]
|
|
485
|
+
def deferred_by_di_gate?
|
|
486
|
+
return false if @settings.symbol_database.internal.force_upload
|
|
487
|
+
return false unless @settings.symbol_database.enabled.nil?
|
|
488
|
+
|
|
489
|
+
# After the guards above, upload_allowed? reduces to the DI-active gate,
|
|
490
|
+
# so a disallowed upload here is precisely a DI-gate deferral.
|
|
491
|
+
!upload_allowed?
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
# Check whether the runtime environment supports symbol database upload,
|
|
495
|
+
# logging the reason when it does not.
|
|
496
|
+
# @param logger [Logger]
|
|
497
|
+
# @return [Boolean]
|
|
498
|
+
def self.environment_supported?(logger)
|
|
499
|
+
return true if SymbolDatabase.supported_runtime?
|
|
500
|
+
|
|
501
|
+
if RUBY_ENGINE != 'ruby'
|
|
502
|
+
logger.debug { "symdb: not supported on #{RUBY_ENGINE}, skipping" }
|
|
503
|
+
else
|
|
504
|
+
logger.debug { "symdb: requires Ruby 2.7+, running #{RUBY_VERSION}, skipping" }
|
|
505
|
+
end
|
|
506
|
+
false
|
|
507
|
+
end
|
|
508
|
+
private_class_method :environment_supported?
|
|
509
|
+
|
|
510
|
+
# Start the scheduler thread if not already running.
|
|
511
|
+
# Must be called from within @scheduler_mutex.synchronize.
|
|
512
|
+
# @return [void]
|
|
513
|
+
def ensure_scheduler_thread
|
|
514
|
+
return if @scheduler_thread&.alive?
|
|
515
|
+
@scheduler_thread = Thread.new { scheduler_loop }
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
# Scheduler thread main loop. Waits for the debounce window to elapse,
|
|
519
|
+
# then runs extract_and_upload. Loops indefinitely so that hot-load
|
|
520
|
+
# signals fired after the initial upload trigger subsequent incremental
|
|
521
|
+
# uploads.
|
|
522
|
+
# @return [void]
|
|
523
|
+
def scheduler_loop
|
|
524
|
+
loop do
|
|
525
|
+
# should_fire = true means the debounce deadline elapsed without further
|
|
526
|
+
# signals; extract_and_upload runs once after the mutex is released.
|
|
527
|
+
should_fire = false
|
|
528
|
+
|
|
529
|
+
@scheduler_mutex.synchronize do
|
|
530
|
+
return if @shutdown
|
|
531
|
+
|
|
532
|
+
# Copy to local so Steep narrows `Float?` to `Float` in the else branch.
|
|
533
|
+
# Steep does not track narrowing on instance variables across nil checks.
|
|
534
|
+
scheduled_at = @scheduled_at
|
|
535
|
+
if scheduled_at.nil?
|
|
536
|
+
# Nothing scheduled (e.g. stop_upload cleared it, or no hot-load
|
|
537
|
+
# events since the last upload). Wait indefinitely for a signal,
|
|
538
|
+
# then re-evaluate on next loop.
|
|
539
|
+
@scheduler_signaled = false
|
|
540
|
+
@scheduler_cv.wait(@scheduler_mutex)
|
|
541
|
+
else
|
|
542
|
+
remaining = scheduled_at - Datadog::Core::Utils::Time.get_time
|
|
543
|
+
if remaining > 0
|
|
544
|
+
# Wait until the debounce deadline. Any signal (start_upload,
|
|
545
|
+
# stop_upload, shutdown!, hot-load event) wakes us early; we
|
|
546
|
+
# always re-loop and recompute rather than firing immediately
|
|
547
|
+
# on wake.
|
|
548
|
+
@scheduler_signaled = false
|
|
549
|
+
@scheduler_cv.wait(@scheduler_mutex, remaining)
|
|
550
|
+
else
|
|
551
|
+
# Deadline elapsed without further signal — fire after releasing
|
|
552
|
+
# the mutex. Clear @scheduled_at so the next loop iteration
|
|
553
|
+
# waits for the next start_upload or hot-load signal.
|
|
554
|
+
should_fire = true
|
|
555
|
+
@scheduled_at = nil
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
# `next` inside `synchronize` only exits the synchronize block — not the
|
|
561
|
+
# surrounding loop. Use an explicit flag so the loop only fires
|
|
562
|
+
# extract_and_upload when the debounce deadline has actually elapsed.
|
|
563
|
+
next unless should_fire
|
|
564
|
+
|
|
565
|
+
# Outside the mutex.
|
|
566
|
+
return if @shutdown
|
|
567
|
+
|
|
568
|
+
extract_and_upload
|
|
569
|
+
end
|
|
570
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
|
571
|
+
Datadog::DI.reraise_if_fatal(e)
|
|
572
|
+
@logger.debug { "symdb: scheduler error: #{e.class}: #{e.message}" }
|
|
573
|
+
@telemetry&.report(e, description: 'symdb: scheduler error')
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
# Extract symbols and upload. First call runs extract_all (full ObjectSpace
|
|
577
|
+
# walk); subsequent calls drain the hot-load buffer and extract just the
|
|
578
|
+
# newly-loaded modules via Extractor#extract.
|
|
579
|
+
# @return [void]
|
|
580
|
+
def extract_and_upload
|
|
581
|
+
@mutex.synchronize { @upload_in_progress = true }
|
|
582
|
+
|
|
583
|
+
begin
|
|
584
|
+
@logger.trace { "symdb: starting extraction and upload" }
|
|
585
|
+
start_time = Datadog::Core::Utils::Time.get_time
|
|
586
|
+
|
|
587
|
+
extracted_count = 0
|
|
588
|
+
targetable_count = 0
|
|
589
|
+
consume = lambda do |scope|
|
|
590
|
+
@scope_batcher.add_scope(scope)
|
|
591
|
+
extracted_count += 1
|
|
592
|
+
targetable_count += count_targetable_methods_in_scope(scope)
|
|
593
|
+
log_scope_tree(scope, 0)
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
if @initial_extraction_done
|
|
597
|
+
extract_hot_load_buffer.each(&consume)
|
|
598
|
+
mode_label = "hot-load"
|
|
599
|
+
else
|
|
600
|
+
# Discard any TracePoint events captured between hook install and
|
|
601
|
+
# this initial scan — extract_all walks ObjectSpace which already
|
|
602
|
+
# covers everything loaded at this moment. Anything loaded during
|
|
603
|
+
# or after extract_all stays buffered for the next drain.
|
|
604
|
+
@hot_load_buffer_mutex.synchronize { @hot_load_buffer.clear }
|
|
605
|
+
# Stream form of extract_all yields one FILE scope at a time and frees
|
|
606
|
+
# the per-file intermediate tree as it goes — the full Array<Scope> is
|
|
607
|
+
# never materialized, keeping peak memory bounded for large workspaces.
|
|
608
|
+
@extractor.extract_all(&consume)
|
|
609
|
+
@initial_extraction_done = true
|
|
610
|
+
mode_label = "initial"
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
extraction_duration = Datadog::Core::Utils::Time.get_time - start_time
|
|
614
|
+
@logger.debug { "symdb: #{mode_label} extracted #{extracted_count} scopes (#{targetable_count} methods with targetable lines) in #{'%.2f' % extraction_duration}s" }
|
|
615
|
+
|
|
616
|
+
# Flush any remaining scopes (triggers upload)
|
|
617
|
+
@scope_batcher.flush
|
|
618
|
+
|
|
619
|
+
@mutex.synchronize do
|
|
620
|
+
@last_upload_time = Datadog::Core::Utils::Time.now
|
|
621
|
+
@last_upload_scope_count = extracted_count
|
|
622
|
+
@last_upload_time_cv.broadcast
|
|
623
|
+
end
|
|
624
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
|
625
|
+
Datadog::DI.reraise_if_fatal(e)
|
|
626
|
+
@logger.debug { "symdb: extraction error: #{e.class}: #{e.message}" }
|
|
627
|
+
@telemetry&.report(e, description: 'symdb: extraction error')
|
|
628
|
+
@mutex.synchronize do
|
|
629
|
+
@last_upload_time = Datadog::Core::Utils::Time.now
|
|
630
|
+
@last_upload_time_cv.broadcast
|
|
631
|
+
end
|
|
632
|
+
ensure
|
|
633
|
+
@mutex.synchronize do
|
|
634
|
+
@upload_in_progress = false
|
|
635
|
+
@upload_in_progress_cv.signal
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
# Drain the hot-load buffer, dedup by object_id, return the array of
|
|
641
|
+
# FILE scopes from per-module extraction.
|
|
642
|
+
# @return [Array<Scope>]
|
|
643
|
+
def extract_hot_load_buffer
|
|
644
|
+
modules = @hot_load_buffer_mutex.synchronize { @hot_load_buffer.shift(@hot_load_buffer.length) }
|
|
645
|
+
return [] if modules.empty?
|
|
646
|
+
|
|
647
|
+
seen = {}
|
|
648
|
+
modules.each { |mod| seen[mod.object_id] = mod }
|
|
649
|
+
seen.values.map { |mod| @extractor.extract(mod) }.compact
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
# Install the TracePoint :class hook (lazy — only on first start_upload).
|
|
653
|
+
# Hook fires for every class/module body open including reopens; pushes
|
|
654
|
+
# the module onto @hot_load_buffer and signals the scheduler. Singleton
|
|
655
|
+
# classes are filtered for the same reason as in Extractor#extract_all.
|
|
656
|
+
# Must be called from within @scheduler_mutex.synchronize.
|
|
657
|
+
# @return [void]
|
|
658
|
+
def install_hot_load_hook
|
|
659
|
+
return if @hot_load_tracepoint
|
|
660
|
+
component = self
|
|
661
|
+
logger = @logger
|
|
662
|
+
telemetry = @telemetry
|
|
663
|
+
@hot_load_tracepoint = TracePoint.new(:class) do |tp|
|
|
664
|
+
# The :class TracePoint fires inside the customer's class body —
|
|
665
|
+
# any exception that escapes this block surfaces at the customer's
|
|
666
|
+
# `class Foo; ... end` line and breaks their class load. The
|
|
667
|
+
# MODULE_SINGLETON_CLASS_PRED dispatch defends against one specific
|
|
668
|
+
# raise source (user-overridden singleton_class?); this rescue
|
|
669
|
+
# closes the general case. Verified: a raise inside the callback
|
|
670
|
+
# backtraces through `<class:CustomerClass>` in Ruby 3.x.
|
|
671
|
+
|
|
672
|
+
mod = tp.self
|
|
673
|
+
next if MODULE_SINGLETON_CLASS_PRED.bind(mod).call
|
|
674
|
+
component.send(:enqueue_hot_load, mod)
|
|
675
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
|
676
|
+
Datadog::DI.reraise_if_fatal(e)
|
|
677
|
+
# Logger or telemetry can themselves raise (custom logger
|
|
678
|
+
# implementation, telemetry worker in an unexpected state). The
|
|
679
|
+
# :class TracePoint fires inside customer class bodies, so the
|
|
680
|
+
# error boundary must hold even when error reporting fails;
|
|
681
|
+
# nothing useful to do if logging is broken.
|
|
682
|
+
begin
|
|
683
|
+
logger.debug { "symdb: hot-load hook error: #{e.class}: #{e.message}" }
|
|
684
|
+
telemetry&.report(e, description: 'symdb: hot-load hook error')
|
|
685
|
+
rescue Exception => report_exc # standard:disable Lint/RescueException
|
|
686
|
+
Datadog::DI.reraise_if_fatal(report_exc)
|
|
687
|
+
nil
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
@hot_load_tracepoint.enable # steep:ignore NoMethod
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
# Enqueue a hot-loaded module and signal the scheduler.
|
|
694
|
+
# Called from the TracePoint :class block — must be cheap.
|
|
695
|
+
# @param mod [Module]
|
|
696
|
+
# @return [void]
|
|
697
|
+
def enqueue_hot_load(mod)
|
|
698
|
+
@hot_load_buffer_mutex.synchronize { @hot_load_buffer << mod }
|
|
699
|
+
@scheduler_mutex.synchronize do
|
|
700
|
+
return if @shutdown
|
|
701
|
+
# TracePoint#disable does not wait for in-flight callbacks: a :class
|
|
702
|
+
# event firing concurrently with stop_upload can reach here after the
|
|
703
|
+
# hook has been torn down. Without this guard the stale event would
|
|
704
|
+
# re-arm the scheduler, contradicting stop_upload's contract. The
|
|
705
|
+
# buffer push above is harmless — the next start_upload runs
|
|
706
|
+
# extract_all, which clears the buffer before extracting.
|
|
707
|
+
return unless @hot_load_tracepoint
|
|
708
|
+
@scheduled_at = Datadog::Core::Utils::Time.get_time + EXTRACT_DEBOUNCE_INTERVAL
|
|
709
|
+
@scheduler_signaled = true
|
|
710
|
+
@scheduler_cv.signal
|
|
711
|
+
end
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
def log_scope_tree(scope, depth)
|
|
715
|
+
indent = ' ' * depth
|
|
716
|
+
@logger.trace { "symdb: #{indent}#{scope.scope_type} #{scope.name}" }
|
|
717
|
+
scope.scopes&.each { |child| log_scope_tree(child, depth + 1) }
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
# Count METHOD scopes with targetable lines inside one FILE scope. Used by
|
|
721
|
+
# extract_and_upload to accumulate the count while streaming, without
|
|
722
|
+
# retaining the Array<Scope> just to compute the total at the end.
|
|
723
|
+
def count_targetable_methods_in_scope(file_scope)
|
|
724
|
+
count = 0
|
|
725
|
+
file_scope.scopes&.each do |class_or_module|
|
|
726
|
+
class_or_module.scopes&.each do |method_scope|
|
|
727
|
+
count += 1 if method_scope.scope_type == 'METHOD' && method_scope.targetable_lines?
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
count
|
|
731
|
+
end
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
end
|