ddtrace 1.2.0 → 1.3.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 +47 -1
- data/LICENSE-3rdparty.csv +2 -0
- data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +1 -1
- data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +9 -2
- data/ext/ddtrace_profiling_native_extension/clock_id.h +20 -0
- data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +30 -1
- data/ext/ddtrace_profiling_native_extension/clock_id_noop.c +10 -1
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +148 -28
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +6 -0
- data/ext/ddtrace_profiling_native_extension/collectors_stack.c +11 -7
- data/ext/ddtrace_profiling_native_extension/extconf.rb +24 -19
- data/ext/ddtrace_profiling_native_extension/helpers.h +12 -0
- data/ext/ddtrace_profiling_native_extension/http_transport.c +40 -47
- data/ext/ddtrace_profiling_native_extension/{libddprof_helpers.h → libdatadog_helpers.h} +2 -1
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +36 -20
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +30 -29
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +2 -5
- data/ext/ddtrace_profiling_native_extension/profiling.c +2 -3
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +25 -0
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +33 -1
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +292 -18
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +1 -1
- data/lib/datadog/appsec/autoload.rb +4 -2
- data/lib/datadog/appsec/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/auto_instrument.rb +0 -2
- data/lib/datadog/appsec/contrib/configuration/settings.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +2 -2
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/integration.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +2 -2
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -3
- data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +4 -4
- data/lib/datadog/appsec/contrib/rails/integration.rb +4 -4
- data/lib/datadog/appsec/contrib/rails/patcher.rb +16 -12
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +5 -5
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +4 -4
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +16 -12
- data/lib/datadog/appsec/event.rb +3 -3
- data/lib/datadog/appsec/extensions.rb +1 -1
- data/lib/datadog/appsec/processor.rb +1 -1
- data/lib/datadog/appsec/reactive/engine.rb +2 -2
- data/lib/datadog/appsec/reactive/operation.rb +3 -3
- data/lib/datadog/appsec.rb +5 -5
- data/lib/datadog/ci/configuration/components.rb +1 -1
- data/lib/datadog/ci/configuration/settings.rb +1 -1
- data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +2 -2
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +5 -5
- data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +1 -1
- data/lib/datadog/ci/contrib/cucumber/integration.rb +3 -3
- data/lib/datadog/ci/contrib/cucumber/patcher.rb +2 -2
- data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +2 -2
- data/lib/datadog/ci/contrib/rspec/example.rb +5 -5
- data/lib/datadog/ci/contrib/rspec/integration.rb +3 -3
- data/lib/datadog/ci/contrib/rspec/patcher.rb +2 -2
- data/lib/datadog/ci/ext/environment.rb +8 -6
- data/lib/datadog/ci/extensions.rb +4 -4
- data/lib/datadog/ci/flush.rb +2 -2
- data/lib/datadog/ci/test.rb +3 -3
- data/lib/datadog/ci.rb +6 -6
- data/lib/datadog/core/buffer/cruby.rb +1 -1
- data/lib/datadog/core/buffer/thread_safe.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +6 -6
- data/lib/datadog/core/configuration/base.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +26 -43
- data/lib/datadog/core/configuration/option_definition.rb +1 -1
- data/lib/datadog/core/configuration/option_definition_set.rb +1 -1
- data/lib/datadog/core/configuration/options.rb +3 -3
- data/lib/datadog/core/configuration/settings.rb +9 -7
- data/lib/datadog/core/configuration.rb +4 -4
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/diagnostics/health.rb +2 -2
- data/lib/datadog/core/environment/cgroup.rb +1 -1
- data/lib/datadog/core/environment/container.rb +1 -1
- data/lib/datadog/core/environment/ext.rb +1 -1
- data/lib/datadog/core/environment/identity.rb +2 -2
- data/lib/datadog/core/environment/platform.rb +1 -1
- data/lib/datadog/core/environment/socket.rb +1 -1
- data/lib/datadog/core/error.rb +1 -1
- data/lib/datadog/core/extensions.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +8 -8
- data/lib/datadog/core/metrics/options.rb +3 -3
- data/lib/datadog/core/runtime/metrics.rb +6 -6
- data/lib/datadog/core/utils/object_set.rb +1 -1
- data/lib/datadog/core/utils/string_table.rb +1 -1
- data/lib/datadog/core/utils/time.rb +3 -3
- data/lib/datadog/core/utils.rb +2 -2
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +2 -2
- data/lib/datadog/core/vendor/multipart-post/net/http/post/multipart.rb +3 -3
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core/workers/polling.rb +2 -2
- data/lib/datadog/core/workers/runtime_metrics.rb +4 -4
- data/lib/datadog/core.rb +50 -50
- data/lib/datadog/kit.rb +1 -1
- data/lib/datadog/opentracer/distributed_headers.rb +2 -2
- data/lib/datadog/opentracer/rack_propagator.rb +11 -7
- data/lib/datadog/opentracer/span.rb +1 -1
- data/lib/datadog/opentracer/text_map_propagator.rb +9 -6
- data/lib/datadog/opentracer/thread_local_scope_manager.rb +1 -1
- data/lib/datadog/opentracer/tracer.rb +19 -15
- data/lib/datadog/opentracer.rb +16 -16
- data/lib/datadog/profiling/buffer.rb +3 -3
- data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +4 -19
- data/lib/datadog/profiling/collectors/old_stack.rb +7 -7
- data/lib/datadog/profiling/collectors/stack.rb +3 -8
- data/lib/datadog/profiling/encoding/profile.rb +1 -1
- data/lib/datadog/profiling/events/stack.rb +1 -1
- data/lib/datadog/profiling/exporter.rb +17 -9
- data/lib/datadog/profiling/ext/forking.rb +36 -37
- data/lib/datadog/profiling/ext.rb +1 -0
- data/lib/datadog/profiling/flush.rb +0 -3
- data/lib/datadog/profiling/http_transport.rb +4 -3
- data/lib/datadog/profiling/old_recorder.rb +2 -7
- data/lib/datadog/profiling/pprof/builder.rb +4 -4
- data/lib/datadog/profiling/pprof/converter.rb +1 -1
- data/lib/datadog/profiling/pprof/message_set.rb +1 -1
- data/lib/datadog/profiling/pprof/stack_sample.rb +4 -4
- data/lib/datadog/profiling/pprof/string_table.rb +1 -1
- data/lib/datadog/profiling/pprof/template.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/scheduler.rb +5 -4
- data/lib/datadog/profiling/stack_recorder.rb +14 -4
- data/lib/datadog/profiling/tag_builder.rb +6 -1
- data/lib/datadog/profiling/tasks/setup.rb +2 -2
- data/lib/datadog/profiling/trace_identifiers/ddtrace.rb +2 -2
- data/lib/datadog/profiling/trace_identifiers/helper.rb +1 -1
- data/lib/datadog/profiling/transport/http/api/endpoint.rb +5 -5
- data/lib/datadog/profiling/transport/http/api/instance.rb +2 -2
- data/lib/datadog/profiling/transport/http/api/spec.rb +1 -1
- data/lib/datadog/profiling/transport/http/api.rb +5 -5
- data/lib/datadog/profiling/transport/http/builder.rb +3 -3
- data/lib/datadog/profiling/transport/http/client.rb +2 -2
- data/lib/datadog/profiling/transport/http/response.rb +1 -1
- data/lib/datadog/profiling/transport/http.rb +21 -15
- data/lib/datadog/profiling.rb +20 -20
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +5 -5
- data/lib/datadog/tracing/context.rb +1 -1
- data/lib/datadog/tracing/context_provider.rb +2 -2
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_cable/event.rb +4 -5
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +3 -3
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/events.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/action_cable/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +3 -3
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +3 -3
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -3
- data/lib/datadog/tracing/contrib/action_mailer/events.rb +2 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/action_view/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +5 -5
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +5 -5
- data/lib/datadog/tracing/contrib/action_view/events.rb +2 -2
- data/lib/datadog/tracing/contrib/action_view/instrumentation/partial_renderer.rb +2 -2
- data/lib/datadog/tracing/contrib/action_view/instrumentation/template_renderer.rb +2 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/action_view/patcher.rb +7 -7
- data/lib/datadog/tracing/contrib/action_view/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/active_job/event.rb +3 -3
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/events.rb +6 -6
- data/lib/datadog/tracing/contrib/active_job/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +0 -2
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +4 -5
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +3 -3
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +2 -2
- data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +2 -2
- data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +3 -4
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/active_record/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +4 -4
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +6 -6
- data/lib/datadog/tracing/contrib/active_record/events.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/active_record/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/utils.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +19 -9
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -5
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/analytics.rb +1 -1
- data/lib/datadog/tracing/contrib/auto_instrument.rb +4 -4
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/configurable.rb +2 -2
- data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +4 -5
- data/lib/datadog/tracing/contrib/dalli/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/dalli/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/delayed_job/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +8 -2
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +3 -4
- data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +32 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -7
- data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
- data/lib/datadog/tracing/contrib/ethon/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +3 -4
- data/lib/datadog/tracing/contrib/ethon/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/excon/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/excon/middleware.rb +6 -7
- data/lib/datadog/tracing/contrib/excon/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/extensions.rb +3 -3
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/faraday/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -6
- data/lib/datadog/tracing/contrib/faraday/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -5
- data/lib/datadog/tracing/contrib/grape/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/grape/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/graphql/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +2 -3
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +4 -4
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +6 -6
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +3 -4
- data/lib/datadog/tracing/contrib/grpc/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +1 -2
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/http/integration.rb +6 -6
- data/lib/datadog/tracing/contrib/http/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +4 -5
- data/lib/datadog/tracing/contrib/httpclient/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -5
- data/lib/datadog/tracing/contrib/httprb/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/event.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +4 -4
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/events.rb +9 -9
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -2
- data/lib/datadog/tracing/contrib/lograge/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +4 -4
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/mysql2/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/mysql2/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/pg/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/pg/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +2 -3
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/presto/patcher.rb +4 -4
- data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/qless/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/qless/patcher.rb +1 -2
- data/lib/datadog/tracing/contrib/qless/qless_job.rb +2 -3
- data/lib/datadog/tracing/contrib/qless/tracer_cleaner.rb +0 -2
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/que/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/que/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/event.rb +4 -5
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/events/consume.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +2 -2
- data/lib/datadog/tracing/contrib/racecar/events.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/racecar/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/rack/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +24 -20
- data/lib/datadog/tracing/contrib/rack/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/framework.rb +16 -21
- data/lib/datadog/tracing/contrib/rails/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +0 -2
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +1 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -8
- data/lib/datadog/tracing/contrib/rails/railtie.rb +3 -3
- data/lib/datadog/tracing/contrib/rails/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +17 -2
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +12 -7
- data/lib/datadog/tracing/contrib/rake/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/rake/patcher.rb +3 -4
- data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +6 -7
- data/lib/datadog/tracing/contrib/redis/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/redis/patcher.rb +6 -6
- data/lib/datadog/tracing/contrib/redis/tags.rb +3 -4
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/resque/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/resque/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/resque/resque_job.rb +3 -4
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/rest_client/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -5
- data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -2
- data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sequel/database.rb +4 -5
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +4 -5
- data/lib/datadog/tracing/contrib/sequel/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/sequel/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -2
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/shoryuken/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +4 -5
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +6 -0
- data/lib/datadog/tracing/contrib/sidekiq/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +14 -7
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +19 -1
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/{scheduled_push.rb → redis_info.rb} +5 -6
- data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +53 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -6
- data/lib/datadog/tracing/contrib/sidekiq/tracing.rb +2 -2
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sinatra/env.rb +2 -2
- data/lib/datadog/tracing/contrib/sinatra/framework.rb +0 -2
- data/lib/datadog/tracing/contrib/sinatra/headers.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +5 -5
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +7 -8
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +6 -7
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sneakers/integration.rb +4 -4
- data/lib/datadog/tracing/contrib/sneakers/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +2 -3
- data/lib/datadog/tracing/contrib/status_code_matcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +3 -3
- data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +4 -5
- data/lib/datadog/tracing/contrib.rb +48 -48
- data/lib/datadog/tracing/correlation.rb +1 -1
- data/lib/datadog/tracing/distributed/headers/b3.rb +4 -4
- data/lib/datadog/tracing/distributed/headers/b3_single.rb +4 -4
- data/lib/datadog/tracing/distributed/headers/datadog.rb +3 -3
- data/lib/datadog/tracing/distributed/headers/parser.rb +1 -1
- data/lib/datadog/tracing/distributed/helpers.rb +2 -2
- data/lib/datadog/tracing/distributed/metadata/b3.rb +4 -4
- data/lib/datadog/tracing/distributed/metadata/b3_single.rb +4 -4
- data/lib/datadog/tracing/distributed/metadata/datadog.rb +2 -2
- data/lib/datadog/tracing/distributed/metadata/parser.rb +1 -1
- data/lib/datadog/tracing/event.rb +1 -1
- data/lib/datadog/tracing/metadata/analytics.rb +2 -2
- data/lib/datadog/tracing/metadata/errors.rb +2 -2
- data/lib/datadog/tracing/metadata/tagging.rb +2 -2
- data/lib/datadog/tracing/metadata.rb +3 -3
- data/lib/datadog/tracing/pipeline/span_filter.rb +10 -6
- data/lib/datadog/tracing/pipeline.rb +3 -3
- data/lib/datadog/tracing/propagation/grpc.rb +6 -6
- data/lib/datadog/tracing/propagation/http.rb +8 -8
- data/lib/datadog/tracing/runtime/metrics.rb +1 -1
- data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/priority_sampler.rb +5 -5
- data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +2 -2
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +3 -3
- data/lib/datadog/tracing/sampling/rate_limiter.rb +1 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +5 -5
- data/lib/datadog/tracing/sampling/rule.rb +3 -3
- data/lib/datadog/tracing/sampling/rule_sampler.rb +4 -4
- data/lib/datadog/tracing/span.rb +4 -4
- data/lib/datadog/tracing/span_operation.rb +9 -9
- data/lib/datadog/tracing/sync_writer.rb +5 -5
- data/lib/datadog/tracing/trace_operation.rb +16 -9
- data/lib/datadog/tracing/trace_segment.rb +5 -5
- data/lib/datadog/tracing/tracer.rb +15 -15
- data/lib/datadog/tracing/workers/trace_writer.rb +9 -9
- data/lib/datadog/tracing/workers.rb +3 -3
- data/lib/datadog/tracing/writer.rb +5 -5
- data/lib/datadog/tracing.rb +8 -8
- data/lib/ddtrace/auto_instrument.rb +2 -2
- data/lib/ddtrace/transport/ext.rb +7 -0
- data/lib/ddtrace/transport/http/adapters/net.rb +2 -2
- data/lib/ddtrace/transport/http/adapters/test.rb +1 -1
- data/lib/ddtrace/transport/http/adapters/unix_socket.rb +2 -2
- data/lib/ddtrace/transport/http/api/map.rb +1 -1
- data/lib/ddtrace/transport/http/api.rb +4 -4
- data/lib/ddtrace/transport/http/builder.rb +5 -5
- data/lib/ddtrace/transport/http/client.rb +2 -2
- data/lib/ddtrace/transport/http/response.rb +1 -1
- data/lib/ddtrace/transport/http/statistics.rb +1 -1
- data/lib/ddtrace/transport/http/traces.rb +5 -5
- data/lib/ddtrace/transport/http.rb +12 -9
- data/lib/ddtrace/transport/io/client.rb +2 -2
- data/lib/ddtrace/transport/io/response.rb +1 -1
- data/lib/ddtrace/transport/io/traces.rb +3 -3
- data/lib/ddtrace/transport/io.rb +3 -3
- data/lib/ddtrace/transport/statistics.rb +2 -2
- data/lib/ddtrace/transport/trace_formatter.rb +5 -5
- data/lib/ddtrace/transport/traces.rb +5 -5
- data/lib/ddtrace/version.rb +1 -1
- data/lib/ddtrace.rb +6 -6
- metadata +14 -22
- data/.editorconfig +0 -22
- data/.gitignore +0 -58
- data/CONTRIBUTING.md +0 -81
- data/ddtrace.gemspec +0 -71
- data/docs/0.x-trace.png +0 -0
- data/docs/1.0-trace.png +0 -0
- data/docs/AutoInstrumentation.md +0 -36
- data/docs/Deprecation.md +0 -8
- data/docs/DevelopmentGuide.md +0 -259
- data/docs/GettingStarted.md +0 -2712
- data/docs/ProfilingDevelopment.md +0 -109
- data/docs/PublicApi.md +0 -14
- data/docs/UpgradeGuide.md +0 -736
|
@@ -2,13 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
#include <ruby.h>
|
|
4
4
|
|
|
5
|
+
#include "helpers.h"
|
|
6
|
+
|
|
5
7
|
// Processes any pending interruptions, including exceptions to be raised.
|
|
6
8
|
// If there's an exception to be raised, it raises it. In that case, this function does not return.
|
|
7
|
-
static inline VALUE process_pending_interruptions(VALUE
|
|
9
|
+
static inline VALUE process_pending_interruptions(DDTRACE_UNUSED VALUE _) {
|
|
8
10
|
rb_thread_check_ints();
|
|
9
11
|
return Qnil;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
// RB_UNLIKELY is not supported on Ruby 2.2 and 2.3
|
|
15
|
+
#ifndef RB_UNLIKELY
|
|
16
|
+
#define RB_UNLIKELY(x) x
|
|
17
|
+
#endif
|
|
18
|
+
|
|
12
19
|
// Calls process_pending_interruptions BUT "rescues" any exceptions to be raised, returning them instead as
|
|
13
20
|
// a non-zero `pending_exception`.
|
|
14
21
|
//
|
|
@@ -31,3 +38,28 @@ static inline int check_if_pending_exception(void) {
|
|
|
31
38
|
rb_protect(process_pending_interruptions, Qnil, &pending_exception);
|
|
32
39
|
return pending_exception;
|
|
33
40
|
}
|
|
41
|
+
|
|
42
|
+
#define ADD_QUOTES_HELPER(x) #x
|
|
43
|
+
#define ADD_QUOTES(x) ADD_QUOTES_HELPER(x)
|
|
44
|
+
|
|
45
|
+
// Ruby has a Check_Type(value, type) that is roughly equivalent to this BUT Ruby's version is rather cryptic when it fails
|
|
46
|
+
// e.g. "wrong argument type nil (expected String)". This is a replacement that prints more information to help debugging.
|
|
47
|
+
#define ENFORCE_TYPE(value, type) \
|
|
48
|
+
{ if (RB_UNLIKELY(!RB_TYPE_P(value, type))) raise_unexpected_type(value, type, ADD_QUOTES(value), ADD_QUOTES(type), __FILE__, __LINE__, __func__); }
|
|
49
|
+
|
|
50
|
+
// Called by ENFORCE_TYPE; should not be used directly
|
|
51
|
+
NORETURN(void raise_unexpected_type(
|
|
52
|
+
VALUE value,
|
|
53
|
+
enum ruby_value_type type,
|
|
54
|
+
const char *value_name,
|
|
55
|
+
const char *type_name,
|
|
56
|
+
const char *file,
|
|
57
|
+
int line,
|
|
58
|
+
const char* function_name
|
|
59
|
+
));
|
|
60
|
+
|
|
61
|
+
// This API is exported as a public symbol by the VM BUT the function header is not defined in any public header, so we
|
|
62
|
+
// repeat it here to be able to use in our code.
|
|
63
|
+
//
|
|
64
|
+
// Queries if the current thread is the owner of the global VM lock.
|
|
65
|
+
int ruby_thread_has_gvl_p(void);
|
|
@@ -1,12 +1,130 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
2
|
#include <ruby/thread.h>
|
|
3
|
+
#include <pthread.h>
|
|
4
|
+
#include <errno.h>
|
|
5
|
+
#include "helpers.h"
|
|
3
6
|
#include "stack_recorder.h"
|
|
4
|
-
#include "
|
|
7
|
+
#include "libdatadog_helpers.h"
|
|
5
8
|
#include "ruby_helpers.h"
|
|
6
9
|
|
|
7
10
|
// Used to wrap a ddprof_ffi_Profile in a Ruby object and expose Ruby-level serialization APIs
|
|
8
11
|
// This file implements the native bits of the Datadog::Profiling::StackRecorder class
|
|
9
12
|
|
|
13
|
+
// ---
|
|
14
|
+
// ## Synchronization mechanism for safe parallel access design notes
|
|
15
|
+
//
|
|
16
|
+
// The state of the StackRecorder is managed using a set of locks to avoid concurrency issues.
|
|
17
|
+
//
|
|
18
|
+
// This is needed because the state is expected to be accessed, in parallel, by two different threads.
|
|
19
|
+
//
|
|
20
|
+
// 1. The thread that is taking a stack sample and that called `record_sample`, let's call it the **sampler thread**.
|
|
21
|
+
// In the current implementation of the profiler, there can only exist one **sampler thread** at a time; if this
|
|
22
|
+
// constraint changes, we should revise the design of the StackRecorder.
|
|
23
|
+
//
|
|
24
|
+
// 2. The thread that serializes and reports profiles, let's call it the **serializer thread**. We enforce that there
|
|
25
|
+
// cannot be more than one thread attempting to serialize profiles at a time.
|
|
26
|
+
//
|
|
27
|
+
// If both the sampler and serializer threads are trying to access the same `ddprof_ffi_Profile` in parallel, we will
|
|
28
|
+
// have a concurrency issue. Thus, the StackRecorder has an added mechanism to avoid this.
|
|
29
|
+
//
|
|
30
|
+
// As an additional constraint, the **sampler thread** has absolute priority and must never block while
|
|
31
|
+
// recording a sample.
|
|
32
|
+
//
|
|
33
|
+
// ### The solution: Keep two profiles at the same time
|
|
34
|
+
//
|
|
35
|
+
// To solve for the constraints above, the StackRecorder keeps two `ddprof_ffi_Profile` profile instances inside itself.
|
|
36
|
+
// They are called the `slot_one_profile` and `slot_two_profile`.
|
|
37
|
+
//
|
|
38
|
+
// Each profile is paired with its own mutex. `slot_one_profile` is protected by `slot_one_mutex` and `slot_two_profile`
|
|
39
|
+
// is protected by `slot_two_mutex`.
|
|
40
|
+
//
|
|
41
|
+
// We additionally introduce the concept of **active** and **inactive** profile slots. At any point, the sampler thread
|
|
42
|
+
// can probe the mutexes to discover which of the profiles corresponds to the active slot, and then records samples in it.
|
|
43
|
+
// When the serializer thread is ready to serialize data, it flips the active and inactive slots; it reports the data
|
|
44
|
+
// on the previously-active profile slot, and the sampler thread can continue to record in the previously-inactive
|
|
45
|
+
// profile slot.
|
|
46
|
+
//
|
|
47
|
+
// Thus, the sampler and serializer threads never cross paths, avoiding concurrency issues. The sampler thread writes to
|
|
48
|
+
// the active profile slot, and the serializer thread reads from the inactive profile slot.
|
|
49
|
+
//
|
|
50
|
+
// ### Locking protocol, high-level
|
|
51
|
+
//
|
|
52
|
+
// The active profile slot is the slot for which its corresponding mutex **is unlocked**. That is, if the sampler
|
|
53
|
+
// thread can grab a lock for a profile slot, then that slot is the active one. (Here you see where the constraint
|
|
54
|
+
// stated above that only one sampler thread can exist kicks in -- this part would need to be more complex if multiple
|
|
55
|
+
// sampler threads were in play.)
|
|
56
|
+
//
|
|
57
|
+
// As a counterpart, the inactive profile slot mutex is **kept locked** until such time the serializer
|
|
58
|
+
// thread is ready to work and decides to flip the slots.
|
|
59
|
+
//
|
|
60
|
+
// When a new StackRecorder is initialized, the `slot_one_mutex` is unlocked, and the `slot_two_mutex` is kept locked,
|
|
61
|
+
// that is, a new instance always starts with slot one active.
|
|
62
|
+
//
|
|
63
|
+
// Additionally, an `active_slot` field is kept, containing a `1` or `2`; this is only kept for the serializer thread
|
|
64
|
+
// to use as a simplification, as well as for testing and debugging; the **sampler thread must never use the `active_slot`
|
|
65
|
+
// field**.
|
|
66
|
+
//
|
|
67
|
+
// ### Locking protocol, from the sampler thread side
|
|
68
|
+
//
|
|
69
|
+
// When the sampler thread wants to record a sample, it goes through the following steps to discover which is the
|
|
70
|
+
// active profile slot:
|
|
71
|
+
//
|
|
72
|
+
// 1. `pthread_mutex_trylock(slot_one_mutex)`. If it succeeds to grab the lock, this means the active profile slot is
|
|
73
|
+
// slot one. If it fails, we move to the next step.
|
|
74
|
+
//
|
|
75
|
+
// 2. `pthread_mutex_trylock(slot_two_mutex)`. If it succeeds to grab the lock, this means the active profile slot is
|
|
76
|
+
// slot two. If it fails, we move to the next step.
|
|
77
|
+
//
|
|
78
|
+
// 3. What does it mean for the sampler thread to have observed both `slot_one_mutex` as well as `slot_two_mutex` as
|
|
79
|
+
// being locked? There are two options:
|
|
80
|
+
// a. The sampler thread got really unlucky. When it tried to grab the `slot_one_mutex`, the active profile slot was
|
|
81
|
+
// the second one BUT then the serializer thread flipped the slots, and by the time the sampler thread probed the
|
|
82
|
+
// `slot_two_mutex`, that one was taken. Since the serializer thread is expected only to work once a minute,
|
|
83
|
+
// we retry steps 1. and 2. and should be able to find an active slot.
|
|
84
|
+
// b. Something is incorrect in the StackRecorder state. In this situation, the sampler thread should give up on
|
|
85
|
+
// sampling and enter an error state.
|
|
86
|
+
//
|
|
87
|
+
// Note that in the steps above, and because the sampler thread uses `trylock` to probe the mutexes, that the
|
|
88
|
+
// sampler thread never blocks. It either is able to find an active profile slot in a bounded amount of steps or it
|
|
89
|
+
// enters an error state.
|
|
90
|
+
//
|
|
91
|
+
// This guarantees that sampler performance is never constrained by serializer performance.
|
|
92
|
+
//
|
|
93
|
+
// ### Locking protocol, from the serializer thread side
|
|
94
|
+
//
|
|
95
|
+
// When the serializer thread wants to serialize a profile, it first flips the active and inactive profile slots.
|
|
96
|
+
//
|
|
97
|
+
// The flipping action is described below. Consider previously-inactive and previously-active as the state of the slots
|
|
98
|
+
// before the flipping happens.
|
|
99
|
+
//
|
|
100
|
+
// The flipping steps are the following:
|
|
101
|
+
//
|
|
102
|
+
// 1. Release the mutex for the previously-inactive profile slot. That slot, as seen by the sampler thread, is now
|
|
103
|
+
// active.
|
|
104
|
+
//
|
|
105
|
+
// 2. Grab the mutex for the previously-active profile slot. Note that this can lead to the serializer thread blocking,
|
|
106
|
+
// if the sampler thread is holding this mutex. After the mutex is grabbed, the previously-active slot becomes inactive,
|
|
107
|
+
// as seen by the sampler thread.
|
|
108
|
+
//
|
|
109
|
+
// 3. Update `active_slot`.
|
|
110
|
+
//
|
|
111
|
+
// After flipping the profile slots, the serializer thread is now free to serialize the inactive profile slot. The slot
|
|
112
|
+
// is kept inactive until the next time the serializer thread wants to serialize data.
|
|
113
|
+
//
|
|
114
|
+
// Note there can be a brief period between steps 1 and 2 where the serializer thread holds no lock, which means that
|
|
115
|
+
// the sampler thread can pick either slot. This is OK: if the sampler thread picks the previously-inactive slot, the
|
|
116
|
+
// samples will be reported on the next serialization; if the sampler thread picks the previously-active slot, the
|
|
117
|
+
// samples are still included in the current serialization. Either option is correct.
|
|
118
|
+
//
|
|
119
|
+
// ### Additional notes
|
|
120
|
+
//
|
|
121
|
+
// Q: Can the sampler thread and the serializer thread ever be the same thread? (E.g. sampling in interrupt handler)
|
|
122
|
+
// A: No; the current profiler design requires that sampling happens only on the thread that is holding the Global VM
|
|
123
|
+
// Lock (GVL). The serializer thread flipping occurs after the serializer thread releases the GVL, and thus the
|
|
124
|
+
// serializer thread will not be able to host the sampling process.
|
|
125
|
+
//
|
|
126
|
+
// ---
|
|
127
|
+
|
|
10
128
|
static VALUE ok_symbol = Qnil; // :ok in Ruby
|
|
11
129
|
static VALUE error_symbol = Qnil; // :error in Ruby
|
|
12
130
|
|
|
@@ -14,9 +132,32 @@ static ID ruby_time_from_id; // id of :ruby_time_from in Ruby
|
|
|
14
132
|
|
|
15
133
|
static VALUE stack_recorder_class = Qnil;
|
|
16
134
|
|
|
135
|
+
// Contains native state for each instance
|
|
136
|
+
struct stack_recorder_state {
|
|
137
|
+
pthread_mutex_t slot_one_mutex;
|
|
138
|
+
ddprof_ffi_Profile *slot_one_profile;
|
|
139
|
+
|
|
140
|
+
pthread_mutex_t slot_two_mutex;
|
|
141
|
+
ddprof_ffi_Profile *slot_two_profile;
|
|
142
|
+
|
|
143
|
+
short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Used to return a pair of values from sampler_lock_active_profile()
|
|
147
|
+
struct active_slot_pair {
|
|
148
|
+
pthread_mutex_t *mutex;
|
|
149
|
+
ddprof_ffi_Profile *profile;
|
|
150
|
+
};
|
|
151
|
+
|
|
17
152
|
struct call_serialize_without_gvl_arguments {
|
|
153
|
+
// Set by caller
|
|
154
|
+
struct stack_recorder_state *state;
|
|
155
|
+
|
|
156
|
+
// Set by callee
|
|
18
157
|
ddprof_ffi_Profile *profile;
|
|
19
158
|
ddprof_ffi_SerializeResult result;
|
|
159
|
+
|
|
160
|
+
// Set by both
|
|
20
161
|
bool serialize_ran;
|
|
21
162
|
};
|
|
22
163
|
|
|
@@ -25,21 +166,33 @@ static void stack_recorder_typed_data_free(void *data);
|
|
|
25
166
|
static VALUE _native_serialize(VALUE self, VALUE recorder_instance);
|
|
26
167
|
static VALUE ruby_time_from(ddprof_ffi_Timespec ddprof_time);
|
|
27
168
|
static void *call_serialize_without_gvl(void *call_args);
|
|
169
|
+
static struct active_slot_pair sampler_lock_active_profile();
|
|
170
|
+
static void sampler_unlock_active_profile(struct active_slot_pair active_slot);
|
|
171
|
+
static ddprof_ffi_Profile *serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state);
|
|
172
|
+
static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
173
|
+
static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
174
|
+
static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
|
|
175
|
+
static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot);
|
|
28
176
|
|
|
29
177
|
void stack_recorder_init(VALUE profiling_module) {
|
|
30
178
|
stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
|
|
179
|
+
// Hosts methods used for testing the native code using RSpec
|
|
180
|
+
VALUE testing_module = rb_define_module_under(stack_recorder_class, "Testing");
|
|
31
181
|
|
|
32
182
|
// Instances of the StackRecorder class are "TypedData" objects.
|
|
33
183
|
// "TypedData" objects are special objects in the Ruby VM that can wrap C structs.
|
|
34
|
-
// In
|
|
184
|
+
// In this case, it wraps the stack_recorder_state.
|
|
35
185
|
//
|
|
36
|
-
// Because Ruby doesn't know how to initialize
|
|
186
|
+
// Because Ruby doesn't know how to initialize native-level structs, we MUST override the allocation function for objects
|
|
37
187
|
// of this class so that we can manage this part. Not overriding or disabling the allocation function is a common
|
|
38
188
|
// gotcha for "TypedData" objects that can very easily lead to VM crashes, see for instance
|
|
39
189
|
// https://bugs.ruby-lang.org/issues/18007 for a discussion around this.
|
|
40
190
|
rb_define_alloc_func(stack_recorder_class, _native_new);
|
|
41
191
|
|
|
42
192
|
rb_define_singleton_method(stack_recorder_class, "_native_serialize", _native_serialize, 1);
|
|
193
|
+
rb_define_singleton_method(testing_module, "_native_active_slot", _native_active_slot, 1);
|
|
194
|
+
rb_define_singleton_method(testing_module, "_native_slot_one_mutex_locked?", _native_is_slot_one_mutex_locked, 1);
|
|
195
|
+
rb_define_singleton_method(testing_module, "_native_slot_two_mutex_locked?", _native_is_slot_two_mutex_locked, 1);
|
|
43
196
|
|
|
44
197
|
ok_symbol = ID2SYM(rb_intern_const("ok"));
|
|
45
198
|
error_symbol = ID2SYM(rb_intern_const("error"));
|
|
@@ -59,24 +212,46 @@ static const rb_data_type_t stack_recorder_typed_data = {
|
|
|
59
212
|
};
|
|
60
213
|
|
|
61
214
|
static VALUE _native_new(VALUE klass) {
|
|
215
|
+
struct stack_recorder_state *state = ruby_xcalloc(1, sizeof(struct stack_recorder_state));
|
|
216
|
+
|
|
62
217
|
ddprof_ffi_Slice_value_type sample_types = {.ptr = enabled_value_types, .len = ENABLED_VALUE_TYPES_COUNT};
|
|
63
218
|
|
|
64
|
-
|
|
219
|
+
state->slot_one_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
|
|
220
|
+
state->slot_two_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
|
|
221
|
+
|
|
222
|
+
// A newly-created StackRecorder starts with slot one being active for samples, so let's lock slot two
|
|
223
|
+
int error = pthread_mutex_lock(&state->slot_two_mutex);
|
|
224
|
+
if (error) rb_syserr_fail(error, "Unexpected failure during pthread_mutex_lock");
|
|
225
|
+
|
|
226
|
+
state->active_slot = 1;
|
|
227
|
+
|
|
228
|
+
// Note: Don't raise exceptions after this point, since it'll lead to libdatadog memory leaking!
|
|
65
229
|
|
|
66
|
-
|
|
230
|
+
state->slot_one_profile = ddprof_ffi_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
|
|
231
|
+
state->slot_two_profile = ddprof_ffi_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
|
|
232
|
+
|
|
233
|
+
return TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
|
|
67
234
|
}
|
|
68
235
|
|
|
69
|
-
static void stack_recorder_typed_data_free(void *
|
|
70
|
-
|
|
236
|
+
static void stack_recorder_typed_data_free(void *state_ptr) {
|
|
237
|
+
struct stack_recorder_state *state = (struct stack_recorder_state *) state_ptr;
|
|
238
|
+
|
|
239
|
+
pthread_mutex_destroy(&state->slot_one_mutex);
|
|
240
|
+
ddprof_ffi_Profile_free(state->slot_one_profile);
|
|
241
|
+
|
|
242
|
+
pthread_mutex_destroy(&state->slot_two_mutex);
|
|
243
|
+
ddprof_ffi_Profile_free(state->slot_two_profile);
|
|
244
|
+
|
|
245
|
+
ruby_xfree(state);
|
|
71
246
|
}
|
|
72
247
|
|
|
73
|
-
static VALUE _native_serialize(VALUE
|
|
74
|
-
|
|
75
|
-
TypedData_Get_Struct(recorder_instance,
|
|
248
|
+
static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
|
249
|
+
struct stack_recorder_state *state;
|
|
250
|
+
TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
|
|
76
251
|
|
|
77
252
|
// We'll release the Global VM Lock while we're calling serialize, so that the Ruby VM can continue to work while this
|
|
78
253
|
// is pending
|
|
79
|
-
struct call_serialize_without_gvl_arguments args = {.
|
|
254
|
+
struct call_serialize_without_gvl_arguments args = {.state = state, .serialize_ran = false};
|
|
80
255
|
|
|
81
256
|
while (!args.serialize_ran) {
|
|
82
257
|
// Give the Ruby VM an opportunity to process any pending interruptions (including raising exceptions).
|
|
@@ -89,7 +264,7 @@ static VALUE _native_serialize(VALUE self, VALUE recorder_instance) {
|
|
|
89
264
|
|
|
90
265
|
// We use rb_thread_call_without_gvl2 here because unlike the regular _gvl variant, gvl2 does not process
|
|
91
266
|
// interruptions and thus does not raise exceptions after running our code.
|
|
92
|
-
rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, /* No interruption function
|
|
267
|
+
rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, NULL /* No interruption function needed in this case */, NULL /* Not needed */);
|
|
93
268
|
}
|
|
94
269
|
|
|
95
270
|
ddprof_ffi_SerializeResult serialized_profile = args.result;
|
|
@@ -105,13 +280,15 @@ static VALUE _native_serialize(VALUE self, VALUE recorder_instance) {
|
|
|
105
280
|
ddprof_ffi_Timespec ddprof_start = serialized_profile.ok.start;
|
|
106
281
|
ddprof_ffi_Timespec ddprof_finish = serialized_profile.ok.end;
|
|
107
282
|
|
|
108
|
-
// Clean up
|
|
283
|
+
// Clean up libdatadog object to avoid leaking in case ruby_time_from raises an exception
|
|
109
284
|
ddprof_ffi_SerializeResult_drop(serialized_profile);
|
|
110
285
|
|
|
111
286
|
VALUE start = ruby_time_from(ddprof_start);
|
|
112
287
|
VALUE finish = ruby_time_from(ddprof_finish);
|
|
113
288
|
|
|
114
|
-
if (!ddprof_ffi_Profile_reset(profile
|
|
289
|
+
if (!ddprof_ffi_Profile_reset(args.profile, NULL /* start_time is optional */ )) {
|
|
290
|
+
return rb_ary_new_from_args(2, error_symbol, rb_str_new_cstr("Failed to reset profile"));
|
|
291
|
+
}
|
|
115
292
|
|
|
116
293
|
return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(3, start, finish, encoded_pprof));
|
|
117
294
|
}
|
|
@@ -127,16 +304,21 @@ static VALUE ruby_time_from(ddprof_ffi_Timespec ddprof_time) {
|
|
|
127
304
|
}
|
|
128
305
|
|
|
129
306
|
void record_sample(VALUE recorder_instance, ddprof_ffi_Sample sample) {
|
|
130
|
-
|
|
131
|
-
TypedData_Get_Struct(recorder_instance,
|
|
307
|
+
struct stack_recorder_state *state;
|
|
308
|
+
TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
|
|
132
309
|
|
|
133
|
-
|
|
310
|
+
struct active_slot_pair active_slot = sampler_lock_active_profile(state);
|
|
311
|
+
|
|
312
|
+
ddprof_ffi_Profile_add(active_slot.profile, sample);
|
|
313
|
+
|
|
314
|
+
sampler_unlock_active_profile(active_slot);
|
|
134
315
|
}
|
|
135
316
|
|
|
136
317
|
static void *call_serialize_without_gvl(void *call_args) {
|
|
137
318
|
struct call_serialize_without_gvl_arguments *args = (struct call_serialize_without_gvl_arguments *) call_args;
|
|
138
319
|
|
|
139
|
-
args->
|
|
320
|
+
args->profile = serializer_flip_active_and_inactive_slots(args->state);
|
|
321
|
+
args->result = ddprof_ffi_Profile_serialize(args->profile, NULL /* end_time is optional */, NULL /* duration_nanos is optional */);
|
|
140
322
|
args->serialize_ran = true;
|
|
141
323
|
|
|
142
324
|
return NULL; // Unused
|
|
@@ -145,3 +327,95 @@ static void *call_serialize_without_gvl(void *call_args) {
|
|
|
145
327
|
void enforce_recorder_instance(VALUE object) {
|
|
146
328
|
Check_TypedStruct(object, &stack_recorder_typed_data);
|
|
147
329
|
}
|
|
330
|
+
|
|
331
|
+
static struct active_slot_pair sampler_lock_active_profile(struct stack_recorder_state *state) {
|
|
332
|
+
int error;
|
|
333
|
+
|
|
334
|
+
for (int attempts = 0; attempts < 2; attempts++) {
|
|
335
|
+
error = pthread_mutex_trylock(&state->slot_one_mutex);
|
|
336
|
+
if (error && error != EBUSY) rb_syserr_fail(error, "Unexpected failure during sampler_lock_active_profile for slot_one_mutex");
|
|
337
|
+
|
|
338
|
+
// Slot one is active
|
|
339
|
+
if (!error) return (struct active_slot_pair) {.mutex = &state->slot_one_mutex, .profile = state->slot_one_profile};
|
|
340
|
+
|
|
341
|
+
// If we got here, slot one was not active, let's try slot two
|
|
342
|
+
|
|
343
|
+
error = pthread_mutex_trylock(&state->slot_two_mutex);
|
|
344
|
+
if (error && error != EBUSY) rb_syserr_fail(error, "Unexpected failure during sampler_lock_active_profile for slot_two_mutex");
|
|
345
|
+
|
|
346
|
+
// Slot two is active
|
|
347
|
+
if (!error) return (struct active_slot_pair) {.mutex = &state->slot_two_mutex, .profile = state->slot_two_profile};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// We already tried both multiple times, and we did not succeed. This is not expected to happen. Let's stop sampling.
|
|
351
|
+
rb_raise(rb_eRuntimeError, "Failed to grab either mutex in sampler_lock_active_profile");
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
static void sampler_unlock_active_profile(struct active_slot_pair active_slot) {
|
|
355
|
+
int error = pthread_mutex_unlock(active_slot.mutex);
|
|
356
|
+
if (error != 0) rb_syserr_fail(error, "Unexpected failure in sampler_unlock_active_profile");
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
static ddprof_ffi_Profile *serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state) {
|
|
360
|
+
int error;
|
|
361
|
+
int previously_active_slot = state->active_slot;
|
|
362
|
+
|
|
363
|
+
if (previously_active_slot != 1 && previously_active_slot != 2) {
|
|
364
|
+
rb_raise(rb_eRuntimeError, "Unexpected active_slot state %d in serializer_flip_active_and_inactive_slots", previously_active_slot);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
pthread_mutex_t *previously_active = (previously_active_slot == 1) ? &state->slot_one_mutex : &state->slot_two_mutex;
|
|
368
|
+
pthread_mutex_t *previously_inactive = (previously_active_slot == 1) ? &state->slot_two_mutex : &state->slot_one_mutex;
|
|
369
|
+
|
|
370
|
+
// Release the lock, thus making this slot active
|
|
371
|
+
error = pthread_mutex_unlock(previously_inactive);
|
|
372
|
+
if (error) rb_syserr_fail(error, "Unexpected failure during serializer_flip_active_and_inactive_slots for previously_inactive");
|
|
373
|
+
|
|
374
|
+
// Grab the lock, thus making this slot inactive
|
|
375
|
+
error = pthread_mutex_lock(previously_active);
|
|
376
|
+
if (error) rb_syserr_fail(error, "Unexpected failure during serializer_flip_active_and_inactive_slots for previously_active");
|
|
377
|
+
|
|
378
|
+
// Update active_slot
|
|
379
|
+
state->active_slot = (previously_active_slot == 1) ? 2 : 1;
|
|
380
|
+
|
|
381
|
+
// Return profile for previously active slot (now inactive)
|
|
382
|
+
return (previously_active_slot == 1) ? state->slot_one_profile : state->slot_two_profile;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
|
386
|
+
// It SHOULD NOT be used for other purposes.
|
|
387
|
+
static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
|
|
388
|
+
struct stack_recorder_state *state;
|
|
389
|
+
TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
|
|
390
|
+
|
|
391
|
+
return INT2NUM(state->active_slot);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
|
395
|
+
// It SHOULD NOT be used for other purposes.
|
|
396
|
+
static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 1); }
|
|
397
|
+
|
|
398
|
+
// This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
|
|
399
|
+
// It SHOULD NOT be used for other purposes.
|
|
400
|
+
static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 2); }
|
|
401
|
+
|
|
402
|
+
static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
|
|
403
|
+
struct stack_recorder_state *state;
|
|
404
|
+
TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
|
|
405
|
+
|
|
406
|
+
pthread_mutex_t *slot_mutex = (slot == 1) ? &state->slot_one_mutex : &state->slot_two_mutex;
|
|
407
|
+
|
|
408
|
+
// Like Heisenberg's uncertainty principle, we can't observe without affecting...
|
|
409
|
+
int error = pthread_mutex_trylock(slot_mutex);
|
|
410
|
+
|
|
411
|
+
if (error == 0) {
|
|
412
|
+
// Mutex was unlocked
|
|
413
|
+
pthread_mutex_unlock(slot_mutex);
|
|
414
|
+
return Qfalse;
|
|
415
|
+
} else if (error == EBUSY) {
|
|
416
|
+
// Mutex was locked
|
|
417
|
+
return Qtrue;
|
|
418
|
+
} else {
|
|
419
|
+
rb_syserr_fail(error, "Unexpected failure when checking mutex state");
|
|
420
|
+
}
|
|
421
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#include <ddprof/ffi.h>
|
|
4
4
|
|
|
5
5
|
// Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `DDPROF_FFI_CHARSLICE_C`.
|
|
6
|
-
// `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.
|
|
6
|
+
// `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.2 CI test images)
|
|
7
7
|
// tripped when compiling `enabled_value_types` using `-std=gnu99` due to the extra cast that is included in
|
|
8
8
|
// `DDPROF_FFI_CHARSLICE_C` with the following error:
|
|
9
9
|
//
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# typed: ignore
|
|
2
2
|
|
|
3
3
|
if %w[1 true].include?((ENV['DD_APPSEC_ENABLED'] || '').downcase)
|
|
4
|
+
require_relative '../../ddtrace'
|
|
5
|
+
|
|
4
6
|
begin
|
|
5
|
-
|
|
7
|
+
require_relative '../appsec'
|
|
6
8
|
rescue StandardError => e
|
|
7
9
|
puts "AppSec failed to load. No security check will be performed. error: #{e.class.name} #{e.message}"
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
begin
|
|
11
|
-
|
|
13
|
+
require_relative 'contrib/auto_instrument'
|
|
12
14
|
Datadog::AppSec::Contrib::AutoInstrument.patch_all
|
|
13
15
|
rescue StandardError => e
|
|
14
16
|
puts "AppSec failed to instrument. No security check will be performed. error: #{e.class.name} #{e.message}"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# typed: false
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
require_relative '../../../instrumentation/gateway'
|
|
4
|
+
require_relative '../../../reactive/operation'
|
|
5
|
+
require_relative '../reactive/request'
|
|
6
|
+
require_relative '../reactive/request_body'
|
|
7
|
+
require_relative '../reactive/response'
|
|
8
|
+
require_relative '../../../event'
|
|
9
9
|
|
|
10
10
|
module Datadog
|
|
11
11
|
module AppSec
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# typed: ignore
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative '../integration'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
require_relative 'configuration/settings'
|
|
6
|
+
require_relative 'patcher'
|
|
7
|
+
require_relative 'request_middleware'
|
|
8
|
+
require_relative 'request_body_middleware'
|
|
9
9
|
|
|
10
10
|
module Datadog
|
|
11
11
|
module AppSec
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
require_relative '../../instrumentation/gateway'
|
|
6
|
+
require_relative '../../processor'
|
|
7
|
+
require_relative '../../assets'
|
|
8
8
|
|
|
9
9
|
module Datadog
|
|
10
10
|
module AppSec
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# typed: false
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
require_relative '../../../instrumentation/gateway'
|
|
4
|
+
require_relative '../../../reactive/operation'
|
|
5
|
+
require_relative '../reactive/action'
|
|
6
|
+
require_relative '../../../event'
|
|
7
7
|
|
|
8
8
|
module Datadog
|
|
9
9
|
module AppSec
|