cw-datadog 2.23.0.2
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 +7 -0
- data/CHANGELOG.md +5142 -0
- data/LICENSE +6 -0
- data/LICENSE-3rdparty.csv +7 -0
- data/LICENSE.Apache +200 -0
- data/LICENSE.BSD3 +24 -0
- data/NOTICE +4 -0
- data/README.md +24 -0
- data/bin/ddprofrb +15 -0
- data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +156 -0
- data/ext/datadog_profiling_native_extension/clock_id.h +23 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +55 -0
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +21 -0
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +1423 -0
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +447 -0
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +131 -0
- data/ext/datadog_profiling_native_extension/collectors_dynamic_sampling_rate.c +150 -0
- data/ext/datadog_profiling_native_extension/collectors_dynamic_sampling_rate.h +18 -0
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
- data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +248 -0
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +3 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +659 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.h +44 -0
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +2221 -0
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +31 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +80 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +63 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +321 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +52 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +67 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +998 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.h +177 -0
- data/ext/datadog_profiling_native_extension/helpers.h +12 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +280 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +84 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +28 -0
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +244 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +881 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +81 -0
- data/ext/datadog_profiling_native_extension/profiling.c +284 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +235 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +88 -0
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +115 -0
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +12 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +1145 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.h +31 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +38 -0
- data/ext/datadog_profiling_native_extension/time_helpers.h +56 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +125 -0
- data/ext/libdatadog_api/crashtracker.h +5 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +80 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +63 -0
- data/ext/libdatadog_api/ddsketch.c +106 -0
- data/ext/libdatadog_api/extconf.rb +110 -0
- data/ext/libdatadog_api/init.c +18 -0
- data/ext/libdatadog_api/library_config.c +172 -0
- data/ext/libdatadog_api/library_config.h +25 -0
- data/ext/libdatadog_api/process_discovery.c +118 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +140 -0
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
- data/lib/datadog/appsec/actions_handler.rb +49 -0
- data/lib/datadog/appsec/anonymizer.rb +16 -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 +59 -0
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -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 +77 -0
- data/lib/datadog/appsec/api_security/sampler.rb +60 -0
- data/lib/datadog/appsec/api_security.rb +23 -0
- data/lib/datadog/appsec/assets/blocked.html +99 -0
- data/lib/datadog/appsec/assets/blocked.json +1 -0
- data/lib/datadog/appsec/assets/blocked.text +5 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +46 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +10504 -0
- data/lib/datadog/appsec/assets/waf_rules/strict.json +3066 -0
- data/lib/datadog/appsec/assets.rb +46 -0
- data/lib/datadog/appsec/autoload.rb +13 -0
- data/lib/datadog/appsec/component.rb +89 -0
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +409 -0
- data/lib/datadog/appsec/configuration.rb +11 -0
- data/lib/datadog/appsec/context.rb +97 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +94 -0
- data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +101 -0
- data/lib/datadog/appsec/contrib/auto_instrument.rb +25 -0
- data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
- data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
- data/lib/datadog/appsec/contrib/devise/ext.rb +35 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +63 -0
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +103 -0
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +70 -0
- data/lib/datadog/appsec/contrib/devise/patches/skip_signin_tracking_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
- data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +42 -0
- data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
- data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
- data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +29 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +56 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +34 -0
- data/lib/datadog/appsec/contrib/integration.rb +37 -0
- data/lib/datadog/appsec/contrib/rack/ext.rb +47 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +101 -0
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +30 -0
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +141 -0
- data/lib/datadog/appsec/contrib/rack/integration.rb +44 -0
- data/lib/datadog/appsec/contrib/rack/patcher.rb +31 -0
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +43 -0
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +218 -0
- data/lib/datadog/appsec/contrib/rails/ext.rb +13 -0
- data/lib/datadog/appsec/contrib/rails/framework.rb +16 -0
- data/lib/datadog/appsec/contrib/rails/gateway/request.rb +67 -0
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +78 -0
- data/lib/datadog/appsec/contrib/rails/integration.rb +43 -0
- data/lib/datadog/appsec/contrib/rails/patcher.rb +171 -0
- data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +27 -0
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
- data/lib/datadog/appsec/contrib/rails/request.rb +36 -0
- data/lib/datadog/appsec/contrib/rails/request_middleware.rb +20 -0
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
- data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +39 -0
- data/lib/datadog/appsec/contrib/sinatra/framework.rb +20 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/request.rb +17 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/route_params.rb +23 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +105 -0
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +43 -0
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +132 -0
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
- data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +20 -0
- data/lib/datadog/appsec/event.rb +139 -0
- data/lib/datadog/appsec/ext.rb +23 -0
- data/lib/datadog/appsec/extensions.rb +16 -0
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +43 -0
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
- data/lib/datadog/appsec/instrumentation/gateway.rb +59 -0
- data/lib/datadog/appsec/instrumentation.rb +9 -0
- data/lib/datadog/appsec/metrics/collector.rb +58 -0
- data/lib/datadog/appsec/metrics/exporter.rb +35 -0
- data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +29 -0
- data/lib/datadog/appsec/metrics.rb +14 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +85 -0
- data/lib/datadog/appsec/monitor.rb +11 -0
- data/lib/datadog/appsec/processor/rule_loader.rb +119 -0
- data/lib/datadog/appsec/rate_limiter.rb +45 -0
- data/lib/datadog/appsec/remote.rb +119 -0
- data/lib/datadog/appsec/response.rb +99 -0
- data/lib/datadog/appsec/sample_rate.rb +21 -0
- data/lib/datadog/appsec/security_engine/engine.rb +176 -0
- data/lib/datadog/appsec/security_engine/result.rb +102 -0
- data/lib/datadog/appsec/security_engine/runner.rb +111 -0
- data/lib/datadog/appsec/security_engine.rb +9 -0
- data/lib/datadog/appsec/security_event.rb +37 -0
- data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
- data/lib/datadog/appsec/trace_keeper.rb +24 -0
- data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
- data/lib/datadog/appsec/utils/http/media_range.rb +201 -0
- data/lib/datadog/appsec/utils/http/media_type.rb +87 -0
- data/lib/datadog/appsec/utils/http.rb +11 -0
- data/lib/datadog/appsec/utils.rb +9 -0
- data/lib/datadog/appsec.rb +65 -0
- data/lib/datadog/auto_instrument.rb +19 -0
- data/lib/datadog/auto_instrument_base.rb +9 -0
- data/lib/datadog/core/buffer/cruby.rb +55 -0
- data/lib/datadog/core/buffer/random.rb +150 -0
- data/lib/datadog/core/buffer/thread_safe.rb +58 -0
- data/lib/datadog/core/chunker.rb +35 -0
- data/lib/datadog/core/cloudwise/IMPLEMENTATION_V2.md +517 -0
- data/lib/datadog/core/cloudwise/QUICKSTART.md +398 -0
- data/lib/datadog/core/cloudwise/README.md +722 -0
- data/lib/datadog/core/cloudwise/app_registration_worker.rb +90 -0
- data/lib/datadog/core/cloudwise/client.rb +490 -0
- data/lib/datadog/core/cloudwise/component.rb +351 -0
- data/lib/datadog/core/cloudwise/heartbeat_worker.rb +137 -0
- data/lib/datadog/core/cloudwise/host_id_worker.rb +85 -0
- data/lib/datadog/core/cloudwise/license_worker.rb +108 -0
- data/lib/datadog/core/cloudwise/probe_state.rb +160 -0
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +339 -0
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/base.rb +91 -0
- data/lib/datadog/core/configuration/components.rb +386 -0
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/config_helper.rb +100 -0
- data/lib/datadog/core/configuration/deprecations.rb +36 -0
- data/lib/datadog/core/configuration/ext.rb +49 -0
- data/lib/datadog/core/configuration/option.rb +368 -0
- data/lib/datadog/core/configuration/option_definition.rb +158 -0
- data/lib/datadog/core/configuration/options.rb +134 -0
- data/lib/datadog/core/configuration/settings.rb +1087 -0
- data/lib/datadog/core/configuration/stable_config.rb +32 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +347 -0
- data/lib/datadog/core/configuration.rb +328 -0
- data/lib/datadog/core/contrib/rails/utils.rb +24 -0
- data/lib/datadog/core/crashtracking/component.rb +105 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +21 -0
- data/lib/datadog/core/ddsketch.rb +19 -0
- data/lib/datadog/core/deprecations.rb +58 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +170 -0
- data/lib/datadog/core/diagnostics/health.rb +19 -0
- data/lib/datadog/core/encoding.rb +90 -0
- data/lib/datadog/core/environment/agent_info.rb +78 -0
- data/lib/datadog/core/environment/cgroup.rb +51 -0
- data/lib/datadog/core/environment/class_count.rb +21 -0
- data/lib/datadog/core/environment/container.rb +89 -0
- data/lib/datadog/core/environment/execution.rb +103 -0
- data/lib/datadog/core/environment/ext.rb +45 -0
- data/lib/datadog/core/environment/gc.rb +20 -0
- data/lib/datadog/core/environment/git.rb +26 -0
- data/lib/datadog/core/environment/identity.rb +84 -0
- data/lib/datadog/core/environment/platform.rb +46 -0
- data/lib/datadog/core/environment/socket.rb +24 -0
- data/lib/datadog/core/environment/thread_count.rb +20 -0
- data/lib/datadog/core/environment/variable_helpers.rb +53 -0
- data/lib/datadog/core/environment/vm_cache.rb +64 -0
- data/lib/datadog/core/environment/yjit.rb +69 -0
- data/lib/datadog/core/error.rb +102 -0
- data/lib/datadog/core/extensions.rb +16 -0
- data/lib/datadog/core/git/ext.rb +16 -0
- data/lib/datadog/core/header_collection.rb +43 -0
- data/lib/datadog/core/logger.rb +45 -0
- data/lib/datadog/core/logging/ext.rb +13 -0
- data/lib/datadog/core/metrics/client.rb +206 -0
- data/lib/datadog/core/metrics/ext.rb +18 -0
- data/lib/datadog/core/metrics/helpers.rb +25 -0
- data/lib/datadog/core/metrics/logging.rb +44 -0
- data/lib/datadog/core/metrics/metric.rb +14 -0
- data/lib/datadog/core/metrics/options.rb +52 -0
- data/lib/datadog/core/pin.rb +71 -0
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
- data/lib/datadog/core/process_discovery.rb +61 -0
- data/lib/datadog/core/rate_limiter.rb +185 -0
- data/lib/datadog/core/remote/client/capabilities.rb +70 -0
- data/lib/datadog/core/remote/client.rb +245 -0
- data/lib/datadog/core/remote/component.rb +161 -0
- data/lib/datadog/core/remote/configuration/content.rb +111 -0
- data/lib/datadog/core/remote/configuration/digest.rb +62 -0
- data/lib/datadog/core/remote/configuration/path.rb +90 -0
- data/lib/datadog/core/remote/configuration/repository.rb +307 -0
- data/lib/datadog/core/remote/configuration/target.rb +74 -0
- data/lib/datadog/core/remote/configuration.rb +18 -0
- data/lib/datadog/core/remote/dispatcher.rb +59 -0
- data/lib/datadog/core/remote/ext.rb +13 -0
- data/lib/datadog/core/remote/negotiation.rb +70 -0
- data/lib/datadog/core/remote/tie/tracing.rb +39 -0
- data/lib/datadog/core/remote/tie.rb +29 -0
- data/lib/datadog/core/remote/transport/config.rb +61 -0
- data/lib/datadog/core/remote/transport/http/api.rb +53 -0
- data/lib/datadog/core/remote/transport/http/client.rb +49 -0
- data/lib/datadog/core/remote/transport/http/config.rb +252 -0
- data/lib/datadog/core/remote/transport/http/negotiation.rb +103 -0
- data/lib/datadog/core/remote/transport/http.rb +83 -0
- data/lib/datadog/core/remote/transport/negotiation.rb +75 -0
- data/lib/datadog/core/remote/worker.rb +105 -0
- data/lib/datadog/core/remote.rb +24 -0
- data/lib/datadog/core/runtime/ext.rb +40 -0
- data/lib/datadog/core/runtime/metrics.rb +202 -0
- data/lib/datadog/core/semaphore.rb +35 -0
- data/lib/datadog/core/tag_builder.rb +52 -0
- data/lib/datadog/core/telemetry/component.rb +206 -0
- data/lib/datadog/core/telemetry/emitter.rb +56 -0
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +287 -0
- data/lib/datadog/core/telemetry/event/base.rb +40 -0
- data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
- data/lib/datadog/core/telemetry/event/log.rb +76 -0
- data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
- data/lib/datadog/core/telemetry/event.rb +37 -0
- data/lib/datadog/core/telemetry/ext.rb +20 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +26 -0
- data/lib/datadog/core/telemetry/logger.rb +52 -0
- data/lib/datadog/core/telemetry/logging.rb +71 -0
- data/lib/datadog/core/telemetry/metric.rb +189 -0
- data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
- data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
- data/lib/datadog/core/telemetry/request.rb +71 -0
- data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
- data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
- data/lib/datadog/core/telemetry/transport/http.rb +63 -0
- data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
- data/lib/datadog/core/telemetry/worker.rb +276 -0
- data/lib/datadog/core/transport/ext.rb +44 -0
- data/lib/datadog/core/transport/http/adapters/net.rb +175 -0
- data/lib/datadog/core/transport/http/adapters/registry.rb +29 -0
- data/lib/datadog/core/transport/http/adapters/test.rb +90 -0
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +83 -0
- data/lib/datadog/core/transport/http/api/endpoint.rb +31 -0
- data/lib/datadog/core/transport/http/api/fallbacks.rb +26 -0
- data/lib/datadog/core/transport/http/api/instance.rb +54 -0
- data/lib/datadog/core/transport/http/api/map.rb +18 -0
- data/lib/datadog/core/transport/http/api/spec.rb +36 -0
- data/lib/datadog/core/transport/http/builder.rb +184 -0
- data/lib/datadog/core/transport/http/env.rb +70 -0
- data/lib/datadog/core/transport/http/response.rb +60 -0
- data/lib/datadog/core/transport/http.rb +75 -0
- data/lib/datadog/core/transport/parcel.rb +22 -0
- data/lib/datadog/core/transport/request.rb +17 -0
- data/lib/datadog/core/transport/response.rb +71 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/base64.rb +22 -0
- data/lib/datadog/core/utils/duration.rb +52 -0
- data/lib/datadog/core/utils/forking.rb +63 -0
- data/lib/datadog/core/utils/hash.rb +79 -0
- data/lib/datadog/core/utils/lru_cache.rb +45 -0
- data/lib/datadog/core/utils/network.rb +142 -0
- data/lib/datadog/core/utils/only_once.rb +42 -0
- data/lib/datadog/core/utils/only_once_successful.rb +87 -0
- data/lib/datadog/core/utils/safe_dup.rb +40 -0
- data/lib/datadog/core/utils/sequence.rb +26 -0
- data/lib/datadog/core/utils/time.rb +84 -0
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/utils/url.rb +25 -0
- data/lib/datadog/core/utils.rb +101 -0
- data/lib/datadog/core/vendor/multipart-post/LICENSE +11 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +118 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +59 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +137 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/version.rb +11 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post.rb +10 -0
- data/lib/datadog/core/vendor/multipart-post/multipart.rb +14 -0
- data/lib/datadog/core/vendor/multipart-post/net/http/post/multipart.rb +34 -0
- data/lib/datadog/core/worker.rb +24 -0
- data/lib/datadog/core/workers/async.rb +202 -0
- data/lib/datadog/core/workers/interval_loop.rb +134 -0
- data/lib/datadog/core/workers/polling.rb +59 -0
- data/lib/datadog/core/workers/queue.rb +44 -0
- data/lib/datadog/core/workers/runtime_metrics.rb +62 -0
- data/lib/datadog/core.rb +38 -0
- data/lib/datadog/data_streams/configuration/settings.rb +49 -0
- data/lib/datadog/data_streams/configuration.rb +11 -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 +509 -0
- data/lib/datadog/data_streams/transport/http/api.rb +33 -0
- data/lib/datadog/data_streams/transport/http/client.rb +49 -0
- data/lib/datadog/data_streams/transport/http/stats.rb +87 -0
- data/lib/datadog/data_streams/transport/http.rb +41 -0
- data/lib/datadog/data_streams/transport/stats.rb +60 -0
- data/lib/datadog/data_streams.rb +100 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/boot.rb +43 -0
- data/lib/datadog/di/code_tracker.rb +204 -0
- data/lib/datadog/di/component.rb +122 -0
- data/lib/datadog/di/configuration/settings.rb +212 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/context.rb +70 -0
- data/lib/datadog/di/contrib/active_record.rb +12 -0
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +28 -0
- data/lib/datadog/di/el/compiler.rb +164 -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 +82 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/instrumenter.rb +566 -0
- data/lib/datadog/di/logger.rb +30 -0
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +231 -0
- data/lib/datadog/di/probe_builder.rb +86 -0
- data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
- data/lib/datadog/di/probe_file_loader.rb +82 -0
- data/lib/datadog/di/probe_manager.rb +261 -0
- data/lib/datadog/di/probe_notification_builder.rb +236 -0
- data/lib/datadog/di/probe_notifier_worker.rb +305 -0
- data/lib/datadog/di/proc_responder.rb +32 -0
- data/lib/datadog/di/redactor.rb +187 -0
- data/lib/datadog/di/remote.rb +145 -0
- data/lib/datadog/di/serializer.rb +422 -0
- data/lib/datadog/di/transport/diagnostics.rb +62 -0
- data/lib/datadog/di/transport/http/api.rb +42 -0
- data/lib/datadog/di/transport/http/client.rb +47 -0
- data/lib/datadog/di/transport/http/diagnostics.rb +65 -0
- data/lib/datadog/di/transport/http/input.rb +77 -0
- data/lib/datadog/di/transport/http.rb +57 -0
- data/lib/datadog/di/transport/input.rb +70 -0
- data/lib/datadog/di/utils.rb +142 -0
- data/lib/datadog/di.rb +36 -0
- data/lib/datadog/error_tracking/collector.rb +87 -0
- data/lib/datadog/error_tracking/component.rb +167 -0
- data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
- data/lib/datadog/error_tracking/configuration.rb +11 -0
- data/lib/datadog/error_tracking/ext.rb +18 -0
- data/lib/datadog/error_tracking/extensions.rb +16 -0
- data/lib/datadog/error_tracking/filters.rb +77 -0
- data/lib/datadog/error_tracking.rb +18 -0
- data/lib/datadog/kit/appsec/events/v2.rb +196 -0
- data/lib/datadog/kit/appsec/events.rb +180 -0
- data/lib/datadog/kit/enable_core_dumps.rb +49 -0
- data/lib/datadog/kit/identity.rb +114 -0
- data/lib/datadog/kit.rb +11 -0
- data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
- data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
- data/lib/datadog/opentelemetry/api/context.rb +208 -0
- data/lib/datadog/opentelemetry/api/trace/span.rb +14 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +37 -0
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +26 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +89 -0
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +169 -0
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +182 -0
- data/lib/datadog/opentelemetry/trace.rb +59 -0
- data/lib/datadog/opentelemetry.rb +52 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +150 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +147 -0
- data/lib/datadog/profiling/collectors/dynamic_sampling_rate.rb +14 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +69 -0
- data/lib/datadog/profiling/collectors/info.rb +156 -0
- data/lib/datadog/profiling/collectors/stack.rb +13 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +102 -0
- data/lib/datadog/profiling/component.rb +445 -0
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +111 -0
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
- data/lib/datadog/profiling/ext.rb +22 -0
- data/lib/datadog/profiling/flush.rb +40 -0
- data/lib/datadog/profiling/http_transport.rb +67 -0
- data/lib/datadog/profiling/load_native_extension.rb +9 -0
- data/lib/datadog/profiling/native_extension.rb +20 -0
- data/lib/datadog/profiling/preload.rb +5 -0
- data/lib/datadog/profiling/profiler.rb +70 -0
- data/lib/datadog/profiling/scheduler.rb +153 -0
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +104 -0
- data/lib/datadog/profiling/tag_builder.rb +59 -0
- data/lib/datadog/profiling/tasks/exec.rb +50 -0
- data/lib/datadog/profiling/tasks/help.rb +18 -0
- data/lib/datadog/profiling/tasks/setup.rb +43 -0
- data/lib/datadog/profiling.rb +167 -0
- data/lib/datadog/single_step_instrument.rb +21 -0
- data/lib/datadog/tracing/analytics.rb +25 -0
- data/lib/datadog/tracing/buffer.rb +129 -0
- data/lib/datadog/tracing/client_ip.rb +61 -0
- data/lib/datadog/tracing/component.rb +216 -0
- data/lib/datadog/tracing/configuration/dynamic/option.rb +71 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +100 -0
- data/lib/datadog/tracing/configuration/ext.rb +118 -0
- data/lib/datadog/tracing/configuration/http.rb +74 -0
- data/lib/datadog/tracing/configuration/settings.rb +579 -0
- data/lib/datadog/tracing/context.rb +68 -0
- data/lib/datadog/tracing/context_provider.rb +82 -0
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +39 -0
- data/lib/datadog/tracing/contrib/action_cable/event.rb +71 -0
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +58 -0
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +63 -0
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +59 -0
- data/lib/datadog/tracing/contrib/action_cable/events.rb +37 -0
- data/lib/datadog/tracing/contrib/action_cable/ext.rb +33 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +86 -0
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +53 -0
- data/lib/datadog/tracing/contrib/action_cable/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +43 -0
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +50 -0
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +65 -0
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +48 -0
- data/lib/datadog/tracing/contrib/action_mailer/events.rb +34 -0
- data/lib/datadog/tracing/contrib/action_mailer/ext.rb +34 -0
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +54 -0
- data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +158 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +85 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +40 -0
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +25 -0
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +54 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +39 -0
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +43 -0
- data/lib/datadog/tracing/contrib/action_view/event.rb +35 -0
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +50 -0
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +57 -0
- data/lib/datadog/tracing/contrib/action_view/events.rb +34 -0
- data/lib/datadog/tracing/contrib/action_view/ext.rb +25 -0
- data/lib/datadog/tracing/contrib/action_view/integration.rb +61 -0
- data/lib/datadog/tracing/contrib/action_view/patcher.rb +34 -0
- data/lib/datadog/tracing/contrib/action_view/utils.rb +36 -0
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +39 -0
- data/lib/datadog/tracing/contrib/active_job/event.rb +58 -0
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +50 -0
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +49 -0
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +49 -0
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +51 -0
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +49 -0
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +50 -0
- data/lib/datadog/tracing/contrib/active_job/events.rb +42 -0
- data/lib/datadog/tracing/contrib/active_job/ext.rb +40 -0
- data/lib/datadog/tracing/contrib/active_job/integration.rb +53 -0
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +38 -0
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +40 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +37 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +68 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +45 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +47 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +25 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +32 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/makara_resolver.rb +36 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +152 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +48 -0
- data/lib/datadog/tracing/contrib/active_record/event.rb +30 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +60 -0
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +80 -0
- data/lib/datadog/tracing/contrib/active_record/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_record/ext.rb +30 -0
- data/lib/datadog/tracing/contrib/active_record/integration.rb +71 -0
- data/lib/datadog/tracing/contrib/active_record/patcher.rb +27 -0
- data/lib/datadog/tracing/contrib/active_record/utils.rb +128 -0
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +171 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +225 -0
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +57 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +60 -0
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +70 -0
- data/lib/datadog/tracing/contrib/active_support/ext.rb +32 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +55 -0
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +95 -0
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +83 -0
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +166 -0
- data/lib/datadog/tracing/contrib/active_support/patcher.rb +27 -0
- data/lib/datadog/tracing/contrib/analytics.rb +33 -0
- data/lib/datadog/tracing/contrib/auto_instrument.rb +53 -0
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +53 -0
- data/lib/datadog/tracing/contrib/aws/ext.rb +50 -0
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +136 -0
- data/lib/datadog/tracing/contrib/aws/integration.rb +50 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +70 -0
- data/lib/datadog/tracing/contrib/aws/patcher.rb +61 -0
- data/lib/datadog/tracing/contrib/aws/service/base.rb +17 -0
- data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +22 -0
- data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +22 -0
- data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +32 -0
- data/lib/datadog/tracing/contrib/aws/service/s3.rb +22 -0
- data/lib/datadog/tracing/contrib/aws/service/sns.rb +30 -0
- data/lib/datadog/tracing/contrib/aws/service/sqs.rb +27 -0
- data/lib/datadog/tracing/contrib/aws/service/states.rb +40 -0
- data/lib/datadog/tracing/contrib/aws/services.rb +139 -0
- data/lib/datadog/tracing/contrib/cloudwise/propagation.rb +315 -0
- data/lib/datadog/tracing/contrib/component.rb +41 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +24 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +53 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +16 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +20 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +47 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +49 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +22 -0
- data/lib/datadog/tracing/contrib/configurable.rb +102 -0
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +128 -0
- data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +43 -0
- data/lib/datadog/tracing/contrib/configuration/settings.rb +43 -0
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +58 -0
- data/lib/datadog/tracing/contrib/dalli/ext.rb +41 -0
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +75 -0
- data/lib/datadog/tracing/contrib/dalli/integration.rb +52 -0
- data/lib/datadog/tracing/contrib/dalli/patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +26 -0
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +49 -0
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +29 -0
- data/lib/datadog/tracing/contrib/delayed_job/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +37 -0
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +108 -0
- data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +34 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +61 -0
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +35 -0
- data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +50 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +172 -0
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +87 -0
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +56 -0
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +229 -0
- data/lib/datadog/tracing/contrib/ethon/ext.rb +33 -0
- data/lib/datadog/tracing/contrib/ethon/integration.rb +48 -0
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +102 -0
- data/lib/datadog/tracing/contrib/ethon/patcher.rb +30 -0
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +82 -0
- data/lib/datadog/tracing/contrib/excon/ext.rb +31 -0
- data/lib/datadog/tracing/contrib/excon/integration.rb +48 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +201 -0
- data/lib/datadog/tracing/contrib/excon/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib/ext.rb +70 -0
- data/lib/datadog/tracing/contrib/extensions.rb +255 -0
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +81 -0
- data/lib/datadog/tracing/contrib/faraday/connection.rb +22 -0
- data/lib/datadog/tracing/contrib/faraday/ext.rb +31 -0
- data/lib/datadog/tracing/contrib/faraday/integration.rb +48 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +128 -0
- data/lib/datadog/tracing/contrib/faraday/patcher.rb +56 -0
- data/lib/datadog/tracing/contrib/faraday/rack_builder.rb +22 -0
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +59 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +316 -0
- data/lib/datadog/tracing/contrib/grape/ext.rb +30 -0
- data/lib/datadog/tracing/contrib/grape/instrumentation.rb +37 -0
- data/lib/datadog/tracing/contrib/grape/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/grape/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +73 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +26 -0
- data/lib/datadog/tracing/contrib/graphql/integration.rb +56 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +58 -0
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +24 -0
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +297 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +31 -0
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +58 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +123 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +96 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +107 -0
- data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +26 -0
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +49 -0
- data/lib/datadog/tracing/contrib/grpc/ext.rb +29 -0
- data/lib/datadog/tracing/contrib/grpc/formatting.rb +127 -0
- data/lib/datadog/tracing/contrib/grpc/integration.rb +50 -0
- data/lib/datadog/tracing/contrib/grpc/intercept_with_datadog.rb +53 -0
- data/lib/datadog/tracing/contrib/grpc/patcher.rb +34 -0
- data/lib/datadog/tracing/contrib/grpc.rb +45 -0
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
- data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +23 -0
- data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
- data/lib/datadog/tracing/contrib/hanami/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +42 -0
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +34 -0
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +77 -0
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +38 -0
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/http/ext.rb +30 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +152 -0
- data/lib/datadog/tracing/contrib/http/integration.rb +52 -0
- data/lib/datadog/tracing/contrib/http/patcher.rb +30 -0
- data/lib/datadog/tracing/contrib/http.rb +45 -0
- data/lib/datadog/tracing/contrib/http_annotation_helper.rb +17 -0
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +76 -0
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +31 -0
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +132 -0
- data/lib/datadog/tracing/contrib/httpclient/integration.rb +48 -0
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +76 -0
- data/lib/datadog/tracing/contrib/httprb/ext.rb +30 -0
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +146 -0
- data/lib/datadog/tracing/contrib/httprb/integration.rb +51 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/integration.rb +78 -0
- data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +39 -0
- data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +19 -0
- data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +18 -0
- data/lib/datadog/tracing/contrib/kafka/event.rb +53 -0
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +42 -0
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +49 -0
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +47 -0
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +47 -0
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +37 -0
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +37 -0
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +37 -0
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +41 -0
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +44 -0
- data/lib/datadog/tracing/contrib/kafka/events.rb +48 -0
- data/lib/datadog/tracing/contrib/kafka/ext.rb +55 -0
- 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 +47 -0
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +43 -0
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +77 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +89 -0
- data/lib/datadog/tracing/contrib/karafka.rb +37 -0
- data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +24 -0
- data/lib/datadog/tracing/contrib/lograge/ext.rb +15 -0
- data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +31 -0
- data/lib/datadog/tracing/contrib/lograge/integration.rb +50 -0
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +46 -0
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +64 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +39 -0
- data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +47 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +51 -0
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +49 -0
- data/lib/datadog/tracing/contrib/mongodb/patcher.rb +34 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +160 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +69 -0
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +109 -0
- data/lib/datadog/tracing/contrib/mysql2/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/mysql2/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +71 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +48 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +46 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +144 -0
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +81 -0
- data/lib/datadog/tracing/contrib/patchable.rb +109 -0
- data/lib/datadog/tracing/contrib/patcher.rb +87 -0
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +69 -0
- data/lib/datadog/tracing/contrib/pg/ext.rb +35 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +214 -0
- data/lib/datadog/tracing/contrib/pg/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/pg/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +52 -0
- data/lib/datadog/tracing/contrib/presto/ext.rb +38 -0
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +138 -0
- data/lib/datadog/tracing/contrib/presto/integration.rb +46 -0
- data/lib/datadog/tracing/contrib/presto/patcher.rb +25 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +41 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +61 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +32 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +67 -0
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +55 -0
- data/lib/datadog/tracing/contrib/que/ext.rb +33 -0
- data/lib/datadog/tracing/contrib/que/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/que/patcher.rb +26 -0
- data/lib/datadog/tracing/contrib/que/tracer.rb +63 -0
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +47 -0
- data/lib/datadog/tracing/contrib/racecar/event.rb +81 -0
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +38 -0
- data/lib/datadog/tracing/contrib/racecar/events/consume.rb +35 -0
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +38 -0
- data/lib/datadog/tracing/contrib/racecar/events.rb +36 -0
- data/lib/datadog/tracing/contrib/racecar/ext.rb +33 -0
- data/lib/datadog/tracing/contrib/racecar/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/racecar/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +59 -0
- data/lib/datadog/tracing/contrib/rack/ext.rb +30 -0
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +50 -0
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +63 -0
- data/lib/datadog/tracing/contrib/rack/integration.rb +50 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +475 -0
- data/lib/datadog/tracing/contrib/rack/patcher.rb +119 -0
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +49 -0
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +58 -0
- data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +10 -0
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +76 -0
- data/lib/datadog/tracing/contrib/rails/ext.rb +33 -0
- data/lib/datadog/tracing/contrib/rails/framework.rb +148 -0
- data/lib/datadog/tracing/contrib/rails/integration.rb +52 -0
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +29 -0
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +46 -0
- data/lib/datadog/tracing/contrib/rails/patcher.rb +98 -0
- data/lib/datadog/tracing/contrib/rails/railtie.rb +19 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +117 -0
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +55 -0
- data/lib/datadog/tracing/contrib/rake/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +103 -0
- data/lib/datadog/tracing/contrib/rake/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/rake/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +49 -0
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +57 -0
- data/lib/datadog/tracing/contrib/redis/ext.rb +36 -0
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +53 -0
- data/lib/datadog/tracing/contrib/redis/integration.rb +80 -0
- data/lib/datadog/tracing/contrib/redis/patcher.rb +92 -0
- data/lib/datadog/tracing/contrib/redis/quantize.rb +80 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +72 -0
- data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +85 -0
- data/lib/datadog/tracing/contrib/redis/vendor/LICENSE +20 -0
- data/lib/datadog/tracing/contrib/redis/vendor/resolver.rb +160 -0
- data/lib/datadog/tracing/contrib/registerable.rb +50 -0
- data/lib/datadog/tracing/contrib/registry.rb +52 -0
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +42 -0
- data/lib/datadog/tracing/contrib/resque/ext.rb +22 -0
- data/lib/datadog/tracing/contrib/resque/integration.rb +48 -0
- data/lib/datadog/tracing/contrib/resque/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/resque/resque_job.rb +106 -0
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +55 -0
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +29 -0
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +46 -0
- data/lib/datadog/tracing/contrib/rest_client/patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +137 -0
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +38 -0
- data/lib/datadog/tracing/contrib/roda/ext.rb +19 -0
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/roda/integration.rb +45 -0
- data/lib/datadog/tracing/contrib/roda/patcher.rb +30 -0
- data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +24 -0
- data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +15 -0
- data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +35 -0
- data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +52 -0
- data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +37 -0
- data/lib/datadog/tracing/contrib/sequel/database.rb +62 -0
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +67 -0
- data/lib/datadog/tracing/contrib/sequel/ext.rb +23 -0
- data/lib/datadog/tracing/contrib/sequel/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/sequel/patcher.rb +37 -0
- data/lib/datadog/tracing/contrib/sequel/utils.rb +90 -0
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +43 -0
- data/lib/datadog/tracing/contrib/shoryuken/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/shoryuken/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +65 -0
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +67 -0
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +47 -0
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +49 -0
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +45 -0
- data/lib/datadog/tracing/contrib/sidekiq/integration.rb +61 -0
- data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +90 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +61 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +36 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +34 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +57 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +34 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +91 -0
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +44 -0
- data/lib/datadog/tracing/contrib/sidekiq.rb +37 -0
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +46 -0
- data/lib/datadog/tracing/contrib/sinatra/env.rb +38 -0
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +31 -0
- data/lib/datadog/tracing/contrib/sinatra/framework.rb +116 -0
- data/lib/datadog/tracing/contrib/sinatra/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +75 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +90 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +109 -0
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +43 -0
- data/lib/datadog/tracing/contrib/sneakers/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/sneakers/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/sneakers/patcher.rb +27 -0
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +60 -0
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +97 -0
- data/lib/datadog/tracing/contrib/status_range_env_parser.rb +33 -0
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +32 -0
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +37 -0
- data/lib/datadog/tracing/contrib/stripe/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/stripe/patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +68 -0
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +39 -0
- data/lib/datadog/tracing/contrib/sucker_punch/exception_handler.rb +28 -0
- data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +104 -0
- data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +35 -0
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +63 -0
- data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +97 -0
- data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
- data/lib/datadog/tracing/contrib/utils/database.rb +31 -0
- data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +111 -0
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +179 -0
- data/lib/datadog/tracing/contrib.rb +82 -0
- data/lib/datadog/tracing/correlation.rb +113 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +163 -0
- data/lib/datadog/tracing/diagnostics/ext.rb +36 -0
- data/lib/datadog/tracing/diagnostics/health.rb +40 -0
- data/lib/datadog/tracing/distributed/b3_multi.rb +73 -0
- data/lib/datadog/tracing/distributed/b3_single.rb +71 -0
- data/lib/datadog/tracing/distributed/baggage.rb +196 -0
- data/lib/datadog/tracing/distributed/datadog.rb +201 -0
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +82 -0
- data/lib/datadog/tracing/distributed/fetcher.rb +21 -0
- data/lib/datadog/tracing/distributed/helpers.rb +65 -0
- data/lib/datadog/tracing/distributed/none.rb +20 -0
- data/lib/datadog/tracing/distributed/propagation.rb +187 -0
- data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +444 -0
- data/lib/datadog/tracing/event.rb +74 -0
- data/lib/datadog/tracing/flush.rb +96 -0
- data/lib/datadog/tracing/metadata/analytics.rb +26 -0
- data/lib/datadog/tracing/metadata/errors.rb +32 -0
- data/lib/datadog/tracing/metadata/ext.rb +213 -0
- data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
- data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
- data/lib/datadog/tracing/metadata/tagging.rb +131 -0
- data/lib/datadog/tracing/metadata.rb +22 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +48 -0
- data/lib/datadog/tracing/pipeline/span_processor.rb +41 -0
- data/lib/datadog/tracing/pipeline.rb +63 -0
- data/lib/datadog/tracing/remote.rb +85 -0
- data/lib/datadog/tracing/runtime/metrics.rb +17 -0
- data/lib/datadog/tracing/sampling/all_sampler.rb +24 -0
- data/lib/datadog/tracing/sampling/ext.rb +58 -0
- data/lib/datadog/tracing/sampling/matcher.rb +119 -0
- data/lib/datadog/tracing/sampling/priority_sampler.rb +160 -0
- data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +87 -0
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +63 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +59 -0
- data/lib/datadog/tracing/sampling/rule.rb +86 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +172 -0
- data/lib/datadog/tracing/sampling/sampler.rb +32 -0
- data/lib/datadog/tracing/sampling/span/ext.rb +25 -0
- data/lib/datadog/tracing/sampling/span/matcher.rb +61 -0
- data/lib/datadog/tracing/sampling/span/rule.rb +77 -0
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
- data/lib/datadog/tracing/sampling/span/sampler.rb +70 -0
- data/lib/datadog/tracing/span.rb +236 -0
- data/lib/datadog/tracing/span_event.rb +161 -0
- data/lib/datadog/tracing/span_link.rb +92 -0
- data/lib/datadog/tracing/span_operation.rb +561 -0
- data/lib/datadog/tracing/sync_writer.rb +71 -0
- data/lib/datadog/tracing/trace_digest.rb +190 -0
- data/lib/datadog/tracing/trace_operation.rb +556 -0
- data/lib/datadog/tracing/trace_segment.rb +227 -0
- data/lib/datadog/tracing/tracer.rb +644 -0
- data/lib/datadog/tracing/transport/http/api.rb +44 -0
- data/lib/datadog/tracing/transport/http/client.rb +59 -0
- data/lib/datadog/tracing/transport/http/statistics.rb +47 -0
- data/lib/datadog/tracing/transport/http/traces.rb +155 -0
- data/lib/datadog/tracing/transport/http.rb +44 -0
- data/lib/datadog/tracing/transport/io/client.rb +90 -0
- data/lib/datadog/tracing/transport/io/response.rb +27 -0
- data/lib/datadog/tracing/transport/io/traces.rb +101 -0
- data/lib/datadog/tracing/transport/io.rb +30 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +155 -0
- data/lib/datadog/tracing/transport/statistics.rb +77 -0
- data/lib/datadog/tracing/transport/trace_formatter.rb +276 -0
- data/lib/datadog/tracing/transport/traces.rb +258 -0
- data/lib/datadog/tracing/utils.rb +99 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +199 -0
- data/lib/datadog/tracing/workers.rb +126 -0
- data/lib/datadog/tracing/writer.rb +190 -0
- data/lib/datadog/tracing.rb +214 -0
- data/lib/datadog/version.rb +27 -0
- data/lib/datadog.rb +20 -0
- metadata +1074 -0
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
#include "heap_recorder.h"
|
|
2
|
+
#include "ruby/st.h"
|
|
3
|
+
#include "ruby_helpers.h"
|
|
4
|
+
#include "collectors_stack.h"
|
|
5
|
+
#include "libdatadog_helpers.h"
|
|
6
|
+
#include "time_helpers.h"
|
|
7
|
+
|
|
8
|
+
// Note on calloc vs ruby_xcalloc use:
|
|
9
|
+
// * Whenever we're allocating memory after being called by the Ruby VM in a "regular" situation (e.g. initializer)
|
|
10
|
+
// we should use `ruby_xcalloc` to give the VM visibility into what we're doing + give it a chance to manage GC
|
|
11
|
+
// * BUT, when we're being called during a sample, being in the middle of an object allocation is a very special
|
|
12
|
+
// situation for the VM to be in, and we've found the hard way (e.g. https://bugs.ruby-lang.org/issues/20629 and
|
|
13
|
+
// https://github.com/DataDog/dd-trace-rb/pull/4240 ) that it can be easy to do things the VM didn't expect.
|
|
14
|
+
// * Thus, out of caution and to avoid future potential issues such as the ones above, whenever we allocate memory
|
|
15
|
+
// during **sampling** we use `calloc` instead of `ruby_xcalloc`. Note that we've never seen issues from using
|
|
16
|
+
// `ruby_xcalloc` at any time, so this is a **precaution** not a "we've seen it break". But it seems a harmless
|
|
17
|
+
// one to use.
|
|
18
|
+
// This applies to both heap_recorder.c and collectors_thread_context.c
|
|
19
|
+
|
|
20
|
+
// Minimum age (in GC generations) of heap objects we want to include in heap
|
|
21
|
+
// recorder iterations. Object with age 0 represent objects that have yet to undergo
|
|
22
|
+
// a GC and, thus, may just be noise/trash at instant of iteration and are usually not
|
|
23
|
+
// relevant for heap profiles as the great majority should be trivially reclaimed
|
|
24
|
+
// during the next GC.
|
|
25
|
+
#define ITERATION_MIN_AGE 1
|
|
26
|
+
// Copied from https://github.com/ruby/ruby/blob/15135030e5808d527325feaaaf04caeb1b44f8b5/gc/default.c#L725C1-L725C27
|
|
27
|
+
// to align with Ruby's GC definition of what constitutes an old object which are only
|
|
28
|
+
// supposed to be reclaimed in major GCs.
|
|
29
|
+
#define OLD_AGE 3
|
|
30
|
+
// Wait at least 2 seconds before asking heap recorder to explicitly update itself. Heap recorder
|
|
31
|
+
// data will only materialize at profile serialization time but updating often helps keep our
|
|
32
|
+
// heap tracking data small since every GC should get rid of a bunch of temporary objects. The
|
|
33
|
+
// more we clean up before profile flush, the less work we'll have to do all-at-once when preparing
|
|
34
|
+
// to flush heap data and holding the GVL which should hopefully help with reducing latency impact.
|
|
35
|
+
#define MIN_TIME_BETWEEN_HEAP_RECORDER_UPDATES_NS SECONDS_AS_NS(2)
|
|
36
|
+
|
|
37
|
+
// A compact representation of a stacktrace frame for a heap allocation.
|
|
38
|
+
typedef struct {
|
|
39
|
+
ddog_prof_ManagedStringId name;
|
|
40
|
+
ddog_prof_ManagedStringId filename;
|
|
41
|
+
int32_t line;
|
|
42
|
+
} heap_frame;
|
|
43
|
+
|
|
44
|
+
// We use memcmp/st_hash below to compare/hash an entire array of heap_frames, so want to make sure no padding is added
|
|
45
|
+
// We could define the structure to be packed, but that seems even weirder across compilers, and this seems more portable?
|
|
46
|
+
_Static_assert(
|
|
47
|
+
sizeof(heap_frame) == sizeof(ddog_prof_ManagedStringId) * 2 + sizeof(int32_t),
|
|
48
|
+
"Size of heap_frame does not match the sum of its members. Padding detected."
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// A compact representation of a stacktrace for a heap allocation.
|
|
52
|
+
// Used to dedup heap allocation stacktraces across multiple objects sharing the same allocation location.
|
|
53
|
+
typedef struct {
|
|
54
|
+
// How many objects are currently tracked in object_records recorder for this heap record.
|
|
55
|
+
uint32_t num_tracked_objects;
|
|
56
|
+
|
|
57
|
+
uint16_t frames_len;
|
|
58
|
+
heap_frame frames[];
|
|
59
|
+
} heap_record;
|
|
60
|
+
static heap_record* heap_record_new(heap_recorder*, ddog_prof_Slice_Location);
|
|
61
|
+
static void heap_record_free(heap_recorder*, heap_record*);
|
|
62
|
+
|
|
63
|
+
#if MAX_FRAMES_LIMIT > UINT16_MAX
|
|
64
|
+
#error Frames len type not compatible with MAX_FRAMES_LIMIT
|
|
65
|
+
#endif
|
|
66
|
+
|
|
67
|
+
static int heap_record_cmp_st(st_data_t, st_data_t);
|
|
68
|
+
static st_index_t heap_record_hash_st(st_data_t);
|
|
69
|
+
static const struct st_hash_type st_hash_type_heap_record = { .compare = heap_record_cmp_st, .hash = heap_record_hash_st };
|
|
70
|
+
|
|
71
|
+
// An object record is used for storing data about currently tracked live objects
|
|
72
|
+
typedef struct {
|
|
73
|
+
long obj_id;
|
|
74
|
+
heap_record *heap_record;
|
|
75
|
+
live_object_data object_data;
|
|
76
|
+
} object_record;
|
|
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};
|
|
81
|
+
|
|
82
|
+
struct heap_recorder {
|
|
83
|
+
// Config
|
|
84
|
+
// Whether the recorder should try to determine approximate sizes for tracked objects.
|
|
85
|
+
bool size_enabled;
|
|
86
|
+
uint sample_rate;
|
|
87
|
+
|
|
88
|
+
// Map[key: heap_record*, record: nothing] (This is a set, basically)
|
|
89
|
+
// NOTE: This table is currently only protected by the GVL since we never interact with it
|
|
90
|
+
// outside the GVL.
|
|
91
|
+
// NOTE: This table has ownership of its heap_records.
|
|
92
|
+
//
|
|
93
|
+
// This is a cpu/memory trade-off: Maintaining the "heap_records" map means we spend extra CPU when sampling as we need
|
|
94
|
+
// to do de-duplication, but we reduce the memory footprint of the heap profiler.
|
|
95
|
+
// In the future, it may be worth revisiting if we can move this inside libdatadog: if libdatadog was able to track
|
|
96
|
+
// entire stacks for us, then we wouldn't need to do it on the Ruby side.
|
|
97
|
+
st_table *heap_records;
|
|
98
|
+
|
|
99
|
+
// Map[obj_id: long, record: object_record*]
|
|
100
|
+
// NOTE: This table is currently only protected by the GVL since we never interact with it
|
|
101
|
+
// outside the GVL.
|
|
102
|
+
// NOTE: This table has ownership of its object_records. The keys are longs and so are
|
|
103
|
+
// passed as values.
|
|
104
|
+
//
|
|
105
|
+
// TODO: @ivoanjo We've evolved to actually never need to look up on object_records (we only insert and iterate),
|
|
106
|
+
// so right now this seems to be just a really really fancy self-resizing list/set.
|
|
107
|
+
// If we replace this with a list, we could record the latest id and compare it when inserting to make sure our
|
|
108
|
+
// assumption of ids never reused + always increasing always holds. (This as an alternative to checking for duplicates)
|
|
109
|
+
st_table *object_records;
|
|
110
|
+
|
|
111
|
+
// Map[obj_id: long, record: object_record*]
|
|
112
|
+
// NOTE: This is a snapshot of object_records built ahead of a iteration. Outside of an
|
|
113
|
+
// iteration context, this table will be NULL. During an iteration, there will be no
|
|
114
|
+
// mutation of the data so iteration can occur without acquiring a lock.
|
|
115
|
+
// NOTE: Contrary to object_records, this table has no ownership of its data.
|
|
116
|
+
st_table *object_records_snapshot;
|
|
117
|
+
// Are we currently updating or not?
|
|
118
|
+
bool updating;
|
|
119
|
+
// The GC gen/epoch/count in which we are updating (or last updated if not currently updating).
|
|
120
|
+
//
|
|
121
|
+
// This enables us to calculate the age of objects considered in the update by comparing it
|
|
122
|
+
// against an object's alloc_gen.
|
|
123
|
+
size_t update_gen;
|
|
124
|
+
// Whether the current update (or last update if not currently updating) is including old
|
|
125
|
+
// objects or not.
|
|
126
|
+
bool update_include_old;
|
|
127
|
+
// When did we do the last update of heap recorder?
|
|
128
|
+
long last_update_ns;
|
|
129
|
+
|
|
130
|
+
// Data for a heap recording that was started but not yet ended
|
|
131
|
+
object_record *active_recording;
|
|
132
|
+
|
|
133
|
+
// Reusable arrays, implementing a flyweight pattern for things like iteration
|
|
134
|
+
#define REUSABLE_LOCATIONS_SIZE MAX_FRAMES_LIMIT
|
|
135
|
+
ddog_prof_Location *reusable_locations;
|
|
136
|
+
|
|
137
|
+
#define REUSABLE_FRAME_DETAILS_SIZE (2 * MAX_FRAMES_LIMIT) // because it'll be used for both function names AND file names)
|
|
138
|
+
ddog_prof_ManagedStringId *reusable_ids;
|
|
139
|
+
ddog_CharSlice *reusable_char_slices;
|
|
140
|
+
|
|
141
|
+
// Sampling state
|
|
142
|
+
uint num_recordings_skipped;
|
|
143
|
+
|
|
144
|
+
ddog_prof_ManagedStringStorage string_storage;
|
|
145
|
+
|
|
146
|
+
struct stats_last_update {
|
|
147
|
+
size_t objects_alive;
|
|
148
|
+
size_t objects_dead;
|
|
149
|
+
size_t objects_skipped;
|
|
150
|
+
size_t objects_frozen;
|
|
151
|
+
} stats_last_update;
|
|
152
|
+
|
|
153
|
+
struct stats_lifetime {
|
|
154
|
+
unsigned long updates_successful;
|
|
155
|
+
unsigned long updates_skipped_concurrent;
|
|
156
|
+
unsigned long updates_skipped_gcgen;
|
|
157
|
+
unsigned long updates_skipped_time;
|
|
158
|
+
|
|
159
|
+
double ewma_young_objects_alive;
|
|
160
|
+
double ewma_young_objects_dead;
|
|
161
|
+
double ewma_young_objects_skipped; // Note: Here "young" refers to the young update; objects skipped includes non-young objects
|
|
162
|
+
|
|
163
|
+
double ewma_objects_alive;
|
|
164
|
+
double ewma_objects_dead;
|
|
165
|
+
double ewma_objects_skipped;
|
|
166
|
+
} stats_lifetime;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
typedef struct {
|
|
170
|
+
heap_recorder *heap_recorder;
|
|
171
|
+
ddog_prof_Slice_Location locations;
|
|
172
|
+
} end_heap_allocation_args;
|
|
173
|
+
|
|
174
|
+
static heap_record* get_or_create_heap_record(heap_recorder*, ddog_prof_Slice_Location);
|
|
175
|
+
static void cleanup_heap_record_if_unused(heap_recorder*, heap_record*);
|
|
176
|
+
static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record);
|
|
177
|
+
static int st_heap_record_entry_free(st_data_t, st_data_t, st_data_t);
|
|
178
|
+
static int st_object_record_entry_free(st_data_t, st_data_t, st_data_t);
|
|
179
|
+
static int st_object_record_update(st_data_t, st_data_t, st_data_t);
|
|
180
|
+
static int st_object_records_iterate(st_data_t, st_data_t, st_data_t);
|
|
181
|
+
static int st_object_records_debug(st_data_t key, st_data_t value, st_data_t extra);
|
|
182
|
+
static int update_object_record_entry(st_data_t*, st_data_t*, st_data_t, int);
|
|
183
|
+
static void commit_recording(heap_recorder *, heap_record *, object_record *active_recording);
|
|
184
|
+
static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args);
|
|
185
|
+
static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update);
|
|
186
|
+
static inline double ewma_stat(double previous, double current);
|
|
187
|
+
static void unintern_or_raise(heap_recorder *, ddog_prof_ManagedStringId);
|
|
188
|
+
static void unintern_all_or_raise(heap_recorder *recorder, ddog_prof_Slice_ManagedStringId ids);
|
|
189
|
+
static VALUE get_ruby_string_or_raise(heap_recorder*, ddog_prof_ManagedStringId);
|
|
190
|
+
|
|
191
|
+
// ==========================
|
|
192
|
+
// Heap Recorder External API
|
|
193
|
+
//
|
|
194
|
+
// WARN: All these APIs should support receiving a NULL heap_recorder, resulting in a noop.
|
|
195
|
+
//
|
|
196
|
+
// WARN: Except for ::heap_recorder_for_each_live_object, we always assume interaction with these APIs
|
|
197
|
+
// happens under the GVL.
|
|
198
|
+
//
|
|
199
|
+
// ==========================
|
|
200
|
+
heap_recorder* heap_recorder_new(ddog_prof_ManagedStringStorage string_storage) {
|
|
201
|
+
heap_recorder *recorder = ruby_xcalloc(1, sizeof(heap_recorder));
|
|
202
|
+
|
|
203
|
+
recorder->heap_records = st_init_table(&st_hash_type_heap_record);
|
|
204
|
+
recorder->object_records = st_init_numtable();
|
|
205
|
+
recorder->object_records_snapshot = NULL;
|
|
206
|
+
recorder->reusable_locations = ruby_xcalloc(REUSABLE_LOCATIONS_SIZE, sizeof(ddog_prof_Location));
|
|
207
|
+
recorder->reusable_ids = ruby_xcalloc(REUSABLE_FRAME_DETAILS_SIZE, sizeof(ddog_prof_ManagedStringId));
|
|
208
|
+
recorder->reusable_char_slices = ruby_xcalloc(REUSABLE_FRAME_DETAILS_SIZE, sizeof(ddog_CharSlice));
|
|
209
|
+
recorder->active_recording = NULL;
|
|
210
|
+
recorder->size_enabled = true;
|
|
211
|
+
recorder->sample_rate = 1; // By default do no sampling on top of what allocation profiling already does
|
|
212
|
+
recorder->string_storage = string_storage;
|
|
213
|
+
|
|
214
|
+
return recorder;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
void heap_recorder_free(heap_recorder *heap_recorder) {
|
|
218
|
+
if (heap_recorder == NULL) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (heap_recorder->object_records_snapshot != NULL) {
|
|
223
|
+
// if there's an unfinished iteration, clean it up now
|
|
224
|
+
// before we clean up any other state it might depend on
|
|
225
|
+
heap_recorder_finish_iteration(heap_recorder);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Clean-up all object records
|
|
229
|
+
st_foreach(heap_recorder->object_records, st_object_record_entry_free, (st_data_t) heap_recorder);
|
|
230
|
+
st_free_table(heap_recorder->object_records);
|
|
231
|
+
|
|
232
|
+
// Clean-up all heap records (this includes those only referred to by queued_samples)
|
|
233
|
+
st_foreach(heap_recorder->heap_records, st_heap_record_entry_free, (st_data_t) heap_recorder);
|
|
234
|
+
st_free_table(heap_recorder->heap_records);
|
|
235
|
+
|
|
236
|
+
if (heap_recorder->active_recording != NULL && heap_recorder->active_recording != &SKIPPED_RECORD) {
|
|
237
|
+
// If there's a partial object record, clean it up as well
|
|
238
|
+
object_record_free(heap_recorder, heap_recorder->active_recording);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
ruby_xfree(heap_recorder->reusable_locations);
|
|
242
|
+
ruby_xfree(heap_recorder->reusable_ids);
|
|
243
|
+
ruby_xfree(heap_recorder->reusable_char_slices);
|
|
244
|
+
|
|
245
|
+
ruby_xfree(heap_recorder);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
void heap_recorder_set_size_enabled(heap_recorder *heap_recorder, bool size_enabled) {
|
|
249
|
+
if (heap_recorder == NULL) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
heap_recorder->size_enabled = size_enabled;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
void heap_recorder_set_sample_rate(heap_recorder *heap_recorder, int sample_rate) {
|
|
257
|
+
if (heap_recorder == NULL) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (sample_rate <= 0) {
|
|
262
|
+
rb_raise(rb_eArgError, "Heap sample rate must be a positive integer value but was %d", sample_rate);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
heap_recorder->sample_rate = sample_rate;
|
|
266
|
+
heap_recorder->num_recordings_skipped = 0;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// WARN: Assumes this gets called before profiler is reinitialized on the fork
|
|
270
|
+
void heap_recorder_after_fork(heap_recorder *heap_recorder) {
|
|
271
|
+
if (heap_recorder == NULL) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// When forking, the child process gets a copy of the entire state of the parent process, minus
|
|
276
|
+
// threads.
|
|
277
|
+
//
|
|
278
|
+
// This means anything the heap recorder is tracking will still be alive after the fork and
|
|
279
|
+
// should thus be kept. Because this heap recorder implementation does not rely on free
|
|
280
|
+
// tracepoints to track liveness, any frees that happen until we fully reinitialize, will
|
|
281
|
+
// simply be noticed on next heap_recorder_prepare_iteration.
|
|
282
|
+
//
|
|
283
|
+
// There is one small caveat though: fork only preserves one thread and in a Ruby app, that
|
|
284
|
+
// will be the thread holding on to the GVL. Since we support iteration on the heap recorder
|
|
285
|
+
// outside of the GVL, any state specific to that interaction may be inconsistent after fork
|
|
286
|
+
// (e.g. an acquired lock for thread safety). Iteration operates on object_records_snapshot
|
|
287
|
+
// though and that one will be updated on next heap_recorder_prepare_iteration so we really
|
|
288
|
+
// only need to finish any iteration that might have been left unfinished.
|
|
289
|
+
if (heap_recorder->object_records_snapshot != NULL) {
|
|
290
|
+
heap_recorder_finish_iteration(heap_recorder);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Clear lifetime stats since this is essentially a new heap recorder
|
|
294
|
+
heap_recorder->stats_lifetime = (struct stats_lifetime) {0};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj, unsigned int weight, ddog_CharSlice alloc_class) {
|
|
298
|
+
if (heap_recorder == NULL) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (heap_recorder->active_recording != NULL) {
|
|
303
|
+
rb_raise(rb_eRuntimeError, "Detected consecutive heap allocation recording starts without end.");
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (++heap_recorder->num_recordings_skipped < heap_recorder->sample_rate ||
|
|
307
|
+
#ifdef NO_IMEMO_OBJECT_ID
|
|
308
|
+
// On Ruby 3.5, we can't ask the object_id from IMEMOs (https://github.com/ruby/ruby/pull/13347)
|
|
309
|
+
RB_BUILTIN_TYPE(new_obj) == RUBY_T_IMEMO
|
|
310
|
+
#else
|
|
311
|
+
false
|
|
312
|
+
#endif
|
|
313
|
+
// If we got really unlucky and an allocation showed up during an update (because it triggered an allocation
|
|
314
|
+
// directly OR because the GVL got released in the middle of an update), let's skip this sample as well.
|
|
315
|
+
// See notes on `heap_recorder_update` for details.
|
|
316
|
+
|| heap_recorder->updating
|
|
317
|
+
) {
|
|
318
|
+
heap_recorder->active_recording = &SKIPPED_RECORD;
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
heap_recorder->num_recordings_skipped = 0;
|
|
323
|
+
|
|
324
|
+
VALUE ruby_obj_id = rb_obj_id(new_obj);
|
|
325
|
+
if (!FIXNUM_P(ruby_obj_id)) {
|
|
326
|
+
rb_raise(rb_eRuntimeError, "Detected a bignum object id. These are not supported by heap profiling.");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
heap_recorder->active_recording = object_record_new(
|
|
330
|
+
FIX2LONG(ruby_obj_id),
|
|
331
|
+
NULL,
|
|
332
|
+
(live_object_data) {
|
|
333
|
+
.weight = weight * heap_recorder->sample_rate,
|
|
334
|
+
.class = intern_or_raise(heap_recorder->string_storage, alloc_class),
|
|
335
|
+
.alloc_gen = rb_gc_count(),
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// end_heap_allocation_recording_with_rb_protect gets called while the stack_recorder is holding one of the profile
|
|
341
|
+
// locks. To enable us to correctly unlock the profile on exception, we wrap the call to end_heap_allocation_recording
|
|
342
|
+
// with an rb_protect.
|
|
343
|
+
__attribute__((warn_unused_result))
|
|
344
|
+
int end_heap_allocation_recording_with_rb_protect(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
|
|
345
|
+
if (heap_recorder == NULL) {
|
|
346
|
+
return 0;
|
|
347
|
+
}
|
|
348
|
+
if (heap_recorder->active_recording == &SKIPPED_RECORD) {
|
|
349
|
+
// Short circuit, in this case there's nothing to be done
|
|
350
|
+
heap_recorder->active_recording = NULL;
|
|
351
|
+
return 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
int exception_state;
|
|
356
|
+
end_heap_allocation_args args = {
|
|
357
|
+
.heap_recorder = heap_recorder,
|
|
358
|
+
.locations = locations,
|
|
359
|
+
};
|
|
360
|
+
rb_protect(end_heap_allocation_recording, (VALUE) &args, &exception_state);
|
|
361
|
+
return exception_state;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
static VALUE end_heap_allocation_recording(VALUE protect_args) {
|
|
365
|
+
end_heap_allocation_args *args = (end_heap_allocation_args *) protect_args;
|
|
366
|
+
|
|
367
|
+
heap_recorder *heap_recorder = args->heap_recorder;
|
|
368
|
+
ddog_prof_Slice_Location locations = args->locations;
|
|
369
|
+
|
|
370
|
+
object_record *active_recording = heap_recorder->active_recording;
|
|
371
|
+
|
|
372
|
+
if (active_recording == NULL) {
|
|
373
|
+
// Recording ended without having been started?
|
|
374
|
+
rb_raise(rb_eRuntimeError, "Ended a heap recording that was not started");
|
|
375
|
+
}
|
|
376
|
+
// From now on, mark the global active recording as invalid so we can short-circuit at any point
|
|
377
|
+
// and not end up with a still active recording. the local active_recording still holds the
|
|
378
|
+
// data required for committing though.
|
|
379
|
+
heap_recorder->active_recording = NULL;
|
|
380
|
+
|
|
381
|
+
if (active_recording == &SKIPPED_RECORD) { // special marker when we decided to skip due to sampling
|
|
382
|
+
// Note: Remember to update the short circuit in end_heap_allocation_recording_with_rb_protect if this logic changes
|
|
383
|
+
return Qnil;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
heap_record *heap_record = get_or_create_heap_record(heap_recorder, locations);
|
|
387
|
+
|
|
388
|
+
// And then commit the new allocation.
|
|
389
|
+
commit_recording(heap_recorder, heap_record, active_recording);
|
|
390
|
+
|
|
391
|
+
return Qnil;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
void heap_recorder_update_young_objects(heap_recorder *heap_recorder) {
|
|
395
|
+
if (heap_recorder == NULL) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
heap_recorder_update(heap_recorder, /* full_update: */ false);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// NOTE: This function needs and assumes it gets called with the GVL being held.
|
|
403
|
+
// But importantly **some of the operations inside `st_object_record_update` may cause a thread switch**,
|
|
404
|
+
// so we can't assume a single update happens in a single "atomic" step -- other threads may get some running time
|
|
405
|
+
// in the meanwhile.
|
|
406
|
+
static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update) {
|
|
407
|
+
if (heap_recorder->updating) {
|
|
408
|
+
if (full_update) {
|
|
409
|
+
// There's another thread that's already doing an update :(
|
|
410
|
+
//
|
|
411
|
+
// Because there's a lock on the `StackRecorder` (see @no_concurrent_serialize_mutex) then it's not possible that
|
|
412
|
+
// the other update is a full update.
|
|
413
|
+
// Thus we expect is happening is that the GVL got released by the other thread in the middle of a non-full update
|
|
414
|
+
// and the scheduler thread decided now was a great time to serialize the profile.
|
|
415
|
+
//
|
|
416
|
+
// So, let's yield the time on the current thread until Ruby goes back to the other thread doing the update and
|
|
417
|
+
// it finishes cleanly.
|
|
418
|
+
while (heap_recorder->updating) { rb_thread_schedule(); }
|
|
419
|
+
} else {
|
|
420
|
+
// Non-full updates are optional, so let's walk away
|
|
421
|
+
heap_recorder->stats_lifetime.updates_skipped_concurrent++;
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (heap_recorder->object_records_snapshot != NULL) {
|
|
427
|
+
// While serialization is happening, it runs without the GVL and uses the object_records_snapshot.
|
|
428
|
+
// Although we iterate on a snapshot of object_records, these records point to other data that has not been
|
|
429
|
+
// snapshotted for efficiency reasons (e.g. heap_records). Since updating may invalidate
|
|
430
|
+
// some of that non-snapshotted data, let's refrain from doing updates during iteration. This also enforces the
|
|
431
|
+
// semantic that iteration will operate as a point-in-time snapshot.
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
size_t current_gc_gen = rb_gc_count();
|
|
436
|
+
long now_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
|
437
|
+
|
|
438
|
+
if (!full_update) {
|
|
439
|
+
if (current_gc_gen == heap_recorder->update_gen) {
|
|
440
|
+
// Are we still in the same GC gen as last update? If so, skip updating since things should not have
|
|
441
|
+
// changed significantly since last time.
|
|
442
|
+
// NOTE: This is mostly a performance decision. I suppose some objects may be cleaned up in intermediate
|
|
443
|
+
// GC steps and sizes may change. But because we have to iterate through all our tracked
|
|
444
|
+
// object records to do an update, let's wait until all steps for a particular GC generation
|
|
445
|
+
// have finished to do so. We may revisit this once we have a better liveness checking mechanism.
|
|
446
|
+
heap_recorder->stats_lifetime.updates_skipped_gcgen++;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (now_ns > 0 && (now_ns - heap_recorder->last_update_ns) < MIN_TIME_BETWEEN_HEAP_RECORDER_UPDATES_NS) {
|
|
451
|
+
// We did an update not too long ago. Let's skip this one to avoid over-taxing the system.
|
|
452
|
+
heap_recorder->stats_lifetime.updates_skipped_time++;
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
heap_recorder->updating = true;
|
|
458
|
+
// Reset last update stats, we'll be building them from scratch during the st_foreach call below
|
|
459
|
+
heap_recorder->stats_last_update = (struct stats_last_update) {0};
|
|
460
|
+
|
|
461
|
+
heap_recorder->update_gen = current_gc_gen;
|
|
462
|
+
heap_recorder->update_include_old = full_update;
|
|
463
|
+
|
|
464
|
+
st_foreach(heap_recorder->object_records, st_object_record_update, (st_data_t) heap_recorder);
|
|
465
|
+
|
|
466
|
+
heap_recorder->last_update_ns = now_ns;
|
|
467
|
+
heap_recorder->stats_lifetime.updates_successful++;
|
|
468
|
+
|
|
469
|
+
// Lifetime stats updating
|
|
470
|
+
if (!full_update) {
|
|
471
|
+
heap_recorder->stats_lifetime.ewma_young_objects_alive = ewma_stat(heap_recorder->stats_lifetime.ewma_young_objects_alive, heap_recorder->stats_last_update.objects_alive);
|
|
472
|
+
heap_recorder->stats_lifetime.ewma_young_objects_dead = ewma_stat(heap_recorder->stats_lifetime.ewma_young_objects_dead, heap_recorder->stats_last_update.objects_dead);
|
|
473
|
+
heap_recorder->stats_lifetime.ewma_young_objects_skipped = ewma_stat(heap_recorder->stats_lifetime.ewma_young_objects_skipped, heap_recorder->stats_last_update.objects_skipped);
|
|
474
|
+
} else {
|
|
475
|
+
heap_recorder->stats_lifetime.ewma_objects_alive = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_alive, heap_recorder->stats_last_update.objects_alive);
|
|
476
|
+
heap_recorder->stats_lifetime.ewma_objects_dead = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_dead, heap_recorder->stats_last_update.objects_dead);
|
|
477
|
+
heap_recorder->stats_lifetime.ewma_objects_skipped = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_skipped, heap_recorder->stats_last_update.objects_skipped);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
heap_recorder->updating = false;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
void heap_recorder_prepare_iteration(heap_recorder *heap_recorder) {
|
|
484
|
+
if (heap_recorder == NULL) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (heap_recorder->object_records_snapshot != NULL) {
|
|
489
|
+
// we could trivially handle this but we raise to highlight and catch unexpected usages.
|
|
490
|
+
rb_raise(rb_eRuntimeError, "New heap recorder iteration prepared without the previous one having been finished.");
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
heap_recorder_update(heap_recorder, /* full_update: */ true);
|
|
494
|
+
|
|
495
|
+
heap_recorder->object_records_snapshot = st_copy(heap_recorder->object_records);
|
|
496
|
+
if (heap_recorder->object_records_snapshot == NULL) {
|
|
497
|
+
rb_raise(rb_eRuntimeError, "Failed to create heap snapshot.");
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
void heap_recorder_finish_iteration(heap_recorder *heap_recorder) {
|
|
502
|
+
if (heap_recorder == NULL) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (heap_recorder->object_records_snapshot == NULL) {
|
|
507
|
+
// we could trivially handle this but we raise to highlight and catch unexpected usages.
|
|
508
|
+
rb_raise(rb_eRuntimeError, "Heap recorder iteration finished without having been prepared.");
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
st_free_table(heap_recorder->object_records_snapshot);
|
|
512
|
+
heap_recorder->object_records_snapshot = NULL;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Internal data we need while performing iteration over live objects.
|
|
516
|
+
typedef struct {
|
|
517
|
+
// The callback we need to call for each object.
|
|
518
|
+
bool (*for_each_callback)(heap_recorder_iteration_data stack_data, void *extra_arg);
|
|
519
|
+
// The extra arg to pass as the second parameter to the callback.
|
|
520
|
+
void *for_each_callback_extra_arg;
|
|
521
|
+
// A reference to the heap recorder so we can access extra stuff like reusable_locations.
|
|
522
|
+
heap_recorder *heap_recorder;
|
|
523
|
+
} iteration_context;
|
|
524
|
+
|
|
525
|
+
// WARN: Assume iterations can run without the GVL for performance reasons. Do not raise, allocate or
|
|
526
|
+
// do NoGVL-unsafe interactions with the Ruby runtime. Any such interactions should be done during
|
|
527
|
+
// heap_recorder_prepare_iteration or heap_recorder_finish_iteration.
|
|
528
|
+
bool heap_recorder_for_each_live_object(
|
|
529
|
+
heap_recorder *heap_recorder,
|
|
530
|
+
bool (*for_each_callback)(heap_recorder_iteration_data stack_data, void *extra_arg),
|
|
531
|
+
void *for_each_callback_extra_arg) {
|
|
532
|
+
if (heap_recorder == NULL) {
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (heap_recorder->object_records_snapshot == NULL) {
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
iteration_context context;
|
|
541
|
+
context.for_each_callback = for_each_callback;
|
|
542
|
+
context.for_each_callback_extra_arg = for_each_callback_extra_arg;
|
|
543
|
+
context.heap_recorder = heap_recorder;
|
|
544
|
+
st_foreach(heap_recorder->object_records_snapshot, st_object_records_iterate, (st_data_t) &context);
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
VALUE heap_recorder_state_snapshot(heap_recorder *heap_recorder) {
|
|
549
|
+
VALUE arguments[] = {
|
|
550
|
+
ID2SYM(rb_intern("num_object_records")), /* => */ LONG2NUM(heap_recorder->object_records->num_entries),
|
|
551
|
+
ID2SYM(rb_intern("num_heap_records")), /* => */ LONG2NUM(heap_recorder->heap_records->num_entries),
|
|
552
|
+
|
|
553
|
+
// Stats as of last update
|
|
554
|
+
ID2SYM(rb_intern("last_update_objects_alive")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_alive),
|
|
555
|
+
ID2SYM(rb_intern("last_update_objects_dead")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_dead),
|
|
556
|
+
ID2SYM(rb_intern("last_update_objects_skipped")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_skipped),
|
|
557
|
+
ID2SYM(rb_intern("last_update_objects_frozen")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_frozen),
|
|
558
|
+
|
|
559
|
+
// Lifetime stats
|
|
560
|
+
ID2SYM(rb_intern("lifetime_updates_successful")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_successful),
|
|
561
|
+
ID2SYM(rb_intern("lifetime_updates_skipped_concurrent")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_skipped_concurrent),
|
|
562
|
+
ID2SYM(rb_intern("lifetime_updates_skipped_gcgen")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_skipped_gcgen),
|
|
563
|
+
ID2SYM(rb_intern("lifetime_updates_skipped_time")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_skipped_time),
|
|
564
|
+
ID2SYM(rb_intern("lifetime_ewma_young_objects_alive")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_young_objects_alive),
|
|
565
|
+
ID2SYM(rb_intern("lifetime_ewma_young_objects_dead")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_young_objects_dead),
|
|
566
|
+
// Note: Here "young" refers to the young update; objects skipped includes non-young objects
|
|
567
|
+
ID2SYM(rb_intern("lifetime_ewma_young_objects_skipped")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_young_objects_skipped),
|
|
568
|
+
ID2SYM(rb_intern("lifetime_ewma_objects_alive")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_alive),
|
|
569
|
+
ID2SYM(rb_intern("lifetime_ewma_objects_dead")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_dead),
|
|
570
|
+
ID2SYM(rb_intern("lifetime_ewma_objects_skipped")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_skipped),
|
|
571
|
+
};
|
|
572
|
+
VALUE hash = rb_hash_new();
|
|
573
|
+
for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(hash, arguments[i], arguments[i+1]);
|
|
574
|
+
return hash;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
typedef struct {
|
|
578
|
+
heap_recorder *recorder;
|
|
579
|
+
VALUE debug_str;
|
|
580
|
+
} debug_context;
|
|
581
|
+
|
|
582
|
+
VALUE heap_recorder_testonly_debug(heap_recorder *heap_recorder) {
|
|
583
|
+
if (heap_recorder == NULL) {
|
|
584
|
+
rb_raise(rb_eArgError, "heap_recorder is NULL");
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
VALUE debug_str = rb_str_new2("object records:\n");
|
|
588
|
+
debug_context context = (debug_context) {.recorder = heap_recorder, .debug_str = debug_str};
|
|
589
|
+
st_foreach(heap_recorder->object_records, st_object_records_debug, (st_data_t) &context);
|
|
590
|
+
|
|
591
|
+
rb_str_catf(debug_str, "state snapshot: %"PRIsVALUE"\n------\n", heap_recorder_state_snapshot(heap_recorder));
|
|
592
|
+
|
|
593
|
+
return debug_str;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// ==========================
|
|
597
|
+
// Heap Recorder Internal API
|
|
598
|
+
// ==========================
|
|
599
|
+
static int st_heap_record_entry_free(st_data_t key, DDTRACE_UNUSED st_data_t value, st_data_t extra_arg) {
|
|
600
|
+
heap_recorder *recorder = (heap_recorder *) extra_arg;
|
|
601
|
+
heap_record_free(recorder, (heap_record *) key);
|
|
602
|
+
return ST_DELETE;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
static int st_object_record_entry_free(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra_arg) {
|
|
606
|
+
heap_recorder *recorder = (heap_recorder *) extra_arg;
|
|
607
|
+
object_record_free(recorder, (object_record *) value);
|
|
608
|
+
return ST_DELETE;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// NOTE: Some operations inside this function can cause the GVL to be released! Plan accordingly.
|
|
612
|
+
static int st_object_record_update(st_data_t key, st_data_t value, st_data_t extra_arg) {
|
|
613
|
+
long obj_id = (long) key;
|
|
614
|
+
object_record *record = (object_record*) value;
|
|
615
|
+
heap_recorder *recorder = (heap_recorder*) extra_arg;
|
|
616
|
+
|
|
617
|
+
VALUE ref;
|
|
618
|
+
|
|
619
|
+
size_t update_gen = recorder->update_gen;
|
|
620
|
+
size_t alloc_gen = record->object_data.alloc_gen;
|
|
621
|
+
// Guard against potential overflows given unsigned types here.
|
|
622
|
+
record->object_data.gen_age = alloc_gen < update_gen ? update_gen - alloc_gen : 0;
|
|
623
|
+
|
|
624
|
+
if (record->object_data.gen_age == 0) {
|
|
625
|
+
// Objects that belong to the current GC gen have not had a chance to be cleaned up yet
|
|
626
|
+
// and won't show up in the iteration anyway so no point in checking their liveness/sizes.
|
|
627
|
+
recorder->stats_last_update.objects_skipped++;
|
|
628
|
+
return ST_CONTINUE;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (!recorder->update_include_old && record->object_data.gen_age >= OLD_AGE) {
|
|
632
|
+
// The current update is not including old objects but this record is for an old object, skip its update.
|
|
633
|
+
recorder->stats_last_update.objects_skipped++;
|
|
634
|
+
return ST_CONTINUE;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (!ruby_ref_from_id(LONG2NUM(obj_id), &ref)) { // Note: This function call can cause the GVL to be released
|
|
638
|
+
// Id no longer associated with a valid ref. Need to delete this object record!
|
|
639
|
+
on_committed_object_record_cleanup(recorder, record);
|
|
640
|
+
recorder->stats_last_update.objects_dead++;
|
|
641
|
+
return ST_DELETE;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// If we got this far, then we found a valid live object for the tracked id.
|
|
645
|
+
|
|
646
|
+
if (
|
|
647
|
+
recorder->size_enabled &&
|
|
648
|
+
recorder->update_include_old && // We only update sizes when doing a full update
|
|
649
|
+
!record->object_data.is_frozen
|
|
650
|
+
) {
|
|
651
|
+
// if we were asked to update sizes and this object was not already seen as being frozen,
|
|
652
|
+
// update size again.
|
|
653
|
+
record->object_data.size = ruby_obj_memsize_of(ref); // Note: This function call can cause the GVL to be released... maybe?
|
|
654
|
+
// (With T_DATA for instance, since it can be a custom method supplied by extensions)
|
|
655
|
+
// Check if it's now frozen so we skip a size update next time
|
|
656
|
+
record->object_data.is_frozen = RB_OBJ_FROZEN(ref);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Ensure that ref is kept on the stack so the Ruby garbage collector does not try to clean up the object before this
|
|
660
|
+
// point.
|
|
661
|
+
RB_GC_GUARD(ref);
|
|
662
|
+
|
|
663
|
+
recorder->stats_last_update.objects_alive++;
|
|
664
|
+
if (record->object_data.is_frozen) {
|
|
665
|
+
recorder->stats_last_update.objects_frozen++;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return ST_CONTINUE;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// WARN: This can get called outside the GVL. NO HEAP ALLOCATIONS OR EXCEPTIONS ARE ALLOWED.
|
|
672
|
+
static int st_object_records_iterate(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra) {
|
|
673
|
+
object_record *record = (object_record*) value;
|
|
674
|
+
const heap_record *stack = record->heap_record;
|
|
675
|
+
iteration_context *context = (iteration_context*) extra;
|
|
676
|
+
|
|
677
|
+
const heap_recorder *recorder = context->heap_recorder;
|
|
678
|
+
|
|
679
|
+
if (record->object_data.gen_age < ITERATION_MIN_AGE) {
|
|
680
|
+
// Skip objects that should not be included in iteration
|
|
681
|
+
return ST_CONTINUE;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
ddog_prof_Location *locations = recorder->reusable_locations;
|
|
685
|
+
for (uint16_t i = 0; i < stack->frames_len; i++) {
|
|
686
|
+
const heap_frame *frame = &stack->frames[i];
|
|
687
|
+
locations[i] = (ddog_prof_Location) {
|
|
688
|
+
.mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
|
|
689
|
+
.function = {
|
|
690
|
+
.name = DDOG_CHARSLICE_C(""),
|
|
691
|
+
.name_id = frame->name,
|
|
692
|
+
.filename = DDOG_CHARSLICE_C(""),
|
|
693
|
+
.filename_id = frame->filename,
|
|
694
|
+
},
|
|
695
|
+
.line = frame->line,
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
heap_recorder_iteration_data iteration_data;
|
|
700
|
+
iteration_data.object_data = record->object_data;
|
|
701
|
+
iteration_data.locations = (ddog_prof_Slice_Location) {.ptr = locations, .len = stack->frames_len};
|
|
702
|
+
|
|
703
|
+
// This is expected to be StackRecorder's add_heap_sample_to_active_profile_without_gvl
|
|
704
|
+
if (!context->for_each_callback(iteration_data, context->for_each_callback_extra_arg)) {
|
|
705
|
+
return ST_STOP;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return ST_CONTINUE;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
static int st_object_records_debug(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra) {
|
|
712
|
+
debug_context *context = (debug_context*) extra;
|
|
713
|
+
VALUE debug_str = context->debug_str;
|
|
714
|
+
|
|
715
|
+
object_record *record = (object_record*) value;
|
|
716
|
+
|
|
717
|
+
rb_str_catf(debug_str, "%"PRIsVALUE"\n", object_record_inspect(context->recorder, record));
|
|
718
|
+
|
|
719
|
+
return ST_CONTINUE;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
static int update_object_record_entry(DDTRACE_UNUSED st_data_t *key, st_data_t *value, st_data_t new_object_record, int existing) {
|
|
723
|
+
if (!existing) {
|
|
724
|
+
(*value) = (st_data_t) new_object_record; // Expected to be a `object_record *`
|
|
725
|
+
} else {
|
|
726
|
+
// If key already existed, we don't touch the existing value, so it can be used for diagnostics
|
|
727
|
+
}
|
|
728
|
+
return ST_CONTINUE;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
static void commit_recording(heap_recorder *heap_recorder, heap_record *heap_record, object_record *active_recording) {
|
|
732
|
+
// Link the object record with the corresponding heap record. This was the last remaining thing we
|
|
733
|
+
// needed to fully build the object_record.
|
|
734
|
+
active_recording->heap_record = heap_record;
|
|
735
|
+
if (heap_record->num_tracked_objects == UINT32_MAX) {
|
|
736
|
+
rb_raise(rb_eRuntimeError, "Reached maximum number of tracked objects for heap record");
|
|
737
|
+
}
|
|
738
|
+
heap_record->num_tracked_objects++;
|
|
739
|
+
|
|
740
|
+
int existing_error = st_update(heap_recorder->object_records, active_recording->obj_id, update_object_record_entry, (st_data_t) active_recording);
|
|
741
|
+
if (existing_error) {
|
|
742
|
+
object_record *existing_record = NULL;
|
|
743
|
+
st_lookup(heap_recorder->object_records, active_recording->obj_id, (st_data_t *) &existing_record);
|
|
744
|
+
if (existing_record == NULL) rb_raise(rb_eRuntimeError, "Unexpected NULL when reading existing record");
|
|
745
|
+
|
|
746
|
+
VALUE existing_inspect = object_record_inspect(heap_recorder, existing_record);
|
|
747
|
+
VALUE new_inspect = object_record_inspect(heap_recorder, active_recording);
|
|
748
|
+
rb_raise(rb_eRuntimeError, "Object ids are supposed to be unique. We got 2 allocation recordings with "
|
|
749
|
+
"the same id. previous={%"PRIsVALUE"} new={%"PRIsVALUE"}", existing_inspect, new_inspect);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
static int update_heap_record_entry_with_new_allocation(st_data_t *key, st_data_t *value, st_data_t data, int existing) {
|
|
754
|
+
heap_record **new_or_existing_record = (heap_record **) data;
|
|
755
|
+
(*new_or_existing_record) = (heap_record *) (*key);
|
|
756
|
+
|
|
757
|
+
if (!existing) {
|
|
758
|
+
(*value) = (st_data_t) true; // We're only using this hash as a set
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
return ST_CONTINUE;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
static heap_record* get_or_create_heap_record(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
|
|
765
|
+
// See note on "heap_records" definition for why we keep this map.
|
|
766
|
+
heap_record *stack = heap_record_new(heap_recorder, locations);
|
|
767
|
+
|
|
768
|
+
heap_record *new_or_existing_record = NULL; // Will be set inside update_heap_record_entry_with_new_allocation
|
|
769
|
+
bool 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);
|
|
770
|
+
if (existing) {
|
|
771
|
+
heap_record_free(heap_recorder, stack);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
return new_or_existing_record;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
static void cleanup_heap_record_if_unused(heap_recorder *heap_recorder, heap_record *heap_record) {
|
|
778
|
+
if (heap_record->num_tracked_objects > 0) {
|
|
779
|
+
// still being used! do nothing...
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (!st_delete(heap_recorder->heap_records, (st_data_t*) &heap_record, NULL)) {
|
|
784
|
+
rb_raise(rb_eRuntimeError, "Attempted to cleanup an untracked heap_record");
|
|
785
|
+
};
|
|
786
|
+
heap_record_free(heap_recorder, heap_record);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record) {
|
|
790
|
+
// @ivoanjo: We've seen a segfault crash in the field in this function (October 2024) which we're still trying to investigate.
|
|
791
|
+
// (See PROF-10656 Datadog-internal for details). Just in case, I've sprinkled a bunch of NULL tests in this function for now.
|
|
792
|
+
// Once we figure out the issue we can get rid of them again.
|
|
793
|
+
|
|
794
|
+
if (heap_recorder == NULL) rb_raise(rb_eRuntimeError, "heap_recorder was NULL in on_committed_object_record_cleanup");
|
|
795
|
+
if (heap_recorder->heap_records == NULL) rb_raise(rb_eRuntimeError, "heap_recorder->heap_records was NULL in on_committed_object_record_cleanup");
|
|
796
|
+
if (record == NULL) rb_raise(rb_eRuntimeError, "record was NULL in on_committed_object_record_cleanup");
|
|
797
|
+
|
|
798
|
+
// Starting with the associated heap record. There will now be one less tracked object pointing to it
|
|
799
|
+
heap_record *heap_record = record->heap_record;
|
|
800
|
+
|
|
801
|
+
if (heap_record == NULL) rb_raise(rb_eRuntimeError, "heap_record was NULL in on_committed_object_record_cleanup");
|
|
802
|
+
|
|
803
|
+
heap_record->num_tracked_objects--;
|
|
804
|
+
|
|
805
|
+
// One less object using this heap record, it may have become unused...
|
|
806
|
+
cleanup_heap_record_if_unused(heap_recorder, heap_record);
|
|
807
|
+
|
|
808
|
+
object_record_free(heap_recorder, record);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// =================
|
|
812
|
+
// Object Record API
|
|
813
|
+
// =================
|
|
814
|
+
object_record* object_record_new(long obj_id, heap_record *heap_record, live_object_data object_data) {
|
|
815
|
+
object_record *record = calloc(1, sizeof(object_record)); // See "note on calloc vs ruby_xcalloc use" above
|
|
816
|
+
record->obj_id = obj_id;
|
|
817
|
+
record->heap_record = heap_record;
|
|
818
|
+
record->object_data = object_data;
|
|
819
|
+
return record;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
void object_record_free(heap_recorder *recorder, object_record *record) {
|
|
823
|
+
unintern_or_raise(recorder, record->object_data.class);
|
|
824
|
+
free(record); // See "note on calloc vs ruby_xcalloc use" above
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
VALUE object_record_inspect(heap_recorder *recorder, object_record *record) {
|
|
828
|
+
heap_frame top_frame = record->heap_record->frames[0];
|
|
829
|
+
VALUE filename = get_ruby_string_or_raise(recorder, top_frame.filename);
|
|
830
|
+
live_object_data object_data = record->object_data;
|
|
831
|
+
|
|
832
|
+
VALUE inspect = rb_sprintf("obj_id=%ld weight=%d size=%zu location=%"PRIsVALUE":%d alloc_gen=%zu gen_age=%zu frozen=%d ",
|
|
833
|
+
record->obj_id, object_data.weight, object_data.size, filename,
|
|
834
|
+
(int) top_frame.line, object_data.alloc_gen, object_data.gen_age, object_data.is_frozen);
|
|
835
|
+
|
|
836
|
+
if (record->object_data.class.value > 0) {
|
|
837
|
+
VALUE class = get_ruby_string_or_raise(recorder, record->object_data.class);
|
|
838
|
+
|
|
839
|
+
rb_str_catf(inspect, "class=%"PRIsVALUE" ", class);
|
|
840
|
+
}
|
|
841
|
+
VALUE ref;
|
|
842
|
+
|
|
843
|
+
if (!ruby_ref_from_id(LONG2NUM(record->obj_id), &ref)) {
|
|
844
|
+
rb_str_catf(inspect, "object=<invalid>");
|
|
845
|
+
} else {
|
|
846
|
+
rb_str_catf(inspect, "value=%p ", (void *) ref);
|
|
847
|
+
VALUE ruby_inspect = ruby_safe_inspect(ref);
|
|
848
|
+
if (ruby_inspect != Qnil) {
|
|
849
|
+
rb_str_catf(inspect, "object=%"PRIsVALUE, ruby_inspect);
|
|
850
|
+
} else {
|
|
851
|
+
rb_str_catf(inspect, "object=%s", ruby_value_type_to_string(rb_type(ref)));
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
return inspect;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// ==============
|
|
859
|
+
// Heap Record API
|
|
860
|
+
// ==============
|
|
861
|
+
heap_record* heap_record_new(heap_recorder *recorder, ddog_prof_Slice_Location locations) {
|
|
862
|
+
uint16_t frames_len = locations.len;
|
|
863
|
+
if (frames_len > MAX_FRAMES_LIMIT) {
|
|
864
|
+
// This is not expected as MAX_FRAMES_LIMIT is shared with the stacktrace construction mechanism
|
|
865
|
+
rb_raise(rb_eRuntimeError, "Found stack with more than %d frames (%d)", MAX_FRAMES_LIMIT, frames_len);
|
|
866
|
+
}
|
|
867
|
+
heap_record *stack = calloc(1, sizeof(heap_record) + frames_len * sizeof(heap_frame)); // See "note on calloc vs ruby_xcalloc use" above
|
|
868
|
+
stack->num_tracked_objects = 0;
|
|
869
|
+
stack->frames_len = frames_len;
|
|
870
|
+
|
|
871
|
+
// Intern all these strings...
|
|
872
|
+
ddog_CharSlice *strings = recorder->reusable_char_slices;
|
|
873
|
+
// Put all the char slices in the same array; we'll pull them out in the same order from the ids array
|
|
874
|
+
for (uint16_t i = 0; i < stack->frames_len; i++) {
|
|
875
|
+
const ddog_prof_Location *location = &locations.ptr[i];
|
|
876
|
+
strings[i] = location->function.filename;
|
|
877
|
+
strings[i + stack->frames_len] = location->function.name;
|
|
878
|
+
}
|
|
879
|
+
intern_all_or_raise(recorder->string_storage, (ddog_prof_Slice_CharSlice) { .ptr = strings, .len = stack->frames_len * 2 }, recorder->reusable_ids, stack->frames_len * 2);
|
|
880
|
+
|
|
881
|
+
// ...and record them for later use
|
|
882
|
+
for (uint16_t i = 0; i < stack->frames_len; i++) {
|
|
883
|
+
stack->frames[i] = (heap_frame) {
|
|
884
|
+
.filename = recorder->reusable_ids[i],
|
|
885
|
+
.name = recorder->reusable_ids[i + stack->frames_len],
|
|
886
|
+
// ddog_prof_Location is a int64_t. We don't expect to have to profile files with more than
|
|
887
|
+
// 2M lines so this cast should be fairly safe?
|
|
888
|
+
.line = (int32_t) locations.ptr[i].line,
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return stack;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
void heap_record_free(heap_recorder *recorder, heap_record *stack) {
|
|
896
|
+
ddog_prof_ManagedStringId *ids = recorder->reusable_ids;
|
|
897
|
+
|
|
898
|
+
// Put all the ids in the same array; doesn't really matter the order
|
|
899
|
+
for (u_int16_t i = 0; i < stack->frames_len; i++) {
|
|
900
|
+
ids[i] = stack->frames[i].filename;
|
|
901
|
+
ids[i + stack->frames_len] = stack->frames[i].name;
|
|
902
|
+
}
|
|
903
|
+
unintern_all_or_raise(recorder, (ddog_prof_Slice_ManagedStringId) { .ptr = ids, .len = stack->frames_len * 2 });
|
|
904
|
+
|
|
905
|
+
free(stack); // See "note on calloc vs ruby_xcalloc use" above
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// The entire stack is represented by ids (name, filename) and lines (integers) so we can treat is as just
|
|
909
|
+
// a big string of bytes and compare it all in one go.
|
|
910
|
+
int heap_record_cmp_st(st_data_t key1, st_data_t key2) {
|
|
911
|
+
heap_record *stack1 = (heap_record*) key1;
|
|
912
|
+
heap_record *stack2 = (heap_record*) key2;
|
|
913
|
+
|
|
914
|
+
if (stack1->frames_len != stack2->frames_len) {
|
|
915
|
+
return ((int) stack1->frames_len) - ((int) stack2->frames_len);
|
|
916
|
+
} else {
|
|
917
|
+
return memcmp(stack1->frames, stack2->frames, stack1->frames_len * sizeof(heap_frame));
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// Initial seed for hash function, same as Ruby uses
|
|
922
|
+
#define FNV1_32A_INIT 0x811c9dc5
|
|
923
|
+
|
|
924
|
+
// The entire stack is represented by ids (name, filename) and lines (integers) so we can treat is as just
|
|
925
|
+
// a big string of bytes and hash it all in one go.
|
|
926
|
+
st_index_t heap_record_hash_st(st_data_t key) {
|
|
927
|
+
heap_record *stack = (heap_record*) key;
|
|
928
|
+
return st_hash(stack->frames, stack->frames_len * sizeof(heap_frame), FNV1_32A_INIT);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
static void unintern_or_raise(heap_recorder *recorder, ddog_prof_ManagedStringId id) {
|
|
932
|
+
if (id.value == 0) return; // Empty string, nothing to do
|
|
933
|
+
|
|
934
|
+
ddog_prof_MaybeError result = ddog_prof_ManagedStringStorage_unintern(recorder->string_storage, id);
|
|
935
|
+
if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
|
|
936
|
+
rb_raise(rb_eRuntimeError, "Failed to unintern id: %"PRIsVALUE, get_error_details_and_drop(&result.some));
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
static void unintern_all_or_raise(heap_recorder *recorder, ddog_prof_Slice_ManagedStringId ids) {
|
|
941
|
+
ddog_prof_MaybeError result = ddog_prof_ManagedStringStorage_unintern_all(recorder->string_storage, ids);
|
|
942
|
+
if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
|
|
943
|
+
rb_raise(rb_eRuntimeError, "Failed to unintern_all: %"PRIsVALUE, get_error_details_and_drop(&result.some));
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
static VALUE get_ruby_string_or_raise(heap_recorder *recorder, ddog_prof_ManagedStringId id) {
|
|
948
|
+
ddog_StringWrapperResult get_string_result = ddog_prof_ManagedStringStorage_get_string(recorder->string_storage, id);
|
|
949
|
+
if (get_string_result.tag == DDOG_STRING_WRAPPER_RESULT_ERR) {
|
|
950
|
+
rb_raise(rb_eRuntimeError, "Failed to get string: %"PRIsVALUE, get_error_details_and_drop(&get_string_result.err));
|
|
951
|
+
}
|
|
952
|
+
VALUE ruby_string = ruby_string_from_vec_u8(get_string_result.ok.message);
|
|
953
|
+
ddog_StringWrapper_drop((ddog_StringWrapper *) &get_string_result.ok);
|
|
954
|
+
|
|
955
|
+
return ruby_string;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
static inline double ewma_stat(double previous, double current) {
|
|
959
|
+
double alpha = 0.3;
|
|
960
|
+
return (1 - alpha) * previous + alpha * current;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
VALUE heap_recorder_testonly_is_object_recorded(heap_recorder *heap_recorder, VALUE obj_id) {
|
|
964
|
+
if (heap_recorder == NULL) {
|
|
965
|
+
rb_raise(rb_eArgError, "heap_recorder is NULL");
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// Check if object records contains an object with this object_id
|
|
969
|
+
return st_is_member(heap_recorder->object_records, FIX2LONG(obj_id)) ? Qtrue : Qfalse;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
void heap_recorder_testonly_reset_last_update(heap_recorder *heap_recorder) {
|
|
973
|
+
if (heap_recorder == NULL) {
|
|
974
|
+
rb_raise(rb_eArgError, "heap_recorder is NULL");
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
heap_recorder->last_update_ns = 0;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
void heap_recorder_testonly_benchmark_intern(heap_recorder *heap_recorder, ddog_CharSlice string, int times, bool use_all) {
|
|
981
|
+
if (heap_recorder == NULL) rb_raise(rb_eArgError, "heap profiling must be enabled");
|
|
982
|
+
if (times > REUSABLE_FRAME_DETAILS_SIZE) rb_raise(rb_eArgError, "times cannot be > than REUSABLE_FRAME_DETAILS_SIZE");
|
|
983
|
+
|
|
984
|
+
if (use_all) {
|
|
985
|
+
ddog_CharSlice *strings = heap_recorder->reusable_char_slices;
|
|
986
|
+
|
|
987
|
+
for (int i = 0; i < times; i++) strings[i] = string;
|
|
988
|
+
|
|
989
|
+
intern_all_or_raise(
|
|
990
|
+
heap_recorder->string_storage,
|
|
991
|
+
(ddog_prof_Slice_CharSlice) { .ptr = strings, .len = times },
|
|
992
|
+
heap_recorder->reusable_ids,
|
|
993
|
+
times
|
|
994
|
+
);
|
|
995
|
+
} else {
|
|
996
|
+
for (int i = 0; i < times; i++) intern_or_raise(heap_recorder->string_storage, string);
|
|
997
|
+
}
|
|
998
|
+
}
|