datadog 2.12.1 → 2.19.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 +243 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +63 -56
- data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -76
- data/ext/datadog_profiling_native_extension/collectors_stack.h +20 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +78 -26
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- 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 +10 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +247 -364
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/http_transport.c +60 -94
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +41 -21
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -4
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +173 -76
- data/ext/libdatadog_api/crashtracker.c +11 -12
- 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/extconf.rb +2 -2
- data/ext/libdatadog_api/init.c +15 -0
- data/ext/libdatadog_api/library_config.c +164 -0
- data/ext/libdatadog_api/library_config.h +25 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +112 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
- data/lib/datadog/appsec/actions_handler.rb +24 -2
- data/lib/datadog/appsec/anonymizer.rb +16 -0
- data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +71 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +23 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +46 -61
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +153 -30
- data/lib/datadog/appsec/context.rb +7 -7
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +10 -12
- data/lib/datadog/appsec/contrib/active_record/integration.rb +2 -2
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +22 -22
- data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/configuration.rb +7 -31
- 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 +34 -23
- 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} +2 -2
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
- data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +9 -10
- data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +8 -9
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +8 -9
- data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +49 -32
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +42 -30
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +11 -13
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +21 -21
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +10 -11
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -23
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/event.rb +96 -135
- data/lib/datadog/appsec/ext.rb +4 -2
- 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/telemetry.rb +1 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +49 -14
- data/lib/datadog/appsec/processor/rule_loader.rb +30 -33
- data/lib/datadog/appsec/remote.rb +31 -59
- data/lib/datadog/appsec/response.rb +6 -6
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +13 -14
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec/utils.rb +0 -2
- data/lib/datadog/appsec.rb +5 -8
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -46
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +48 -31
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/ext.rb +4 -0
- data/lib/datadog/core/configuration/option.rb +81 -45
- data/lib/datadog/core/configuration/option_definition.rb +4 -4
- data/lib/datadog/core/configuration/options.rb +3 -3
- data/lib/datadog/core/configuration/settings.rb +109 -44
- data/lib/datadog/core/configuration/stable_config.rb +22 -0
- data/lib/datadog/core/configuration.rb +40 -16
- data/lib/datadog/core/crashtracking/component.rb +3 -10
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/encoding.rb +1 -1
- data/lib/datadog/core/environment/agent_info.rb +4 -3
- 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 +20 -21
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +36 -0
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client.rb +40 -32
- data/lib/datadog/core/remote/component.rb +6 -9
- 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 +14 -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/client.rb +5 -4
- data/lib/datadog/core/remote/transport/http/config.rb +27 -37
- data/lib/datadog/core/remote/transport/http/negotiation.rb +7 -33
- data/lib/datadog/core/remote/transport/http.rb +22 -57
- data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
- data/lib/datadog/core/runtime/metrics.rb +12 -5
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +81 -52
- data/lib/datadog/core/telemetry/emitter.rb +23 -11
- 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_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 +17 -472
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +11 -5
- data/lib/datadog/core/telemetry/metric.rb +8 -8
- 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 +90 -24
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/api/instance.rb +17 -0
- data/lib/datadog/core/transport/http/api/spec.rb +17 -0
- data/lib/datadog/core/transport/http/builder.rb +19 -17
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/transport/http.rb +39 -2
- 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/utils.rb +7 -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/boot.rb +34 -0
- data/lib/datadog/di/component.rb +0 -2
- data/lib/datadog/di/instrumenter.rb +48 -5
- data/lib/datadog/di/probe_notification_builder.rb +38 -43
- data/lib/datadog/di/probe_notifier_worker.rb +25 -17
- data/lib/datadog/di/remote.rb +2 -0
- data/lib/datadog/di/serializer.rb +10 -2
- data/lib/datadog/di/transport/diagnostics.rb +4 -3
- data/lib/datadog/di/transport/http/api.rb +2 -12
- data/lib/datadog/di/transport/http/client.rb +4 -3
- data/lib/datadog/di/transport/http/diagnostics.rb +7 -34
- data/lib/datadog/di/transport/http/input.rb +18 -35
- data/lib/datadog/di/transport/http.rb +14 -62
- data/lib/datadog/di/transport/input.rb +14 -5
- data/lib/datadog/di/utils.rb +5 -0
- data/lib/datadog/di.rb +0 -33
- 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 +195 -0
- data/lib/datadog/kit/appsec/events.rb +12 -0
- data/lib/datadog/kit/identity.rb +5 -1
- 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 +18 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/info.rb +44 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +17 -2
- data/lib/datadog/profiling/component.rb +8 -9
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +12 -7
- data/lib/datadog/profiling/ext.rb +0 -14
- data/lib/datadog/profiling/flush.rb +5 -8
- data/lib/datadog/profiling/http_transport.rb +7 -61
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +10 -2
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +9 -9
- data/lib/datadog/profiling/tag_builder.rb +7 -41
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/profiling.rb +7 -2
- data/lib/datadog/single_step_instrument.rb +9 -0
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/component.rb +15 -12
- data/lib/datadog/tracing/configuration/ext.rb +7 -1
- data/lib/datadog/tracing/configuration/settings.rb +18 -2
- data/lib/datadog/tracing/context_provider.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +11 -2
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -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/faraday/middleware.rb +5 -3
- 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/httpclient/instrumentation.rb +6 -16
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
- 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/lograge/patcher.rb +4 -2
- 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/subscribers.rb +18 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -6
- 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/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +61 -40
- 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/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- 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/diagnostics/environment_logger.rb +3 -1
- 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 +10 -1
- data/lib/datadog/tracing/span_event.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +68 -16
- data/lib/datadog/tracing/sync_writer.rb +2 -3
- data/lib/datadog/tracing/trace_digest.rb +9 -2
- data/lib/datadog/tracing/trace_operation.rb +55 -27
- data/lib/datadog/tracing/trace_segment.rb +6 -4
- data/lib/datadog/tracing/tracer.rb +51 -7
- data/lib/datadog/tracing/transport/http/api.rb +2 -10
- data/lib/datadog/tracing/transport/http/client.rb +5 -4
- data/lib/datadog/tracing/transport/http/traces.rb +13 -41
- data/lib/datadog/tracing/transport/http.rb +11 -44
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
- data/lib/datadog/tracing/transport/traces.rb +26 -9
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
- data/lib/datadog/tracing/writer.rb +2 -6
- data/lib/datadog/tracing.rb +16 -3
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +8 -2
- metadata +88 -23
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
- data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
- data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
- data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
- data/lib/datadog/appsec/processor.rb +0 -107
- data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
- 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
@@ -34,7 +34,7 @@ typedef struct {
|
|
34
34
|
|
35
35
|
// The class of the object that we're tracking.
|
36
36
|
// NOTE: This is optional and will be set to NULL if not set.
|
37
|
-
|
37
|
+
ddog_prof_ManagedStringId class;
|
38
38
|
|
39
39
|
// The GC allocation gen in which we saw this object being allocated.
|
40
40
|
//
|
@@ -59,7 +59,7 @@ typedef struct {
|
|
59
59
|
} heap_recorder_iteration_data;
|
60
60
|
|
61
61
|
// Initialize a new heap recorder.
|
62
|
-
heap_recorder* heap_recorder_new(
|
62
|
+
heap_recorder* heap_recorder_new(ddog_prof_ManagedStringStorage string_storage);
|
63
63
|
|
64
64
|
// Free a previously initialized heap recorder.
|
65
65
|
void heap_recorder_free(heap_recorder *heap_recorder);
|
@@ -164,10 +164,6 @@ VALUE heap_recorder_state_snapshot(heap_recorder *heap_recorder);
|
|
164
164
|
|
165
165
|
// v--- TEST-ONLY APIs ---v
|
166
166
|
|
167
|
-
// Assert internal hashing logic is valid for the provided locations and its
|
168
|
-
// corresponding internal representations in heap recorder.
|
169
|
-
void heap_recorder_testonly_assert_hash_matches(ddog_prof_Slice_Location locations);
|
170
|
-
|
171
167
|
// Returns a Ruby string with a representation of internal data helpful to
|
172
168
|
// troubleshoot issues such as unexpected test failures.
|
173
169
|
VALUE heap_recorder_testonly_debug(heap_recorder *heap_recorder);
|
@@ -177,3 +173,5 @@ VALUE heap_recorder_testonly_is_object_recorded(heap_recorder *heap_recorder, VA
|
|
177
173
|
|
178
174
|
// Used to ensure that a GC actually triggers an update of the objects
|
179
175
|
void heap_recorder_testonly_reset_last_update(heap_recorder *heap_recorder);
|
176
|
+
|
177
|
+
void heap_recorder_testonly_benchmark_intern(heap_recorder *heap_recorder, ddog_CharSlice string, int times, bool use_all);
|
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "helpers.h"
|
5
5
|
#include "libdatadog_helpers.h"
|
6
6
|
#include "ruby_helpers.h"
|
7
|
+
#include "encoded_profile.h"
|
7
8
|
|
8
9
|
// Used to report profiling data to Datadog.
|
9
10
|
// This file implements the native bits of the Datadog::Profiling::HttpTransport class
|
@@ -14,32 +15,22 @@ static VALUE error_symbol = Qnil; // :error in Ruby
|
|
14
15
|
static VALUE library_version_string = Qnil;
|
15
16
|
|
16
17
|
typedef struct {
|
17
|
-
|
18
|
-
|
18
|
+
ddog_prof_ProfileExporter *exporter;
|
19
|
+
ddog_prof_Request_Result *build_result;
|
19
20
|
ddog_CancellationToken *cancel_token;
|
20
|
-
|
21
|
+
ddog_prof_Result_HttpStatus result;
|
21
22
|
bool send_ran;
|
22
23
|
} call_exporter_without_gvl_arguments;
|
23
24
|
|
24
25
|
static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
|
25
26
|
static VALUE _native_validate_exporter(VALUE self, VALUE exporter_configuration);
|
26
|
-
static
|
27
|
-
static VALUE handle_exporter_failure(
|
27
|
+
static ddog_prof_ProfileExporter_Result create_exporter(VALUE exporter_configuration, VALUE tags_as_array);
|
28
|
+
static VALUE handle_exporter_failure(ddog_prof_ProfileExporter_Result exporter_result);
|
28
29
|
static VALUE _native_do_export(
|
29
30
|
VALUE self,
|
30
31
|
VALUE exporter_configuration,
|
31
32
|
VALUE upload_timeout_milliseconds,
|
32
|
-
VALUE
|
33
|
-
VALUE start_timespec_nanoseconds,
|
34
|
-
VALUE finish_timespec_seconds,
|
35
|
-
VALUE finish_timespec_nanoseconds,
|
36
|
-
VALUE pprof_file_name,
|
37
|
-
VALUE pprof_data,
|
38
|
-
VALUE code_provenance_file_name,
|
39
|
-
VALUE code_provenance_data,
|
40
|
-
VALUE tags_as_array,
|
41
|
-
VALUE internal_metadata_json,
|
42
|
-
VALUE info_json
|
33
|
+
VALUE flush
|
43
34
|
);
|
44
35
|
static void *call_exporter_without_gvl(void *call_args);
|
45
36
|
static void interrupt_exporter_call(void *cancel_token);
|
@@ -48,7 +39,7 @@ void http_transport_init(VALUE profiling_module) {
|
|
48
39
|
VALUE http_transport_class = rb_define_class_under(profiling_module, "HttpTransport", rb_cObject);
|
49
40
|
|
50
41
|
rb_define_singleton_method(http_transport_class, "_native_validate_exporter", _native_validate_exporter, 1);
|
51
|
-
rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export,
|
42
|
+
rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 3);
|
52
43
|
|
53
44
|
ok_symbol = ID2SYM(rb_intern_const("ok"));
|
54
45
|
error_symbol = ID2SYM(rb_intern_const("error"));
|
@@ -65,14 +56,14 @@ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
|
|
65
56
|
|
66
57
|
static VALUE _native_validate_exporter(DDTRACE_UNUSED VALUE _self, VALUE exporter_configuration) {
|
67
58
|
ENFORCE_TYPE(exporter_configuration, T_ARRAY);
|
68
|
-
|
59
|
+
ddog_prof_ProfileExporter_Result exporter_result = create_exporter(exporter_configuration, rb_ary_new());
|
69
60
|
|
70
61
|
VALUE failure_tuple = handle_exporter_failure(exporter_result);
|
71
62
|
if (!NIL_P(failure_tuple)) return failure_tuple;
|
72
63
|
|
73
64
|
// We don't actually need the exporter for now -- we just wanted to validate that we could create it with the
|
74
65
|
// settings we were given
|
75
|
-
ddog_prof_Exporter_drop(exporter_result.ok);
|
66
|
+
ddog_prof_Exporter_drop(&exporter_result.ok);
|
76
67
|
|
77
68
|
return rb_ary_new_from_args(2, ok_symbol, Qnil);
|
78
69
|
}
|
@@ -84,26 +75,21 @@ static ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
|
|
84
75
|
ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
|
85
76
|
ID working_mode = SYM2ID(exporter_working_mode);
|
86
77
|
|
87
|
-
|
88
|
-
ID agent_id = rb_intern("agent");
|
89
|
-
|
90
|
-
if (working_mode != agentless_id && working_mode != agent_id) {
|
91
|
-
rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
|
92
|
-
}
|
93
|
-
|
94
|
-
if (working_mode == agentless_id) {
|
78
|
+
if (working_mode == rb_intern("agentless")) {
|
95
79
|
VALUE site = rb_ary_entry(exporter_configuration, 1);
|
96
80
|
VALUE api_key = rb_ary_entry(exporter_configuration, 2);
|
97
81
|
|
98
82
|
return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
|
99
|
-
} else
|
83
|
+
} else if (working_mode == rb_intern("agent")) {
|
100
84
|
VALUE base_url = rb_ary_entry(exporter_configuration, 1);
|
101
85
|
|
102
86
|
return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
|
87
|
+
} else {
|
88
|
+
rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
|
103
89
|
}
|
104
90
|
}
|
105
91
|
|
106
|
-
static
|
92
|
+
static ddog_prof_ProfileExporter_Result create_exporter(VALUE exporter_configuration, VALUE tags_as_array) {
|
107
93
|
ENFORCE_TYPE(exporter_configuration, T_ARRAY);
|
108
94
|
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
109
95
|
|
@@ -117,7 +103,7 @@ static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration
|
|
117
103
|
ddog_CharSlice library_version = char_slice_from_ruby_string(library_version_string);
|
118
104
|
ddog_CharSlice profiling_family = DDOG_CHARSLICE_C("ruby");
|
119
105
|
|
120
|
-
|
106
|
+
ddog_prof_ProfileExporter_Result exporter_result =
|
121
107
|
ddog_prof_Exporter_new(library_name, library_version, profiling_family, &tags, endpoint);
|
122
108
|
|
123
109
|
ddog_Vec_Tag_drop(tags);
|
@@ -125,8 +111,12 @@ static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration
|
|
125
111
|
return exporter_result;
|
126
112
|
}
|
127
113
|
|
128
|
-
static
|
129
|
-
|
114
|
+
static void validate_token(ddog_CancellationToken token, const char *file, int line) {
|
115
|
+
if (token.inner == NULL) rb_raise(rb_eRuntimeError, "Unexpected: Validation token was empty at %s:%d", file, line);
|
116
|
+
}
|
117
|
+
|
118
|
+
static VALUE handle_exporter_failure(ddog_prof_ProfileExporter_Result exporter_result) {
|
119
|
+
return exporter_result.tag == DDOG_PROF_PROFILE_EXPORTER_RESULT_OK_HANDLE_PROFILE_EXPORTER ?
|
130
120
|
Qnil :
|
131
121
|
rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&exporter_result.err));
|
132
122
|
}
|
@@ -134,39 +124,37 @@ static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_resul
|
|
134
124
|
// Note: This function handles a bunch of libdatadog dynamically-allocated objects, so it MUST not use any Ruby APIs
|
135
125
|
// which can raise exceptions, otherwise the objects will be leaked.
|
136
126
|
static VALUE perform_export(
|
137
|
-
|
138
|
-
|
139
|
-
ddog_Timespec finish,
|
127
|
+
ddog_prof_ProfileExporter *exporter,
|
128
|
+
ddog_prof_EncodedProfile *profile,
|
140
129
|
ddog_prof_Exporter_Slice_File files_to_compress_and_export,
|
141
|
-
ddog_prof_Exporter_Slice_File files_to_export_unmodified,
|
142
|
-
ddog_Vec_Tag *additional_tags,
|
143
130
|
ddog_CharSlice internal_metadata,
|
144
131
|
ddog_CharSlice info
|
145
132
|
) {
|
146
|
-
|
147
|
-
ddog_prof_Exporter_Request_BuildResult build_result = ddog_prof_Exporter_Request_build(
|
133
|
+
ddog_prof_Request_Result build_result = ddog_prof_Exporter_Request_build(
|
148
134
|
exporter,
|
149
|
-
|
150
|
-
finish,
|
135
|
+
profile,
|
151
136
|
files_to_compress_and_export,
|
152
|
-
files_to_export_unmodified,
|
153
|
-
|
154
|
-
endpoints_stats,
|
137
|
+
/* files_to_export_unmodified: */ ddog_prof_Exporter_Slice_File_empty(),
|
138
|
+
/* optional_additional_tags: */ NULL,
|
155
139
|
&internal_metadata,
|
156
140
|
&info
|
157
141
|
);
|
158
142
|
|
159
|
-
if (build_result.tag ==
|
143
|
+
if (build_result.tag == DDOG_PROF_REQUEST_RESULT_ERR_HANDLE_REQUEST) {
|
160
144
|
ddog_prof_Exporter_drop(exporter);
|
161
145
|
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&build_result.err));
|
162
146
|
}
|
163
147
|
|
164
|
-
ddog_CancellationToken
|
148
|
+
ddog_CancellationToken cancel_token_request = ddog_CancellationToken_new();
|
149
|
+
ddog_CancellationToken cancel_token_interrupt = ddog_CancellationToken_clone(&cancel_token_request);
|
150
|
+
|
151
|
+
validate_token(cancel_token_request, __FILE__, __LINE__);
|
152
|
+
validate_token(cancel_token_interrupt, __FILE__, __LINE__);
|
165
153
|
|
166
154
|
// We'll release the Global VM Lock while we're calling send, so that the Ruby VM can continue to work while this
|
167
155
|
// is pending
|
168
156
|
call_exporter_without_gvl_arguments args =
|
169
|
-
{.exporter = exporter, .build_result = &build_result, .cancel_token =
|
157
|
+
{.exporter = exporter, .build_result = &build_result, .cancel_token = &cancel_token_request, .send_ran = false};
|
170
158
|
|
171
159
|
// We use rb_thread_call_without_gvl2 instead of rb_thread_call_without_gvl as the gvl2 variant never raises any
|
172
160
|
// exceptions.
|
@@ -183,14 +171,15 @@ static VALUE perform_export(
|
|
183
171
|
int pending_exception = 0;
|
184
172
|
|
185
173
|
while (!args.send_ran && !pending_exception) {
|
186
|
-
rb_thread_call_without_gvl2(call_exporter_without_gvl, &args, interrupt_exporter_call,
|
174
|
+
rb_thread_call_without_gvl2(call_exporter_without_gvl, &args, interrupt_exporter_call, &cancel_token_interrupt);
|
187
175
|
|
188
176
|
// To make sure we don't leak memory, we never check for pending exceptions if send ran
|
189
177
|
if (!args.send_ran) pending_exception = check_if_pending_exception();
|
190
178
|
}
|
191
179
|
|
192
180
|
// Cleanup exporter and token, no longer needed
|
193
|
-
ddog_CancellationToken_drop(
|
181
|
+
ddog_CancellationToken_drop(&cancel_token_request);
|
182
|
+
ddog_CancellationToken_drop(&cancel_token_interrupt);
|
194
183
|
ddog_prof_Exporter_drop(exporter);
|
195
184
|
|
196
185
|
if (pending_exception) {
|
@@ -203,10 +192,10 @@ static VALUE perform_export(
|
|
203
192
|
|
204
193
|
// The request itself does not need to be freed as libdatadog takes ownership of it as part of sending.
|
205
194
|
|
206
|
-
|
195
|
+
ddog_prof_Result_HttpStatus result = args.result;
|
207
196
|
|
208
|
-
return result.tag ==
|
209
|
-
rb_ary_new_from_args(2, ok_symbol, UINT2NUM(result.
|
197
|
+
return result.tag == DDOG_PROF_RESULT_HTTP_STATUS_OK_HTTP_STATUS ?
|
198
|
+
rb_ary_new_from_args(2, ok_symbol, UINT2NUM(result.ok.code)) :
|
210
199
|
rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&result.err));
|
211
200
|
}
|
212
201
|
|
@@ -214,26 +203,19 @@ static VALUE _native_do_export(
|
|
214
203
|
DDTRACE_UNUSED VALUE _self,
|
215
204
|
VALUE exporter_configuration,
|
216
205
|
VALUE upload_timeout_milliseconds,
|
217
|
-
VALUE
|
218
|
-
VALUE start_timespec_nanoseconds,
|
219
|
-
VALUE finish_timespec_seconds,
|
220
|
-
VALUE finish_timespec_nanoseconds,
|
221
|
-
VALUE pprof_file_name,
|
222
|
-
VALUE pprof_data,
|
223
|
-
VALUE code_provenance_file_name,
|
224
|
-
VALUE code_provenance_data,
|
225
|
-
VALUE tags_as_array,
|
226
|
-
VALUE internal_metadata_json,
|
227
|
-
VALUE info_json
|
206
|
+
VALUE flush
|
228
207
|
) {
|
208
|
+
VALUE encoded_profile = rb_funcall(flush, rb_intern("encoded_profile"), 0);
|
209
|
+
VALUE code_provenance_file_name = rb_funcall(flush, rb_intern("code_provenance_file_name"), 0);
|
210
|
+
VALUE code_provenance_data = rb_funcall(flush, rb_intern("code_provenance_data"), 0);
|
211
|
+
VALUE tags_as_array = rb_funcall(flush, rb_intern("tags_as_array"), 0);
|
212
|
+
VALUE internal_metadata_json = rb_funcall(flush, rb_intern("internal_metadata_json"), 0);
|
213
|
+
VALUE info_json = rb_funcall(flush, rb_intern("info_json"), 0);
|
214
|
+
|
229
215
|
ENFORCE_TYPE(upload_timeout_milliseconds, T_FIXNUM);
|
230
|
-
|
231
|
-
ENFORCE_TYPE(start_timespec_nanoseconds, T_FIXNUM);
|
232
|
-
ENFORCE_TYPE(finish_timespec_seconds, T_FIXNUM);
|
233
|
-
ENFORCE_TYPE(finish_timespec_nanoseconds, T_FIXNUM);
|
234
|
-
ENFORCE_TYPE(pprof_file_name, T_STRING);
|
235
|
-
ENFORCE_TYPE(pprof_data, T_STRING);
|
216
|
+
enforce_encoded_profile_instance(encoded_profile);
|
236
217
|
ENFORCE_TYPE(code_provenance_file_name, T_STRING);
|
218
|
+
ENFORCE_TYPE(tags_as_array, T_ARRAY);
|
237
219
|
ENFORCE_TYPE(internal_metadata_json, T_STRING);
|
238
220
|
ENFORCE_TYPE(info_json, T_STRING);
|
239
221
|
|
@@ -243,23 +225,9 @@ static VALUE _native_do_export(
|
|
243
225
|
|
244
226
|
uint64_t timeout_milliseconds = NUM2ULONG(upload_timeout_milliseconds);
|
245
227
|
|
246
|
-
ddog_Timespec start =
|
247
|
-
{.seconds = NUM2LONG(start_timespec_seconds), .nanoseconds = NUM2UINT(start_timespec_nanoseconds)};
|
248
|
-
ddog_Timespec finish =
|
249
|
-
{.seconds = NUM2LONG(finish_timespec_seconds), .nanoseconds = NUM2UINT(finish_timespec_nanoseconds)};
|
250
|
-
|
251
228
|
int to_compress_length = have_code_provenance ? 1 : 0;
|
252
229
|
ddog_prof_Exporter_File to_compress[to_compress_length];
|
253
|
-
int already_compressed_length = 1; // pprof
|
254
|
-
ddog_prof_Exporter_File already_compressed[already_compressed_length];
|
255
|
-
|
256
230
|
ddog_prof_Exporter_Slice_File files_to_compress_and_export = {.ptr = to_compress, .len = to_compress_length};
|
257
|
-
ddog_prof_Exporter_Slice_File files_to_export_unmodified = {.ptr = already_compressed, .len = already_compressed_length};
|
258
|
-
|
259
|
-
already_compressed[0] = (ddog_prof_Exporter_File) {
|
260
|
-
.name = char_slice_from_ruby_string(pprof_file_name),
|
261
|
-
.file = byte_slice_from_ruby_string(pprof_data),
|
262
|
-
};
|
263
231
|
|
264
232
|
if (have_code_provenance) {
|
265
233
|
to_compress[0] = (ddog_prof_Exporter_File) {
|
@@ -268,32 +236,28 @@ static VALUE _native_do_export(
|
|
268
236
|
};
|
269
237
|
}
|
270
238
|
|
271
|
-
ddog_Vec_Tag *null_additional_tags = NULL;
|
272
239
|
ddog_CharSlice internal_metadata = char_slice_from_ruby_string(internal_metadata_json);
|
273
240
|
ddog_CharSlice info = char_slice_from_ruby_string(info_json);
|
274
241
|
|
275
|
-
|
242
|
+
ddog_prof_ProfileExporter_Result exporter_result = create_exporter(exporter_configuration, tags_as_array);
|
276
243
|
// Note: Do not add anything that can raise exceptions after this line, as otherwise the exporter memory will leak
|
277
244
|
|
278
245
|
VALUE failure_tuple = handle_exporter_failure(exporter_result);
|
279
246
|
if (!NIL_P(failure_tuple)) return failure_tuple;
|
280
247
|
|
281
|
-
|
282
|
-
if (timeout_result.tag ==
|
248
|
+
ddog_VoidResult timeout_result = ddog_prof_Exporter_set_timeout(&exporter_result.ok, timeout_milliseconds);
|
249
|
+
if (timeout_result.tag == DDOG_VOID_RESULT_ERR) {
|
283
250
|
// NOTE: Seems a bit harsh to fail the upload if we can't set a timeout. OTOH, this is only expected to fail
|
284
251
|
// if the exporter is not well built. Because such a situation should already be caught above I think it's
|
285
252
|
// preferable to leave this here as a virtually unreachable exception rather than ignoring it.
|
286
|
-
ddog_prof_Exporter_drop(exporter_result.ok);
|
287
|
-
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.
|
253
|
+
ddog_prof_Exporter_drop(&exporter_result.ok);
|
254
|
+
return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.err));
|
288
255
|
}
|
289
256
|
|
290
257
|
return perform_export(
|
291
|
-
exporter_result.ok,
|
292
|
-
|
293
|
-
finish,
|
258
|
+
&exporter_result.ok,
|
259
|
+
to_ddog_prof_EncodedProfile(encoded_profile),
|
294
260
|
files_to_compress_and_export,
|
295
|
-
files_to_export_unmodified,
|
296
|
-
null_additional_tags,
|
297
261
|
internal_metadata,
|
298
262
|
info
|
299
263
|
);
|
@@ -310,5 +274,7 @@ static void *call_exporter_without_gvl(void *call_args) {
|
|
310
274
|
|
311
275
|
// Called by Ruby when it wants to interrupt call_exporter_without_gvl above, e.g. when the app wants to exit cleanly
|
312
276
|
static void interrupt_exporter_call(void *cancel_token) {
|
277
|
+
// TODO: False here can mean two things: it was already cancelled OR it failed to cancel.
|
278
|
+
// Would be nice to change libdatadog to be able to distinguish between them...
|
313
279
|
ddog_CancellationToken_cancel((ddog_CancellationToken *) cancel_token);
|
314
280
|
}
|
@@ -60,3 +60,25 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
|
|
60
60
|
ddog_Error_drop(error);
|
61
61
|
return error_msg_size;
|
62
62
|
}
|
63
|
+
|
64
|
+
ddog_prof_ManagedStringId intern_or_raise(ddog_prof_ManagedStringStorage string_storage, ddog_CharSlice string) {
|
65
|
+
if (string.len == 0) return (ddog_prof_ManagedStringId) { 0 }; // Id 0 is always an empty string, no need to ask
|
66
|
+
|
67
|
+
ddog_prof_ManagedStringStorageInternResult intern_result = ddog_prof_ManagedStringStorage_intern(string_storage, string);
|
68
|
+
if (intern_result.tag == DDOG_PROF_MANAGED_STRING_STORAGE_INTERN_RESULT_ERR) {
|
69
|
+
rb_raise(rb_eRuntimeError, "Failed to intern string: %"PRIsVALUE, get_error_details_and_drop(&intern_result.err));
|
70
|
+
}
|
71
|
+
return intern_result.ok;
|
72
|
+
}
|
73
|
+
|
74
|
+
void intern_all_or_raise(
|
75
|
+
ddog_prof_ManagedStringStorage string_storage,
|
76
|
+
ddog_prof_Slice_CharSlice strings,
|
77
|
+
ddog_prof_ManagedStringId *output_ids,
|
78
|
+
uintptr_t output_ids_size
|
79
|
+
) {
|
80
|
+
ddog_prof_MaybeError result = ddog_prof_ManagedStringStorage_intern_all(string_storage, strings, output_ids, output_ids_size);
|
81
|
+
if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
|
82
|
+
rb_raise(rb_eRuntimeError, "Failed to intern_all: %"PRIsVALUE, get_error_details_and_drop(&result.some));
|
83
|
+
}
|
84
|
+
}
|
@@ -18,8 +18,11 @@ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capa
|
|
18
18
|
const char *ruby_value_type_to_string(enum ruby_value_type type);
|
19
19
|
ddog_CharSlice ruby_value_type_to_char_slice(enum ruby_value_type type);
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
ddog_prof_ManagedStringId intern_or_raise(ddog_prof_ManagedStringStorage string_storage, ddog_CharSlice string);
|
22
|
+
|
23
|
+
void intern_all_or_raise(
|
24
|
+
ddog_prof_ManagedStringStorage string_storage,
|
25
|
+
ddog_prof_Slice_CharSlice strings,
|
26
|
+
ddog_prof_ManagedStringId *output_ids,
|
27
|
+
uintptr_t output_ids_size
|
28
|
+
);
|
@@ -212,21 +212,6 @@ uint64_t native_thread_id_for(VALUE thread) {
|
|
212
212
|
#endif
|
213
213
|
}
|
214
214
|
|
215
|
-
// Returns the stack depth by using the same approach as rb_profile_frames and backtrace_each: get the positions
|
216
|
-
// of the end and current frame pointers and subtracting them.
|
217
|
-
ptrdiff_t stack_depth_for(VALUE thread) {
|
218
|
-
const rb_execution_context_t *ec = thread_struct_from_object(thread)->ec;
|
219
|
-
const rb_control_frame_t *cfp = ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
|
220
|
-
|
221
|
-
if (end_cfp == NULL) return 0;
|
222
|
-
|
223
|
-
// Skip dummy frame, as seen in `backtrace_each` (`vm_backtrace.c`) and our custom rb_profile_frames
|
224
|
-
// ( https://github.com/ruby/ruby/blob/4bd38e8120f2fdfdd47a34211720e048502377f1/vm_backtrace.c#L890-L914 )
|
225
|
-
end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
|
226
|
-
|
227
|
-
return end_cfp <= cfp ? 0 : end_cfp - cfp - 1;
|
228
|
-
}
|
229
|
-
|
230
215
|
// This was renamed in Ruby 3.2
|
231
216
|
#if !defined(ccan_list_for_each) && defined(list_for_each)
|
232
217
|
#define ccan_list_for_each list_for_each
|
@@ -312,6 +297,7 @@ VALUE thread_name_for(VALUE thread) {
|
|
312
297
|
// to support our custom rb_profile_frames (see below)
|
313
298
|
// Modifications:
|
314
299
|
// * Support int first_lineno for Ruby 3.2.0+ (https://github.com/ruby/ruby/pull/6430)
|
300
|
+
// * Validate iseq and pos before calling `rb_iseq_line_no` as a safety measure (see comment below for details)
|
315
301
|
//
|
316
302
|
// `node_id` gets used depending on Ruby VM compilation settings (USE_ISEQ_NODE_ID being defined).
|
317
303
|
// To avoid getting false "unused argument" warnings in setups where it's not used, we need to do this weird dance
|
@@ -358,6 +344,18 @@ calc_pos(const rb_iseq_t *iseq, const VALUE *pc, int *lineno, int *node_id)
|
|
358
344
|
__builtin_trap();
|
359
345
|
}
|
360
346
|
#endif
|
347
|
+
|
348
|
+
// In PROF-11475 we spotted a crash when calling `rb_iseq_line_no` from this method.
|
349
|
+
// We were only able to reproduce this issue on Ruby 2.6 and 2.7, not 2.5 or the 3.x series (tried 3.0, 3.2 and 3.4).
|
350
|
+
// Note that going out of bounds doesn't crash every time, as usual with C we may just read garbage or get lucky.
|
351
|
+
//
|
352
|
+
// For those problematic Rubies, we observed that when we try to take a sample in the middle of processing the
|
353
|
+
// VM `LEAVE` instruction, the value of `n` can violate the documented assumptions above and be
|
354
|
+
// `n > ISEQ_BODY(iseq)->iseq_size)`.
|
355
|
+
//
|
356
|
+
// To work around this and any other potential issues, we validate here that the bytecode position is sane.
|
357
|
+
if (RB_UNLIKELY(n < 0 || n > ISEQ_BODY(iseq)->iseq_size)) return 0;
|
358
|
+
|
361
359
|
if (lineno) *lineno = rb_iseq_line_no(iseq, pos);
|
362
360
|
#ifdef USE_ISEQ_NODE_ID
|
363
361
|
if (node_id) *node_id = rb_iseq_node_id(iseq, pos);
|
@@ -402,6 +400,9 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
|
|
402
400
|
// * Add frame_flags.same_frame and logic to skip redoing work if the buffer already contains the same data we're collecting
|
403
401
|
// * Skipped use of rb_callable_method_entry_t (cme) for Ruby frames as it doesn't impact us.
|
404
402
|
// * Imported fix from https://github.com/ruby/ruby/pull/8280 to keep us closer to upstream
|
403
|
+
// * Added potential fix for https://github.com/ruby/ruby/pull/13643 (this one is a just-in-case, unclear if it happens
|
404
|
+
// for ddtrace)
|
405
|
+
// * Reversed order of iteration to better enable caching
|
405
406
|
//
|
406
407
|
// What is rb_profile_frames?
|
407
408
|
// `rb_profile_frames` is a Ruby VM debug API added for use by profilers for sampling the stack trace of a Ruby thread.
|
@@ -437,6 +438,16 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *st
|
|
437
438
|
// support sampling any thread (including the current) passed as an argument
|
438
439
|
rb_thread_t *th = thread_struct_from_object(thread);
|
439
440
|
const rb_execution_context_t *ec = th->ec;
|
441
|
+
|
442
|
+
// As of this writing, we don't support profiling with MN enabled, and this only happens in that mode, but as we
|
443
|
+
// probably want to experiment with it in the future, I've decided to import https://github.com/ruby/ruby/pull/9310
|
444
|
+
// here.
|
445
|
+
if (ec == NULL) return 0;
|
446
|
+
|
447
|
+
// I suspect this won't happen for ddtrace, but just-in-case we've imported a potential fix for
|
448
|
+
// https://github.com/ruby/ruby/pull/13643 by assuming that these can be NULL/zero with the cfp being non-NULL yet.
|
449
|
+
if (ec->vm_stack == NULL || ec->vm_stack_size == 0) return 0;
|
450
|
+
|
440
451
|
const rb_control_frame_t *cfp = ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
|
441
452
|
#ifndef NO_JIT_RETURN
|
442
453
|
const rb_control_frame_t *top = cfp;
|
@@ -454,11 +465,6 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *st
|
|
454
465
|
// it from https://github.com/ruby/ruby/pull/7116 in a "just in case" kind of mindset.
|
455
466
|
if (cfp == NULL) return 0;
|
456
467
|
|
457
|
-
// As of this writing, we don't support profiling with MN enabled, and this only happens in that mode, but as we
|
458
|
-
// probably want to experiment with it in the future, I've decided to import https://github.com/ruby/ruby/pull/9310
|
459
|
-
// here.
|
460
|
-
if (ec == NULL) return 0;
|
461
|
-
|
462
468
|
// Fix: Skip dummy frame that shows up in main thread.
|
463
469
|
//
|
464
470
|
// According to a comment in `backtrace_each` (`vm_backtrace.c`), there's two dummy frames that we should ignore
|
@@ -475,7 +481,20 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *st
|
|
475
481
|
// See comment on `record_placeholder_stack_in_native_code` for a full explanation of what this means (and why we don't just return 0)
|
476
482
|
if (end_cfp <= cfp) return PLACEHOLDER_STACK_IN_NATIVE_CODE;
|
477
483
|
|
478
|
-
|
484
|
+
// This is the position just after the top of the stack -- e.g. where a new frame pushed on the stack would end up.
|
485
|
+
const rb_control_frame_t *top_sentinel = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
|
486
|
+
|
487
|
+
// We iterate the stack from bottom (beginning of thread) to the top (currently-active frame). This is different
|
488
|
+
// from upstream rb_profile_frames, but actually matches what `backtrace_each` does (yes, different Ruby VM APIs
|
489
|
+
// iterate in different directions).
|
490
|
+
// We do this to better take advantage of the `same_frame` caching mechanism: By starting from the bottom of the
|
491
|
+
// stack towards the top, we can usually keep most of the stack intact when the code is only going up and down
|
492
|
+
// a few methods at the top. Before this change, the cache was really only useful if between samples the app had
|
493
|
+
// not moved from the current stack, as adding or removing one frame would invalidate the existing cache (because
|
494
|
+
// every position would shift).
|
495
|
+
cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
|
496
|
+
|
497
|
+
for (i=0; i<limit && cfp != top_sentinel; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
|
479
498
|
if (cfp->iseq && !cfp->pc) {
|
480
499
|
// Fix: Do nothing -- this frame should not be used
|
481
500
|
//
|
@@ -561,6 +580,7 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *st
|
|
561
580
|
|
562
581
|
stack_buffer[i].as.native_frame.caching_cme = (VALUE)cme;
|
563
582
|
stack_buffer[i].as.native_frame.method_id = cme->def->original_id;
|
583
|
+
stack_buffer[i].as.native_frame.function = cme->def->body.cfunc.func;
|
564
584
|
stack_buffer[i].is_ruby_frame = false;
|
565
585
|
i++;
|
566
586
|
}
|
@@ -18,16 +18,19 @@ typedef struct {
|
|
18
18
|
rb_nativethread_id_t owner;
|
19
19
|
} current_gvl_owner;
|
20
20
|
|
21
|
+
// If a sample is kept around for later use, some of its fields need marking. Remember to
|
22
|
+
// update the marking code in `sampling_buffer_mark` if new fields are added.
|
21
23
|
typedef struct {
|
22
24
|
union {
|
23
25
|
struct {
|
24
|
-
VALUE iseq;
|
25
|
-
void *caching_pc; // For caching only
|
26
|
+
VALUE iseq; // Needs marking if kept around
|
27
|
+
void *caching_pc; // For caching validation/invalidation only (does not need marking)
|
26
28
|
int line;
|
27
29
|
} ruby_frame;
|
28
30
|
struct {
|
29
|
-
VALUE caching_cme; // For caching only
|
31
|
+
VALUE caching_cme; // For caching validation/invalidation only (does not need marking)
|
30
32
|
ID method_id;
|
33
|
+
void *function;
|
31
34
|
} native_frame;
|
32
35
|
} as;
|
33
36
|
bool is_ruby_frame : 1;
|
@@ -38,7 +41,6 @@ rb_nativethread_id_t pthread_id_for(VALUE thread);
|
|
38
41
|
bool is_current_thread_holding_the_gvl(void);
|
39
42
|
current_gvl_owner gvl_owner(void);
|
40
43
|
uint64_t native_thread_id_for(VALUE thread);
|
41
|
-
ptrdiff_t stack_depth_for(VALUE thread);
|
42
44
|
void ddtrace_thread_list(VALUE result_array);
|
43
45
|
bool is_thread_alive(VALUE thread);
|
44
46
|
VALUE thread_name_for(VALUE thread);
|
@@ -20,6 +20,7 @@ void collectors_dynamic_sampling_rate_init(VALUE profiling_module);
|
|
20
20
|
void collectors_idle_sampling_helper_init(VALUE profiling_module);
|
21
21
|
void collectors_stack_init(VALUE profiling_module);
|
22
22
|
void collectors_thread_context_init(VALUE profiling_module);
|
23
|
+
void encoded_profile_init(VALUE profiling_module);
|
23
24
|
void http_transport_init(VALUE profiling_module);
|
24
25
|
void stack_recorder_init(VALUE profiling_module);
|
25
26
|
|
@@ -61,6 +62,7 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
|
|
61
62
|
collectors_idle_sampling_helper_init(profiling_module);
|
62
63
|
collectors_stack_init(profiling_module);
|
63
64
|
collectors_thread_context_init(profiling_module);
|
65
|
+
encoded_profile_init(profiling_module);
|
64
66
|
http_transport_init(profiling_module);
|
65
67
|
stack_recorder_init(profiling_module);
|
66
68
|
unsafe_api_calls_check_init();
|
@@ -103,16 +103,6 @@ void raise_syserr(
|
|
103
103
|
}
|
104
104
|
}
|
105
105
|
|
106
|
-
char* ruby_strndup(const char *str, size_t size) {
|
107
|
-
char *dup;
|
108
|
-
|
109
|
-
dup = xmalloc(size + 1);
|
110
|
-
memcpy(dup, str, size);
|
111
|
-
dup[size] = '\0';
|
112
|
-
|
113
|
-
return dup;
|
114
|
-
}
|
115
|
-
|
116
106
|
static VALUE _id2ref(VALUE obj_id) {
|
117
107
|
// Call ::ObjectSpace._id2ref natively. It will raise if the id is no longer valid
|
118
108
|
return rb_funcall(module_object_space, _id2ref_id, 1, obj_id);
|
@@ -122,9 +112,7 @@ static VALUE _id2ref_failure(DDTRACE_UNUSED VALUE _unused1, DDTRACE_UNUSED VALUE
|
|
122
112
|
return Qfalse;
|
123
113
|
}
|
124
114
|
|
125
|
-
//
|
126
|
-
// writes the ref to the value pointer parameter if !NULL. False if id doesn't
|
127
|
-
// reference a valid object (in which case value is not changed).
|
115
|
+
// See notes on header for important details
|
128
116
|
bool ruby_ref_from_id(VALUE obj_id, VALUE *value) {
|
129
117
|
// Call ::ObjectSpace._id2ref natively. It will raise if the id is no longer valid
|
130
118
|
// so we need to call it via rb_rescue2
|
@@ -67,20 +67,12 @@ NORETURN(void raise_syserr(
|
|
67
67
|
const char *function_name
|
68
68
|
));
|
69
69
|
|
70
|
-
// Alternative to ruby_strdup that takes a size argument.
|
71
|
-
// Similar to C's strndup but slightly less smart as size is expected to
|
72
|
-
// be smaller or equal to the real size of str (minus null termination if it
|
73
|
-
// exists).
|
74
|
-
// A new string will be returned with size+1 bytes and last byte set to '\0'.
|
75
|
-
// The returned string must be freed explicitly.
|
76
|
-
//
|
77
|
-
// WARN: Cannot be used during GC or outside the GVL.
|
78
|
-
char* ruby_strndup(const char *str, size_t size);
|
79
|
-
|
80
70
|
// Native wrapper to get an object ref from an id. Returns true on success and
|
81
71
|
// writes the ref to the value pointer parameter if !NULL. False if id doesn't
|
82
72
|
// reference a valid object (in which case value is not changed).
|
83
|
-
|
73
|
+
//
|
74
|
+
// Note: GVL can be released and other threads may get to run before this method returns
|
75
|
+
bool ruby_ref_from_id(VALUE obj_id, VALUE *value);
|
84
76
|
|
85
77
|
// Native wrapper to get the approximate/estimated current size of the passed
|
86
78
|
// object.
|