datadog 2.7.1 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +310 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +66 -56
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +10 -10
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +314 -145
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -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 +7 -8
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
- data/ext/datadog_profiling_native_extension/heap_recorder.c +61 -174
- data/ext/datadog_profiling_native_extension/heap_recorder.h +2 -2
- data/ext/datadog_profiling_native_extension/http_transport.c +64 -98
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +68 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +10 -1
- data/ext/datadog_profiling_native_extension/profiling.c +19 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.c +84 -131
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- 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 +17 -15
- data/ext/libdatadog_api/crashtracker.h +5 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/init.c +15 -0
- data/ext/libdatadog_api/library_config.c +122 -0
- data/ext/libdatadog_api/library_config.h +19 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +117 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- 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/lru_cache.rb +49 -0
- data/lib/datadog/appsec/api_security.rb +9 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
- data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
- data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +41 -33
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +152 -25
- data/lib/datadog/appsec/context.rb +74 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +92 -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 +1 -1
- 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 +22 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
- data/lib/datadog/appsec/contrib/devise/patcher.rb +33 -25
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
- data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
- 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 +41 -0
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +17 -30
- data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +78 -98
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +52 -68
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +16 -33
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +25 -38
- 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 +38 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +31 -68
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -31
- data/lib/datadog/appsec/event.rb +96 -135
- data/lib/datadog/appsec/ext.rb +12 -3
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
- data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
- data/lib/datadog/appsec/metrics/collector.rb +38 -0
- data/lib/datadog/appsec/metrics/exporter.rb +35 -0
- data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
- data/lib/datadog/appsec/metrics.rb +13 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +52 -32
- data/lib/datadog/appsec/processor/rule_loader.rb +26 -31
- data/lib/datadog/appsec/processor/rule_merger.rb +7 -6
- data/lib/datadog/appsec/processor.rb +5 -4
- data/lib/datadog/appsec/remote.rb +26 -12
- data/lib/datadog/appsec/response.rb +19 -85
- data/lib/datadog/appsec/security_engine/result.rb +67 -0
- data/lib/datadog/appsec/security_engine/runner.rb +88 -0
- data/lib/datadog/appsec/security_engine.rb +9 -0
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec/utils.rb +0 -2
- data/lib/datadog/appsec.rb +23 -10
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +42 -14
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +76 -32
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/ext.rb +5 -1
- data/lib/datadog/core/configuration/option.rb +79 -43
- data/lib/datadog/core/configuration/option_definition.rb +6 -4
- data/lib/datadog/core/configuration/options.rb +3 -3
- data/lib/datadog/core/configuration/settings.rb +100 -41
- data/lib/datadog/core/configuration/stable_config.rb +23 -0
- data/lib/datadog/core/configuration.rb +43 -11
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +4 -13
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/encoding.rb +17 -1
- data/lib/datadog/core/environment/agent_info.rb +78 -0
- data/lib/datadog/core/environment/cgroup.rb +10 -12
- data/lib/datadog/core/environment/container.rb +38 -40
- data/lib/datadog/core/environment/ext.rb +6 -6
- data/lib/datadog/core/environment/git.rb +1 -0
- data/lib/datadog/core/environment/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/environment/variable_helpers.rb +1 -1
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +27 -27
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/process_discovery.rb +32 -0
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client/capabilities.rb +6 -0
- data/lib/datadog/core/remote/client.rb +107 -92
- data/lib/datadog/core/remote/component.rb +18 -19
- data/lib/datadog/core/remote/configuration/digest.rb +7 -7
- data/lib/datadog/core/remote/configuration/path.rb +1 -1
- data/lib/datadog/core/remote/configuration/repository.rb +2 -1
- data/lib/datadog/core/remote/negotiation.rb +9 -9
- data/lib/datadog/core/remote/transport/config.rb +4 -3
- data/lib/datadog/core/remote/transport/http/api.rb +13 -18
- data/lib/datadog/core/remote/transport/http/client.rb +5 -4
- data/lib/datadog/core/remote/transport/http/config.rb +27 -55
- data/lib/datadog/core/remote/transport/http/negotiation.rb +8 -51
- data/lib/datadog/core/remote/transport/http.rb +25 -94
- data/lib/datadog/core/remote/transport/negotiation.rb +17 -4
- data/lib/datadog/core/remote/worker.rb +10 -7
- data/lib/datadog/core/runtime/metrics.rb +12 -5
- data/lib/datadog/core/telemetry/component.rb +84 -49
- data/lib/datadog/core/telemetry/emitter.rb +23 -11
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -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_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 +179 -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 +17 -383
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/logging.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +28 -6
- data/lib/datadog/core/telemetry/request.rb +4 -4
- 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 +128 -25
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
- data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +18 -1
- data/lib/datadog/core/transport/http/api/spec.rb +36 -0
- data/lib/datadog/{tracing → core}/transport/http/builder.rb +53 -31
- data/lib/datadog/core/transport/http.rb +75 -0
- data/lib/datadog/core/transport/response.rb +4 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
- data/lib/datadog/core/utils/duration.rb +32 -32
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/network.rb +6 -6
- data/lib/datadog/core/utils/only_once_successful.rb +16 -5
- data/lib/datadog/core/utils/time.rb +20 -0
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
- data/lib/datadog/core/worker.rb +1 -1
- data/lib/datadog/core/workers/async.rb +29 -12
- data/lib/datadog/core/workers/interval_loop.rb +12 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
- data/lib/datadog/core.rb +8 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/boot.rb +34 -0
- data/lib/datadog/di/code_tracker.rb +26 -15
- data/lib/datadog/di/component.rb +23 -14
- data/lib/datadog/di/configuration/settings.rb +25 -1
- data/lib/datadog/di/contrib/active_record.rb +1 -0
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +28 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +111 -20
- data/lib/datadog/di/logger.rb +30 -0
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +14 -7
- data/lib/datadog/di/probe_builder.rb +1 -0
- data/lib/datadog/di/probe_manager.rb +11 -5
- data/lib/datadog/di/probe_notification_builder.rb +34 -8
- data/lib/datadog/di/probe_notifier_worker.rb +52 -26
- data/lib/datadog/di/redactor.rb +0 -1
- data/lib/datadog/di/remote.rb +147 -0
- data/lib/datadog/di/serializer.rb +14 -7
- 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 +67 -0
- data/lib/datadog/di/transport/http.rb +57 -0
- data/lib/datadog/di/transport/input.rb +62 -0
- data/lib/datadog/di/utils.rb +103 -0
- data/lib/datadog/di.rb +14 -76
- 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.rb +15 -3
- data/lib/datadog/kit/identity.rb +9 -5
- 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 +16 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
- data/lib/datadog/opentelemetry.rb +2 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +3 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
- data/lib/datadog/profiling/component.rb +60 -76
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +3 -4
- data/lib/datadog/profiling/ext.rb +0 -2
- data/lib/datadog/profiling/flush.rb +5 -8
- data/lib/datadog/profiling/http_transport.rb +6 -85
- data/lib/datadog/profiling/load_native_extension.rb +1 -33
- data/lib/datadog/profiling/scheduler.rb +8 -1
- data/lib/datadog/profiling/stack_recorder.rb +4 -4
- data/lib/datadog/profiling/tag_builder.rb +1 -5
- data/lib/datadog/profiling.rb +6 -2
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/component.rb +16 -12
- data/lib/datadog/tracing/configuration/ext.rb +8 -1
- data/lib/datadog/tracing/configuration/settings.rb +22 -10
- data/lib/datadog/tracing/context_provider.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +7 -3
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -2
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +36 -1
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +14 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
- data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
- data/lib/datadog/tracing/contrib/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/extensions.rb +29 -3
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
- data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
- data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
- data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -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 +66 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
- data/lib/datadog/tracing/contrib/karafka.rb +37 -0
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/correlation.rb +9 -2
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +131 -0
- data/lib/datadog/tracing/distributed/datadog.rb +4 -2
- data/lib/datadog/tracing/distributed/propagation.rb +25 -4
- data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/tracing/metadata/ext.rb +5 -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.rb +2 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
- data/lib/datadog/tracing/span.rb +22 -5
- data/lib/datadog/tracing/span_event.rb +124 -4
- data/lib/datadog/tracing/span_operation.rb +52 -16
- data/lib/datadog/tracing/sync_writer.rb +9 -5
- data/lib/datadog/tracing/trace_digest.rb +9 -2
- data/lib/datadog/tracing/trace_operation.rb +44 -24
- data/lib/datadog/tracing/trace_segment.rb +6 -4
- data/lib/datadog/tracing/tracer.rb +60 -12
- data/lib/datadog/tracing/transport/http/api.rb +5 -4
- data/lib/datadog/tracing/transport/http/client.rb +5 -4
- data/lib/datadog/tracing/transport/http/traces.rb +13 -44
- data/lib/datadog/tracing/transport/http.rb +13 -70
- data/lib/datadog/tracing/transport/serializable_trace.rb +31 -7
- data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
- data/lib/datadog/tracing/transport/traces.rb +47 -13
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers/trace_writer.rb +8 -5
- data/lib/datadog/tracing/workers.rb +5 -4
- data/lib/datadog/tracing/writer.rb +10 -6
- data/lib/datadog/tracing.rb +16 -3
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +2 -0
- metadata +143 -50
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
- data/ext/datadog_profiling_loader/extconf.rb +0 -60
- data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
- data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
- data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
- data/lib/datadog/appsec/contrib/patcher.rb +0 -12
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
- data/lib/datadog/appsec/processor/actions.rb +0 -49
- data/lib/datadog/appsec/processor/context.rb +0 -107
- data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
- data/lib/datadog/appsec/reactive/engine.rb +0 -47
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
- data/lib/datadog/appsec/scope.rb +0 -58
- data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
- data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
- data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
- data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
- data/lib/datadog/core/telemetry/http/env.rb +0 -20
- data/lib/datadog/core/telemetry/http/ext.rb +0 -28
- data/lib/datadog/core/telemetry/http/response.rb +0 -70
- data/lib/datadog/core/telemetry/http/transport.rb +0 -90
- data/lib/datadog/di/transport.rb +0 -81
- data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
@@ -8,6 +8,7 @@
|
|
8
8
|
#include "ruby_helpers.h"
|
9
9
|
#include "time_helpers.h"
|
10
10
|
#include "heap_recorder.h"
|
11
|
+
#include "encoded_profile.h"
|
11
12
|
|
12
13
|
// Used to wrap a ddog_prof_Profile in a Ruby object and expose Ruby-level serialization APIs
|
13
14
|
// This file implements the native bits of the Datadog::Profiling::StackRecorder class
|
@@ -173,18 +174,19 @@ static const uint8_t all_value_types_positions[] =
|
|
173
174
|
|
174
175
|
// Struct for storing stats related to a profile in a particular slot.
|
175
176
|
// These stats will share the same lifetime as the data in that profile slot.
|
176
|
-
typedef struct
|
177
|
+
typedef struct {
|
177
178
|
// How many individual samples were recorded into this slot (un-weighted)
|
178
179
|
uint64_t recorded_samples;
|
179
180
|
} stats_slot;
|
180
181
|
|
181
|
-
typedef struct
|
182
|
+
typedef struct {
|
182
183
|
ddog_prof_Profile profile;
|
183
184
|
stats_slot stats;
|
185
|
+
ddog_Timespec start_timestamp;
|
184
186
|
} profile_slot;
|
185
187
|
|
186
188
|
// Contains native state for each instance
|
187
|
-
struct
|
189
|
+
typedef struct {
|
188
190
|
// Heap recorder instance
|
189
191
|
heap_recorder *heap_recorder;
|
190
192
|
bool heap_clean_after_gc_enabled;
|
@@ -210,17 +212,17 @@ struct stack_recorder_state {
|
|
210
212
|
long serialization_time_ns_max;
|
211
213
|
uint64_t serialization_time_ns_total;
|
212
214
|
} stats_lifetime;
|
213
|
-
};
|
215
|
+
} stack_recorder_state;
|
214
216
|
|
215
217
|
// Used to group mutex and the corresponding profile slot for easy unlocking after work is done.
|
216
|
-
typedef struct
|
218
|
+
typedef struct {
|
217
219
|
pthread_mutex_t *mutex;
|
218
220
|
profile_slot *data;
|
219
221
|
} locked_profile_slot;
|
220
222
|
|
221
|
-
struct
|
223
|
+
typedef struct {
|
222
224
|
// Set by caller
|
223
|
-
|
225
|
+
stack_recorder_state *state;
|
224
226
|
ddog_Timespec finish_timestamp;
|
225
227
|
|
226
228
|
// Set by callee
|
@@ -231,35 +233,33 @@ struct call_serialize_without_gvl_arguments {
|
|
231
233
|
|
232
234
|
// Set by both
|
233
235
|
bool serialize_ran;
|
234
|
-
};
|
236
|
+
} call_serialize_without_gvl_arguments;
|
235
237
|
|
236
238
|
static VALUE _native_new(VALUE klass);
|
237
|
-
static void initialize_slot_concurrency_control(
|
238
|
-
static void initialize_profiles(
|
239
|
+
static void initialize_slot_concurrency_control(stack_recorder_state *state);
|
240
|
+
static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types);
|
239
241
|
static void stack_recorder_typed_data_free(void *data);
|
240
242
|
static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
241
243
|
static VALUE _native_serialize(VALUE self, VALUE recorder_instance);
|
242
244
|
static VALUE ruby_time_from(ddog_Timespec ddprof_time);
|
243
245
|
static void *call_serialize_without_gvl(void *call_args);
|
244
|
-
static locked_profile_slot sampler_lock_active_profile(
|
246
|
+
static locked_profile_slot sampler_lock_active_profile(stack_recorder_state *state);
|
245
247
|
static void sampler_unlock_active_profile(locked_profile_slot active_slot);
|
246
|
-
static profile_slot* serializer_flip_active_and_inactive_slots(
|
248
|
+
static profile_slot* serializer_flip_active_and_inactive_slots(stack_recorder_state *state);
|
247
249
|
static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
248
250
|
static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
249
251
|
static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
250
252
|
static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot);
|
251
253
|
static ddog_Timespec system_epoch_now_timespec(void);
|
252
254
|
static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);
|
253
|
-
static void serializer_set_start_timestamp_for_next_profile(
|
255
|
+
static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time);
|
254
256
|
static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
|
255
|
-
static void reset_profile_slot(profile_slot *slot, ddog_Timespec
|
257
|
+
static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp);
|
256
258
|
static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class);
|
257
259
|
static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations);
|
258
260
|
static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
259
261
|
static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
260
262
|
static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
261
|
-
static VALUE _native_gc_force_recycle(DDTRACE_UNUSED VALUE _self, VALUE obj);
|
262
|
-
static VALUE _native_has_seen_id_flag(DDTRACE_UNUSED VALUE _self, VALUE obj);
|
263
263
|
static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance);
|
264
264
|
static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns, long heap_iteration_prep_time_ns, long heap_profile_build_time_ns);
|
265
265
|
static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE object_id);
|
@@ -297,10 +297,6 @@ void stack_recorder_init(VALUE profiling_module) {
|
|
297
297
|
_native_end_fake_slow_heap_serialization, 1);
|
298
298
|
rb_define_singleton_method(testing_module, "_native_debug_heap_recorder",
|
299
299
|
_native_debug_heap_recorder, 1);
|
300
|
-
rb_define_singleton_method(testing_module, "_native_gc_force_recycle",
|
301
|
-
_native_gc_force_recycle, 1);
|
302
|
-
rb_define_singleton_method(testing_module, "_native_has_seen_id_flag",
|
303
|
-
_native_has_seen_id_flag, 1);
|
304
300
|
rb_define_singleton_method(testing_module, "_native_is_object_recorded?", _native_is_object_recorded, 2);
|
305
301
|
rb_define_singleton_method(testing_module, "_native_heap_recorder_reset_last_update", _native_heap_recorder_reset_last_update, 1);
|
306
302
|
rb_define_singleton_method(testing_module, "_native_recorder_after_gc_step", _native_recorder_after_gc_step, 1);
|
@@ -322,7 +318,7 @@ static const rb_data_type_t stack_recorder_typed_data = {
|
|
322
318
|
};
|
323
319
|
|
324
320
|
static VALUE _native_new(VALUE klass) {
|
325
|
-
|
321
|
+
stack_recorder_state *state = ruby_xcalloc(1, sizeof(stack_recorder_state));
|
326
322
|
|
327
323
|
// Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
|
328
324
|
// being leaked.
|
@@ -338,29 +334,22 @@ static VALUE _native_new(VALUE klass) {
|
|
338
334
|
.serialization_time_ns_min = INT64_MAX,
|
339
335
|
};
|
340
336
|
|
341
|
-
// Note: At this point, slot_one_profile
|
337
|
+
// Note: At this point, slot_one_profile/slot_two_profile contain null pointers. Libdatadog validates pointers
|
342
338
|
// before using them so it's ok for us to go ahead and create the StackRecorder object.
|
343
339
|
|
344
|
-
// Note: As of this writing, no new Ruby objects get created and stored in the state. If that ever changes, remember
|
345
|
-
// to keep them on the stack and mark them with RB_GC_GUARD -- otherwise it's possible for a GC to run and
|
346
|
-
// since the instance representing the state does not yet exist, such objects will not get marked.
|
347
|
-
|
348
340
|
VALUE stack_recorder = TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
|
349
341
|
|
350
|
-
// NOTE: We initialize this because we want a new recorder to be operational even
|
342
|
+
// NOTE: We initialize this because we want a new recorder to be operational even before #initialize runs and our
|
351
343
|
// default is everything enabled. However, if during recording initialization it turns out we don't want
|
352
|
-
// heap samples, we will free and reset heap_recorder to NULL
|
353
|
-
// to heap profiling (all calls to heap_recorder_* with a NULL heap recorder are noops).
|
344
|
+
// heap samples, we will free and reset heap_recorder back to NULL.
|
354
345
|
state->heap_recorder = heap_recorder_new();
|
355
346
|
|
356
|
-
// Note: Don't raise exceptions after this point, since it'll lead to libdatadog memory leaking!
|
357
|
-
|
358
347
|
initialize_profiles(state, sample_types);
|
359
348
|
|
360
349
|
return stack_recorder;
|
361
350
|
}
|
362
351
|
|
363
|
-
static void initialize_slot_concurrency_control(
|
352
|
+
static void initialize_slot_concurrency_control(stack_recorder_state *state) {
|
364
353
|
state->mutex_slot_one = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
|
365
354
|
state->mutex_slot_two = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
|
366
355
|
|
@@ -370,34 +359,31 @@ static void initialize_slot_concurrency_control(struct stack_recorder_state *sta
|
|
370
359
|
state->active_slot = 1;
|
371
360
|
}
|
372
361
|
|
373
|
-
static void initialize_profiles(
|
362
|
+
static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types) {
|
363
|
+
ddog_Timespec start_timestamp = system_epoch_now_timespec();
|
364
|
+
|
374
365
|
ddog_prof_Profile_NewResult slot_one_profile_result =
|
375
|
-
ddog_prof_Profile_new(sample_types, NULL /* period is optional
|
366
|
+
ddog_prof_Profile_new(sample_types, NULL /* period is optional */);
|
376
367
|
|
377
368
|
if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
378
369
|
rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
|
379
370
|
}
|
380
371
|
|
372
|
+
state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
|
373
|
+
|
381
374
|
ddog_prof_Profile_NewResult slot_two_profile_result =
|
382
|
-
ddog_prof_Profile_new(sample_types, NULL /* period is optional
|
375
|
+
ddog_prof_Profile_new(sample_types, NULL /* period is optional */);
|
383
376
|
|
384
377
|
if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
|
385
|
-
//
|
386
|
-
ddog_prof_Profile_drop(&slot_one_profile_result.ok);
|
387
|
-
// And now we can raise...
|
378
|
+
// Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
|
388
379
|
rb_raise(rb_eRuntimeError, "Failed to initialize slot two profile: %"PRIsVALUE, get_error_details_and_drop(&slot_two_profile_result.err));
|
389
380
|
}
|
390
381
|
|
391
|
-
state->
|
392
|
-
.profile = slot_one_profile_result.ok,
|
393
|
-
};
|
394
|
-
state->profile_slot_two = (profile_slot) {
|
395
|
-
.profile = slot_two_profile_result.ok,
|
396
|
-
};
|
382
|
+
state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok, .start_timestamp = start_timestamp };
|
397
383
|
}
|
398
384
|
|
399
385
|
static void stack_recorder_typed_data_free(void *state_ptr) {
|
400
|
-
|
386
|
+
stack_recorder_state *state = (stack_recorder_state *) state_ptr;
|
401
387
|
|
402
388
|
pthread_mutex_destroy(&state->mutex_slot_one);
|
403
389
|
ddog_prof_Profile_drop(&state->profile_slot_one.profile);
|
@@ -432,8 +418,8 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
432
418
|
ENFORCE_BOOLEAN(timeline_enabled);
|
433
419
|
ENFORCE_BOOLEAN(heap_clean_after_gc_enabled);
|
434
420
|
|
435
|
-
|
436
|
-
TypedData_Get_Struct(recorder_instance,
|
421
|
+
stack_recorder_state *state;
|
422
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
437
423
|
|
438
424
|
state->heap_clean_after_gc_enabled = (heap_clean_after_gc_enabled == Qtrue);
|
439
425
|
|
@@ -523,8 +509,8 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
|
|
523
509
|
}
|
524
510
|
|
525
511
|
static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
526
|
-
|
527
|
-
TypedData_Get_Struct(recorder_instance,
|
512
|
+
stack_recorder_state *state;
|
513
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
528
514
|
|
529
515
|
ddog_Timespec finish_timestamp = system_epoch_now_timespec();
|
530
516
|
// Need to do this while still holding on to the Global VM Lock; see comments on method for why
|
@@ -538,7 +524,7 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
538
524
|
|
539
525
|
// We'll release the Global VM Lock while we're calling serialize, so that the Ruby VM can continue to work while this
|
540
526
|
// is pending
|
541
|
-
|
527
|
+
call_serialize_without_gvl_arguments args = {
|
542
528
|
.state = state,
|
543
529
|
.finish_timestamp = finish_timestamp,
|
544
530
|
.serialize_ran = false
|
@@ -582,18 +568,14 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
|
|
582
568
|
|
583
569
|
state->stats_lifetime.serialization_successes++;
|
584
570
|
|
585
|
-
|
586
|
-
|
587
|
-
ddog_Timespec ddprof_start = serialized_profile.ok.start;
|
588
|
-
ddog_Timespec ddprof_finish = serialized_profile.ok.end;
|
571
|
+
// Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it
|
572
|
+
VALUE encoded_profile = from_ddog_prof_EncodedProfile(serialized_profile.ok);
|
589
573
|
|
590
|
-
|
591
|
-
|
592
|
-
VALUE start = ruby_time_from(ddprof_start);
|
593
|
-
VALUE finish = ruby_time_from(ddprof_finish);
|
574
|
+
VALUE start = ruby_time_from(args.slot->start_timestamp);
|
575
|
+
VALUE finish = ruby_time_from(finish_timestamp);
|
594
576
|
VALUE profile_stats = build_profile_stats(args.slot, serialization_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
|
595
577
|
|
596
|
-
return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish,
|
578
|
+
return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_profile, profile_stats));
|
597
579
|
}
|
598
580
|
|
599
581
|
static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
|
@@ -603,8 +585,8 @@ static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
|
|
603
585
|
}
|
604
586
|
|
605
587
|
void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations, sample_values values, sample_labels labels) {
|
606
|
-
|
607
|
-
TypedData_Get_Struct(recorder_instance,
|
588
|
+
stack_recorder_state *state;
|
589
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
608
590
|
|
609
591
|
locked_profile_slot active_slot = sampler_lock_active_profile(state);
|
610
592
|
|
@@ -657,9 +639,9 @@ void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations,
|
|
657
639
|
}
|
658
640
|
}
|
659
641
|
|
660
|
-
void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample_weight, ddog_CharSlice
|
661
|
-
|
662
|
-
TypedData_Get_Struct(recorder_instance,
|
642
|
+
void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample_weight, ddog_CharSlice alloc_class) {
|
643
|
+
stack_recorder_state *state;
|
644
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
663
645
|
// FIXME: Heap sampling currently has to be done in 2 parts because the construction of locations is happening
|
664
646
|
// very late in the allocation-sampling path (which is shared with the cpu sampling path). This can
|
665
647
|
// be fixed with some refactoring but for now this leads to a less impactful change.
|
@@ -667,8 +649,8 @@ void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample
|
|
667
649
|
}
|
668
650
|
|
669
651
|
void record_endpoint(VALUE recorder_instance, uint64_t local_root_span_id, ddog_CharSlice endpoint) {
|
670
|
-
|
671
|
-
TypedData_Get_Struct(recorder_instance,
|
652
|
+
stack_recorder_state *state;
|
653
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
672
654
|
|
673
655
|
locked_profile_slot active_slot = sampler_lock_active_profile(state);
|
674
656
|
|
@@ -682,8 +664,8 @@ void record_endpoint(VALUE recorder_instance, uint64_t local_root_span_id, ddog_
|
|
682
664
|
}
|
683
665
|
|
684
666
|
void recorder_after_gc_step(VALUE recorder_instance) {
|
685
|
-
|
686
|
-
TypedData_Get_Struct(recorder_instance,
|
667
|
+
stack_recorder_state *state;
|
668
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
687
669
|
|
688
670
|
if (state->heap_clean_after_gc_enabled) heap_recorder_update_young_objects(state->heap_recorder);
|
689
671
|
}
|
@@ -693,7 +675,7 @@ void recorder_after_gc_step(VALUE recorder_instance) {
|
|
693
675
|
// Heap recorder iteration context allows us access to stack recorder state and profile being serialized
|
694
676
|
// during iteration of heap recorder live objects.
|
695
677
|
typedef struct heap_recorder_iteration_context {
|
696
|
-
|
678
|
+
stack_recorder_state *state;
|
697
679
|
profile_slot *slot;
|
698
680
|
|
699
681
|
bool error;
|
@@ -755,7 +737,7 @@ static bool add_heap_sample_to_active_profile_without_gvl(heap_recorder_iteratio
|
|
755
737
|
return true;
|
756
738
|
}
|
757
739
|
|
758
|
-
static void build_heap_profile_without_gvl(
|
740
|
+
static void build_heap_profile_without_gvl(stack_recorder_state *state, profile_slot *slot) {
|
759
741
|
heap_recorder_iteration_context iteration_context = {
|
760
742
|
.state = state,
|
761
743
|
.slot = slot,
|
@@ -776,12 +758,11 @@ static void build_heap_profile_without_gvl(struct stack_recorder_state *state, p
|
|
776
758
|
}
|
777
759
|
|
778
760
|
static void *call_serialize_without_gvl(void *call_args) {
|
779
|
-
|
761
|
+
call_serialize_without_gvl_arguments *args = (call_serialize_without_gvl_arguments *) call_args;
|
780
762
|
|
781
763
|
long serialize_no_gvl_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
|
782
764
|
|
783
765
|
profile_slot *slot_now_inactive = serializer_flip_active_and_inactive_slots(args->state);
|
784
|
-
|
785
766
|
args->slot = slot_now_inactive;
|
786
767
|
|
787
768
|
// Now that we have the inactive profile with all but heap samples, lets fill it with heap data
|
@@ -790,7 +771,7 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
790
771
|
args->heap_profile_build_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
|
791
772
|
|
792
773
|
// Note: The profile gets reset by the serialize call
|
793
|
-
args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->
|
774
|
+
args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->slot->start_timestamp, &args->finish_timestamp);
|
794
775
|
args->serialize_ran = true;
|
795
776
|
args->serialize_no_gvl_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
|
796
777
|
|
@@ -798,11 +779,11 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
798
779
|
}
|
799
780
|
|
800
781
|
VALUE enforce_recorder_instance(VALUE object) {
|
801
|
-
|
782
|
+
ENFORCE_TYPED_DATA(object, &stack_recorder_typed_data);
|
802
783
|
return object;
|
803
784
|
}
|
804
785
|
|
805
|
-
static locked_profile_slot sampler_lock_active_profile(
|
786
|
+
static locked_profile_slot sampler_lock_active_profile(stack_recorder_state *state) {
|
806
787
|
int error;
|
807
788
|
|
808
789
|
for (int attempts = 0; attempts < 2; attempts++) {
|
@@ -829,7 +810,7 @@ static void sampler_unlock_active_profile(locked_profile_slot active_slot) {
|
|
829
810
|
ENFORCE_SUCCESS_GVL(pthread_mutex_unlock(active_slot.mutex));
|
830
811
|
}
|
831
812
|
|
832
|
-
static profile_slot* serializer_flip_active_and_inactive_slots(
|
813
|
+
static profile_slot* serializer_flip_active_and_inactive_slots(stack_recorder_state *state) {
|
833
814
|
int previously_active_slot = state->active_slot;
|
834
815
|
|
835
816
|
if (previously_active_slot != 1 && previously_active_slot != 2) {
|
@@ -855,8 +836,8 @@ static profile_slot* serializer_flip_active_and_inactive_slots(struct stack_reco
|
|
855
836
|
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
856
837
|
// It SHOULD NOT be used for other purposes.
|
857
838
|
static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
858
|
-
|
859
|
-
TypedData_Get_Struct(recorder_instance,
|
839
|
+
stack_recorder_state *state;
|
840
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
860
841
|
|
861
842
|
return INT2NUM(state->active_slot);
|
862
843
|
}
|
@@ -870,8 +851,8 @@ static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE
|
|
870
851
|
static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 2); }
|
871
852
|
|
872
853
|
static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
|
873
|
-
|
874
|
-
TypedData_Get_Struct(recorder_instance,
|
854
|
+
stack_recorder_state *state;
|
855
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
875
856
|
|
876
857
|
pthread_mutex_t *slot_mutex = (slot == 1) ? &state->mutex_slot_one : &state->mutex_slot_two;
|
877
858
|
|
@@ -901,15 +882,15 @@ static ddog_Timespec system_epoch_now_timespec(void) {
|
|
901
882
|
// Assumption: This method gets called BEFORE restarting profiling -- e.g. there are no components attempting to
|
902
883
|
// trigger samples at the same time.
|
903
884
|
static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
|
904
|
-
|
905
|
-
TypedData_Get_Struct(recorder_instance,
|
885
|
+
stack_recorder_state *state;
|
886
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
906
887
|
|
907
888
|
// In case the fork happened halfway through `serializer_flip_active_and_inactive_slots` execution and the
|
908
889
|
// resulting state is inconsistent, we make sure to reset it back to the initial state.
|
909
890
|
initialize_slot_concurrency_control(state);
|
910
|
-
|
911
|
-
reset_profile_slot(&state->profile_slot_one,
|
912
|
-
reset_profile_slot(&state->profile_slot_two,
|
891
|
+
ddog_Timespec start_timestamp = system_epoch_now_timespec();
|
892
|
+
reset_profile_slot(&state->profile_slot_one, start_timestamp);
|
893
|
+
reset_profile_slot(&state->profile_slot_two, start_timestamp);
|
913
894
|
|
914
895
|
heap_recorder_after_fork(state->heap_recorder);
|
915
896
|
|
@@ -918,10 +899,10 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_
|
|
918
899
|
|
919
900
|
// Assumption 1: This method is called with the GVL being held, because `ddog_prof_Profile_reset` mutates the profile and must
|
920
901
|
// not be interrupted part-way through by a VM fork.
|
921
|
-
static void serializer_set_start_timestamp_for_next_profile(
|
902
|
+
static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time) {
|
922
903
|
// Before making this profile active, we reset it so that it uses the correct start_time for its start
|
923
904
|
profile_slot *next_profile_slot = (state->active_slot == 1) ? &state->profile_slot_two : &state->profile_slot_one;
|
924
|
-
reset_profile_slot(next_profile_slot,
|
905
|
+
reset_profile_slot(next_profile_slot, start_time);
|
925
906
|
}
|
926
907
|
|
927
908
|
static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint) {
|
@@ -932,8 +913,7 @@ static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_
|
|
932
913
|
|
933
914
|
static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class) {
|
934
915
|
ENFORCE_TYPE(weight, T_FIXNUM);
|
935
|
-
|
936
|
-
track_object(recorder_instance, new_obj, NUM2UINT(weight), &alloc_class_slice);
|
916
|
+
track_object(recorder_instance, new_obj, NUM2UINT(weight), char_slice_from_ruby_string(alloc_class));
|
937
917
|
return Qtrue;
|
938
918
|
}
|
939
919
|
|
@@ -967,19 +947,20 @@ static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locatio
|
|
967
947
|
return Qnil;
|
968
948
|
}
|
969
949
|
|
970
|
-
static void reset_profile_slot(profile_slot *slot, ddog_Timespec
|
971
|
-
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile
|
950
|
+
static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
|
951
|
+
ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile);
|
972
952
|
if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
|
973
953
|
rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
|
974
954
|
}
|
955
|
+
slot->start_timestamp = start_timestamp;
|
975
956
|
slot->stats = (stats_slot) {};
|
976
957
|
}
|
977
958
|
|
978
959
|
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
979
960
|
// It SHOULD NOT be used for other purposes.
|
980
961
|
static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
981
|
-
|
982
|
-
TypedData_Get_Struct(recorder_instance,
|
962
|
+
stack_recorder_state *state;
|
963
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
983
964
|
|
984
965
|
heap_recorder_prepare_iteration(state->heap_recorder);
|
985
966
|
|
@@ -989,8 +970,8 @@ static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _se
|
|
989
970
|
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
990
971
|
// It SHOULD NOT be used for other purposes.
|
991
972
|
static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
992
|
-
|
993
|
-
TypedData_Get_Struct(recorder_instance,
|
973
|
+
stack_recorder_state *state;
|
974
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
994
975
|
|
995
976
|
heap_recorder_finish_iteration(state->heap_recorder);
|
996
977
|
|
@@ -1000,43 +981,15 @@ static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self
|
|
1000
981
|
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
1001
982
|
// It SHOULD NOT be used for other purposes.
|
1002
983
|
static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
1003
|
-
|
1004
|
-
TypedData_Get_Struct(recorder_instance,
|
984
|
+
stack_recorder_state *state;
|
985
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
1005
986
|
|
1006
987
|
return heap_recorder_testonly_debug(state->heap_recorder);
|
1007
988
|
}
|
1008
989
|
|
1009
|
-
#pragma GCC diagnostic push
|
1010
|
-
// rb_gc_force_recycle was deprecated in latest versions of Ruby and is a noop.
|
1011
|
-
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
1012
|
-
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
1013
|
-
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
1014
|
-
// It SHOULD NOT be used for other purposes.
|
1015
|
-
static VALUE _native_gc_force_recycle(DDTRACE_UNUSED VALUE _self, VALUE obj) {
|
1016
|
-
#ifdef HAVE_WORKING_RB_GC_FORCE_RECYCLE
|
1017
|
-
rb_gc_force_recycle(obj);
|
1018
|
-
#endif
|
1019
|
-
return Qnil;
|
1020
|
-
}
|
1021
|
-
#pragma GCC diagnostic pop
|
1022
|
-
|
1023
|
-
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
1024
|
-
// It SHOULD NOT be used for other purposes.
|
1025
|
-
static VALUE _native_has_seen_id_flag(DDTRACE_UNUSED VALUE _self, VALUE obj) {
|
1026
|
-
#ifndef NO_SEEN_OBJ_ID_FLAG
|
1027
|
-
if (RB_FL_TEST(obj, RUBY_FL_SEEN_OBJ_ID)) {
|
1028
|
-
return Qtrue;
|
1029
|
-
} else {
|
1030
|
-
return Qfalse;
|
1031
|
-
}
|
1032
|
-
#else
|
1033
|
-
return Qfalse;
|
1034
|
-
#endif
|
1035
|
-
}
|
1036
|
-
|
1037
990
|
static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
|
1038
|
-
|
1039
|
-
TypedData_Get_Struct(recorder_instance,
|
991
|
+
stack_recorder_state *state;
|
992
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
1040
993
|
|
1041
994
|
uint64_t total_serializations = state->stats_lifetime.serialization_successes + state->stats_lifetime.serialization_failures;
|
1042
995
|
|
@@ -1074,15 +1027,15 @@ static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns,
|
|
1074
1027
|
static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE obj_id) {
|
1075
1028
|
ENFORCE_TYPE(obj_id, T_FIXNUM);
|
1076
1029
|
|
1077
|
-
|
1078
|
-
TypedData_Get_Struct(recorder_instance,
|
1030
|
+
stack_recorder_state *state;
|
1031
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
1079
1032
|
|
1080
1033
|
return heap_recorder_testonly_is_object_recorded(state->heap_recorder, obj_id);
|
1081
1034
|
}
|
1082
1035
|
|
1083
1036
|
static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
1084
|
-
|
1085
|
-
TypedData_Get_Struct(recorder_instance,
|
1037
|
+
stack_recorder_state *state;
|
1038
|
+
TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
|
1086
1039
|
|
1087
1040
|
heap_recorder_testonly_reset_last_update(state->heap_recorder);
|
1088
1041
|
|
@@ -13,7 +13,7 @@ typedef struct {
|
|
13
13
|
int64_t timeline_wall_time_ns;
|
14
14
|
} sample_values;
|
15
15
|
|
16
|
-
typedef struct
|
16
|
+
typedef struct {
|
17
17
|
ddog_prof_Slice_Label labels;
|
18
18
|
|
19
19
|
// This is used to allow the `Collectors::Stack` to modify the existing label, if any. This MUST be NULL or point
|
@@ -26,6 +26,6 @@ typedef struct sample_labels {
|
|
26
26
|
|
27
27
|
void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations, sample_values values, sample_labels labels);
|
28
28
|
void record_endpoint(VALUE recorder_instance, uint64_t local_root_span_id, ddog_CharSlice endpoint);
|
29
|
-
void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample_weight, ddog_CharSlice
|
29
|
+
void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample_weight, ddog_CharSlice alloc_class);
|
30
30
|
void recorder_after_gc_step(VALUE recorder_instance);
|
31
31
|
VALUE enforce_recorder_instance(VALUE object);
|
@@ -39,7 +39,7 @@ static inline long system_epoch_time_now_ns(raise_on_failure_setting raise_on_fa
|
|
39
39
|
// https://docs.redhat.com/en/documentation/red_hat_enterprise_linux_for_real_time/7/html/reference_guide/sect-posix_clocks#Using_clock_getres_to_compare_clock_resolution
|
40
40
|
// We introduce here a separate type for it, so as to make it harder to misuse/more explicit when these timestamps are used
|
41
41
|
|
42
|
-
typedef struct
|
42
|
+
typedef struct {
|
43
43
|
long timestamp_ns;
|
44
44
|
} coarse_instant;
|
45
45
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ruby/debug.h>
|
3
|
+
#include <stdbool.h>
|
4
|
+
|
5
|
+
#include "datadog_ruby_common.h"
|
6
|
+
#include "unsafe_api_calls_check.h"
|
7
|
+
#include "extconf.h"
|
8
|
+
|
9
|
+
static bool inside_unsafe_context = false;
|
10
|
+
|
11
|
+
#ifndef NO_POSTPONED_TRIGGER
|
12
|
+
static rb_postponed_job_handle_t check_for_unsafe_api_calls_handle;
|
13
|
+
#endif
|
14
|
+
|
15
|
+
static void check_for_unsafe_api_calls(DDTRACE_UNUSED void *_unused);
|
16
|
+
|
17
|
+
void unsafe_api_calls_check_init(void) {
|
18
|
+
#ifndef NO_POSTPONED_TRIGGER
|
19
|
+
int unused_flags = 0;
|
20
|
+
|
21
|
+
check_for_unsafe_api_calls_handle = rb_postponed_job_preregister(unused_flags, check_for_unsafe_api_calls, NULL);
|
22
|
+
|
23
|
+
if (check_for_unsafe_api_calls_handle == POSTPONED_JOB_HANDLE_INVALID) {
|
24
|
+
rb_raise(rb_eRuntimeError, "Failed to register check_for_unsafe_api_calls_handle postponed job (got POSTPONED_JOB_HANDLE_INVALID)");
|
25
|
+
}
|
26
|
+
#endif
|
27
|
+
}
|
28
|
+
|
29
|
+
void debug_enter_unsafe_context(void) {
|
30
|
+
inside_unsafe_context = true;
|
31
|
+
|
32
|
+
#ifndef NO_POSTPONED_TRIGGER
|
33
|
+
rb_postponed_job_trigger(check_for_unsafe_api_calls_handle);
|
34
|
+
#else
|
35
|
+
rb_postponed_job_register(0, check_for_unsafe_api_calls, NULL);
|
36
|
+
#endif
|
37
|
+
}
|
38
|
+
|
39
|
+
void debug_leave_unsafe_context(void) {
|
40
|
+
inside_unsafe_context = false;
|
41
|
+
}
|
42
|
+
|
43
|
+
static void check_for_unsafe_api_calls(DDTRACE_UNUSED void *_unused) {
|
44
|
+
if (inside_unsafe_context) rb_bug(
|
45
|
+
"Datadog Ruby profiler detected callback nested inside sample. Please report this at https://github.com/datadog/dd-trace-rb/blob/master/CONTRIBUTING.md#found-a-bug"
|
46
|
+
);
|
47
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
// This checker is used to detect accidental thread scheduling switching points happening during profiling sampling.
|
4
|
+
//
|
5
|
+
// Specifically, when the profiler is sampling, we're never supposed to call into Ruby code (e.g. methods
|
6
|
+
// implemented using Ruby code) or allocate Ruby objects.
|
7
|
+
// That's because those events introduce thread switch points, and really we don't the VM switching between threads
|
8
|
+
// in the middle of the profiler sampling.
|
9
|
+
// This includes raising exceptions, unless we're trying to stop the profiler, and even then we must be careful.
|
10
|
+
//
|
11
|
+
// The above is especially true in situations such as GC profiling or allocation/heap profiling, as in those situations
|
12
|
+
// we can even crash the Ruby VM if we switch away at the wrong time.
|
13
|
+
//
|
14
|
+
// The below APIs can be used to detect these situations. They work by relying on the following observation:
|
15
|
+
// in most (all?) thread switch points, Ruby will check for interrupts and run the postponed jobs.
|
16
|
+
//
|
17
|
+
// Thus, if we set a flag while we're sampling (inside_unsafe_context), trigger the postponed job, and then only unset
|
18
|
+
// the flag after sampling, he correct thing to happen is that the postponed job should never see the flag.
|
19
|
+
//
|
20
|
+
// If, however, we have a bug and there's a thread switch point, our postponed job will see the flag and immediately
|
21
|
+
// stop the Ruby VM before further damage happens (and hopefully giving us a stack trace clearly pointing to the culprit).
|
22
|
+
|
23
|
+
void unsafe_api_calls_check_init(void);
|
24
|
+
|
25
|
+
// IMPORTANT: This method **MUST** only be called from test code, as it causes an immediate hard-crash on the Ruby VM
|
26
|
+
// when it detects a potential issue, and that's not something we want for production apps.
|
27
|
+
//
|
28
|
+
// In the future we may introduce some kind of setting (off by default) to also allow this to be safely be used
|
29
|
+
// in production code if needed.
|
30
|
+
void debug_enter_unsafe_context(void);
|
31
|
+
void debug_leave_unsafe_context(void);
|